Zkoušel jsem napsat metodu ke třídě ColorPicker, která by umožnila provést autosize... Zatím to má fungovat tak, že pokud hnete oknem mimo obrazovku, zvětší se okno i s grafem. Tím se dosáhne zvětšení obrázků (testováno s 800x600), které jinak zůstávají poměrně malé. ImageHandler je třída, která umožní implementovat kód, aby to něco dělalo. Původně se mělo kliknout na ax1 a obrázek se měl zmenšit ale velikost grafu ax1 zůstala stejná. Myslím že teď to negunguje, ale to není podstatné.
Zdá se mi, že autosize_... nefunguje v ten správný okamžik, bylo by lépe, kdyby se provedl autosize až po kliknutí na obrázek, při změně velikosti.
Myslím že chyba je že dpi = self.ppi je asi 96 ať to dám na maximální rozlišení nebo na 800x600. Mám 24" monitor. Původně jsem měl pevně nastavenou velikost monitoru naměřený rozměr a z toho jsem zjišťoval dpi. A to fungovalo lépe. DPI bylo buď 38 nebo 96 podle toho jak jsem nastavil rozlišení. Zdá se, že subprocess vrací vždy 96, ale to dělá normálně:
$ xdpyinfo | grep -B 2 resolution
screen #0:
dimensions: 800x600 pixels (212x159 millimeters)
resolution: 96x96 dots per inch
user@Toshi:~$
No já si myslím, že je to dpi špatně, protože při malém rozlišení 800x600 budou dvě dpi a bude to ta menší hodnota těch cca 38
$ xdpyinfo | grep -B 2 resolution
screen #0:
dimensions: 1920x1080 pixels (508x286 millimeters)
resolution: 96x96 dots per inch
V podstatě mě zajímaj vaše krátké poznámky nebo upozornění na chybu v logice. Možná to nedělá vůbec co si myslím že to dělá, to já se obávám. Asi chápu proč to autoři matlablib neintegrovali, protože chtěli aby to nebylo závislé na externích příkazech jako subprocessy apod.
# Předchozí verze: skript hierarchie-problem-2.py # Oproti staré verzi přibyl výpočet dpi a velikosti # grafu. Zatím není jasné, zda velikost grafu půjde zvětšit # a zbavit se nežádoucích mezer pod grafem nebo vpravo vedle # grafu. # # Tento kód je připraven jako OOP # Při dotazu na ChatGPT jsem v první verzi kladl důraz na: # 1) převod kódu do třídy # 2) hierarchii a strukturu jako při Objektově Orientovaném Programování # 3) převod kódu z main() do metod a změnu obsluhy handlaru pro události klik na graf # jehož chyba byla v nesprávném handleru # # V nové verzi je třeba odladit a dokonfigurovat metodu # autosize_horizontal_axes
# # Slidery nejsou na správném místě - je to bug. Chtěl bych # aby tam nebyla ta velká mezera pod grafem a zbavit se i # té mezery vedle.import cv2 import matplotlib.pyplot as plt import numpy as np from matplotlib.widgets import RangeSlider import configparser import subprocess # nutné pro zjištění dpi obrazovky # import pyautogui class ImageHandler: def __init__(self): self.original_image = None self.zoomed_image = None self.hsv_zoomed_image_copy = None self.mask = None self.masked_image = None def load_image(self): try: filename = self.load_filename() except KeyError: filename = "" self.save_filename(filename) print("Loading image:", filename) self.original_image = cv2.cvtColor(cv2.imread(filename), cv2.COLOR_BGR2RGB) self.zoomed_image = cv2.cvtColor(cv2.imread(filename), cv2.COLOR_BGR2RGB) self.hsv_zoomed_image_copy = cv2.cvtColor(self.zoomed_image, cv2.COLOR_RGB2HSV) self.mask = np.ones_like(self.zoomed_image[:, :, 0], dtype=np.uint8) * 255 self.masked_image = np.copy(self.zoomed_image) def save_filename(self, filename): config = configparser.ConfigParser() config['DEFAULT'] = {'filename': filename} with open('config.cfg', 'w') as configfile: config.write(configfile) def load_filename(self): config = configparser.ConfigParser() config.read('config.cfg') return config['DEFAULT']['filename'] def process_image(self, event, ax, color_picker_instance): new_height = int(color_picker_instance.fig_manager.window.geometry().split("+")[0].split("x")[1]) if new_height > 50: color_picker_instance.window_height = new_height if event.inaxes == ax: try: if self.original_image is not None: print("self.original_image obsahuje obrazová data") if self.zoomed_image is not None: image_to_resize = self.zoomed_image else: image_to_resize = self.original_image self.zoomed_image = cv2.resize(image_to_resize, (0, 0), fx=0.5, fy=0.5) image_to_resize = None print("Nové rozměry zmenšeného obrázku:", self.zoomed_image.shape) ax.imshow(self.zoomed_image) plt.draw() else: print("original_image neobsahuje obrazová data") except Exception as e: print(f"Chyba při zpracování obrázku: {e}") class ColorPicker(ImageHandler): def __init__(self): super().__init__() self.fig = None self.ppi = 0 self.window_height = None self.desktop_w_inches = 0 self.desktop_h_inches = 0 self.ax_sizes = {'ax1': {'w': 0, 'h': 600}, 'ax2': {'w': 0, 'h': 0}} self.fig_manager = None self.cid = None # ID události on_mouse_move self.mm = 0.0393701 def on_mouse_move(self, event): self.window_height = int(self.fig_manager.window.geometry().split("+")[0].split("x")[1]) if self.window_height > 800: self.fig.canvas.mpl_disconnect(self.cid) def get_dpi_and_screen_size(self): xdpyinfo = subprocess.Popen(('xdpyinfo'), stdout=subprocess.PIPE) self.output = subprocess.check_output(('grep', '-B', '2', 'resolution'), stdin=xdpyinfo.stdout) xdpyinfo.wait() screen_width = None screen_height = None dpi = None for line in self.output.decode().split('\n'): if 'dimensions' in line: dimensions = line.split(':')[-1].strip().split('x') screen_width = int(dimensions[0]) screen_height = int(dimensions[1].split(" ")[0]) elif 'resolution' in line: resolution = line.split(':')[-1].strip().split('x') dpi = int(resolution[0]) return dpi, screen_width, screen_height def create_figure(self, screen_width, screen_height): self.ppi = self.dpi self.desktop_w_inches = screen_width / self.dpi self.desktop_h_inches = screen_height / self.dpi self.fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(self.desktop_w_inches, self.desktop_h_inches), dpi=self.dpi) self.load_image() plt.subplots_adjust(left=0.045, bottom=0.095, hspace=0, wspace=0.070) ax1.imshow(self.zoomed_image) ax2.imshow(self.masked_image) self.fig_manager = plt.get_current_fig_manager() def autosize_horizontal_axes(self, ax=None, reset_both=False): if self.ax_sizes == None: self.ax_sizes = {'ax1': {'w': 0, 'h': 600}, 'ax2': {'w': 0, 'h': 0}} # ÚDAJE O VELIKOSTI CANVASU (JE MENŠÍ NEŽ PLOCHA DESKTOP) canvas_width_pixels, canvas_height_pixels = plt.gcf().canvas.get_width_height() canvas_width_inches = canvas_width_pixels * self.ppi canvas_height_inches = canvas_height_pixels * self.ppi canvas_width_inches = plt.rcParams['figure.figsize'][0] canvas_height_inches = plt.rcParams['figure.figsize'][1] # ÚDAJE O VELIKOSTI PLOCHY DESKTOP # screen_width, screen_height = pyautogui.size() print(self.desktop_w_inches) print(self.desktop_h_inches) # get dimention values if not ax: ax=plt.gca() xmin, ymin, xmax, ymax = ax.bbox.bounds bb = ax.get_window_extent().bounds inch_per_px = 1 / self.ppi w=ax.bbox.width/self.ppi h=ax.bbox.height/self.ppi if self.window_height != None: client_height = self.window_height client_height_inches = self.window_height / self.ppi else: client_height = self.desktop_h_inches*self.ppi # první volání if self.ax_sizes['ax1']['w'] == 0: self.ax_sizes['ax1']['w']=w self.ax_sizes['ax1']['h']=h else: # druhé volání if self.ax_sizes['ax2']['w'] == 0: self.ax_sizes['ax2']['w']=w self.ax_sizes['ax2']['h']=h space_horizontal = abs(self.desktop_w_inches-self.ax_sizes['ax1']['w']-self.ax_sizes['ax2']['w']) # This is calculated from one line of axis of two columns max_vs=max(self.ax_sizes['ax1']['h'],self.ax_sizes['ax2']['h']) space_vertical = abs(self.desktop_h_inches-max_vs) # Estimation of the space for enlargement pdl2=space_horizontal/2 pdb2=space_vertical/2 h_ratio = self.ax_sizes['ax1']['w']/pdl2 v_ratio = self.ax_sizes['ax1']['h']/pdb2 enlarge_w1 = (self.ax_sizes['ax1']['w']+v_ratio) enlarge_h1 = self.ax_sizes['ax1']['h']+h_ratio enlarge_w2 = (self.ax_sizes['ax2']['w']+v_ratio) enlarge_h2 = self.ax_sizes['ax2']['h']+h_ratio # ww=round(w*self.ppi) # hh=round(h*self.ppi) # figw = float(w)/(r-l) # figh = float(h)/(t-b) ax.figure.get_axes()[0].figure.set_size_inches(enlarge_w1, enlarge_h1) ax.figure.set_size_inches(enlarge_w2, enlarge_h2) self.ax_sizes['ax1']['w']=0 self.ax_sizes['ax1']['h']=0 if reset_both == True: self.ax_sizes['ax2']['w']=0 self.ax_sizes['ax2']['h']=0 def main(self): self.dpi, screen_width, screen_height = self.get_dpi_and_screen_size() self.create_figure(screen_width, screen_height) # Nastavení velikosti os podle slidů self.autosize_horizontal_axes(self.fig.axes[0]) self.autosize_horizontal_axes(self.fig.axes[1]) rslider_ax = self.fig.add_axes([0.20, 0.05, 0.60, 0.03]) rslider = RangeSlider(rslider_ax, "H", 0, 255, valinit=(0, 255)) gslider_ax = self.fig.add_axes([0.20, 0.01, 0.60, 0.03]) gslider = RangeSlider(gslider_ax, "S", 0, 255, valinit=(0, 255)) bslider_ax = self.fig.add_axes([0.20, -0.03, 0.60, 0.03]) bslider = RangeSlider(bslider_ax, "V", 0, 255, valinit=(0, 255)) self.fig.canvas.mpl_connect('button_press_event', lambda event: self.process_image(event, ax1, self)) self.cid = self.fig.canvas.mpl_connect('motion_notify_event', self.on_mouse_move) plt.show(block=False) runme = True while plt.fignum_exists(self.fig.number): w = plt.get_current_fig_manager().window subprocess.run(["xdotool", "windowactivate", "--name", "'Figure 1'", "windowmove", "75", "1"]) subprocess.run(["xdotool", "windowactivate", "--name", "'Figure 1'", "windowmove", "1", "1"]) # Získání výšky titulní lišty okna runme = False plt.pause(4000000) if __name__ == "__main__": picker = ColorPicker() picker.main()