def _downscale_image(self, image: Image) -> Image: scale_size = self._calculate_scaled_size(image.size) inv_scale_size = self._inverse_tuple(scale_size) scaled_pixels = cv2.resize(image._pixels, inv_scale_size, interpolation=cv2.INTER_LINEAR) return Image(scaled_pixels)
def init(self): """ Inicializa o buffer de desenho. """ self.buffer = wx.EmptyBitmap(*self.size) self.im = Image.new(self.size) self.update()
def main(): image_path = sys.argv[1] casc_path = sys.argv[2] image = Image(image_path) image_loaded = image.get_image() preprocessor = Preprocessor(image_loaded) image_processed = preprocessor.preprocess() detector = Detector(casc_path) faces = detector.detect(image_processed) print "Found {0} faces!".format(len(faces)) print "Faces: ", faces visualizer = Visualizer(image.get_image()) visualizer.viz(faces) cv2.waitKey(0)
def highpass_filter(image: Image, freq=10) -> Image: f = np.fft.fft2(image.src) f_shift = np.fft.fftshift(f) rows, cols = image.dimensions crow, ccol = int(rows / 2), int(cols / 2) f_shift[crow - freq:crow + freq, ccol - freq:ccol + freq] = 0 f_ishift = np.fft.ifftshift(f_shift) img_back = np.fft.ifft2(f_ishift) img_back = np.abs(img_back) return Image(np.uint8(img_back))
def call(self, photo_link) -> Image: self.corr_id = str(uuid.uuid4()) self.channel.basic_publish(exchange='', routing_key=INPUT_QUEUE_NAME, properties=pika.BasicProperties( reply_to=self.callback_queue, correlation_id=self.corr_id, ), body=photo_link) while self.response is None: self.connection.process_data_events() return Image.from_bytes(self.response)
def open_file(self, msg): file_name = PyQt5.QtWidgets.QFileDialog.getOpenFileName(self,'Open Image',' ', 'FITS Files (*.fits *.fit *.fts);;HDR Images (*.exr);;' 'Images (*.tiff *.tif *.png *.jpeg *.jpg *.bmp *.dib ' '*.jpe *.pbm *.pgm *.ppm *.sr *.ras *.jp2);;All (*)') if(file_name[0]): # Load the image from file print(file_name[0]) im=Image(file_name[0]) pixmap = PyQt5.QtGui.QPixmap.fromImage(im.toqimage()) #we add the image browsing widget sub = QMdiSubWindow(None, Qt.WindowShadeButtonHint) sub.setWindowTitle("Browse") label = QLabel() label.setPixmap(pixmap) sub.setWidget(label) self.mdiArea.addSubWindow(sub) workspace.add(sub) sub.show()
def sobreescreve(button, control, e): """ Callback para o clique do botão de teste. :param button Botão que foi clicado. :param control Controlador da página. :param e Dados do evento. """ control.soil = control.cane = False control.win.i_cane.SetValue(False) control.win.i_soil.SetValue(False) control.intest = True x0 = min(control.selected, key = lambda e: e.pos.x).pos.x y0 = min(control.selected, key = lambda e: e.pos.y).pos.y x1 = max(control.selected, key = lambda e: e.pos.x).pos.x y1 = max(control.selected, key = lambda e: e.pos.y).pos.y xdiff = x1 - x0 ydiff = y1 - y0 psize = control.parent.im.psize img = Image.new(((1 + xdiff) * psize.x, (1 + ydiff) * psize.y)) comm = SingleStage(high, segment) comm.event = False x = [[0,128,128]] y = [0] x = x + control.train[0] + control.train[1] y = y + [0] * len(control.train[0]) + [255] * len(control.train[1]) if len(x) > 2: with open('patchtrain.csv','w') as f: for i in range(len(x)): tstr = ' '.join(map(str,x[i])) + ' '+ str(y[i])+'\n' f.write(tstr) for elem in control.selected: comm.push(patch = elem[0], pos = elem.pos) pwork = PatchWork(control.parent.im.psize, img) pwork.shred(0) control.last = control.sp.im control.sp.im = pwork update(control, control.win.canvas) while comm.pendent: data = comm.pop() pwork.access(data.pos - control.diff).sew(data.image.colorize()) update(control, control.win.canvas)
def resize_and_copy(src_path, dst_path): # Lazy copy if cfg.lazy_copy and exists(dst_path): return # Resize and Save elif cfg.photo_resize: rim = image_resize(Image.open(src_path), cfg.photo_resize_horizontal_max_size, cfg.photo_resize_vertical_max_size) rim.save(dst_path) # Just copy else: copy2(src_path, dst_path)
def initimage(self, fname): """ Inicializa a imagem a ser processada por essa página. :param fname Caminho do arquivo a ser aberto. """ img = Image.load(fname) self.im = LayeredPatchWork((200, 200), img, img.swap(), img.swap(), img.swap()) self.sp = SelectionSpectator(self.im, self.im.psize, self.pg.canvas.size) self.pg.canvas.set(self.sp) self.pg.address = fname self.sp.update() self.pg.canvas.update() self.ex = Algorithm(self.im) self.patchcount = len(self.ex.patch) print "Quantidade de retalhos:", self.patchcount self.pg.r_patch.SetLabel("0/" + str(self.patchcount))
def load_from_dir(cls, dir_path: str, face_detector: FaceDetector, marks_detector: FaceMarksDetector) -> 'MasksLibrary': def get_mask_name_from(file_path: str) -> str: name = os.path.basename(file_path) name = os.path.splitext(name)[0] return name new_lib = MasksLibrary() image_paths = [os.path.join(dir_path, f) for f in os.listdir(dir_path)] for image_path in image_paths: try: image = Image.from_file(image_path) name = get_mask_name_from(image_path) mask = Mask.from_image(image, face_detector, marks_detector) new_lib[name] = mask except Exception as err: print(f"Error creating mask for {image_path}\nError: {err}") continue return new_lib
def generate(self): """ Cria uma imagem baseada nos elementos selecionados para segmentação avulsa. :return Image """ x0 = min(self.selected, key = lambda e: e.pos.x).pos.x y0 = min(self.selected, key = lambda e: e.pos.y).pos.y x1 = max(self.selected, key = lambda e: e.pos.x).pos.x y1 = max(self.selected, key = lambda e: e.pos.y).pos.y xdiff = x1 - x0 ydiff = y1 - y0 psize = self.parent.im.psize self.diff = Point(x0, y0) img = Image.new(((1 + xdiff) * psize.x, (1 + ydiff) * psize.y)) pwork = PatchWork(psize, img) pwork.shred(0) for elem in self.selected: pwork.access((elem.pos - self.diff)).sew(elem[1]) return pwork
def generate(self): """ Cria uma imagem baseada nos elementos selecionados para segmentação avulsa. :return Image """ x0 = min(self.selected, key=lambda e: e.pos.x).pos.x y0 = min(self.selected, key=lambda e: e.pos.y).pos.y x1 = max(self.selected, key=lambda e: e.pos.x).pos.x y1 = max(self.selected, key=lambda e: e.pos.y).pos.y xdiff = x1 - x0 ydiff = y1 - y0 psize = self.parent.im.psize self.diff = Point(x0, y0) img = Image.new(((1 + xdiff) * psize.x, (1 + ydiff) * psize.y)) pwork = PatchWork(psize, img) pwork.shred(0) for elem in self.selected: pwork.access((elem.pos - self.diff)).sew(elem[1]) return pwork
def __init__(self, argv: list, argc: int): """ argv: ./__main__.py [SOURCE] [ALGORITHM] [MODE] [COMPRESSION] [OVERFLOW] [TARGET] argc: number of command line arguments Methods: validImageFile validExtension validCompression getValidInput saveLog run """ self.name = argv[0] self.validExt = (".jpg", ".jpeg", ".png", ".tif") self.initialized = False if argc == 2: print(self.usage() + "\n") elif argc == 1 or argc > 8: print(self.usage()) return print("Initializing...") self.imgName = None self.source = None self.path = None self.algorithm = None self.mode = None self.compression = None self.overflow = False self.shouldLog = False self.target = None self.resourcePath = os.path.join(os.getcwd(), "input") self.outputPath = os.path.join(os.getcwd(), "output") self.variances = { "low": 90., "medium": 95., "high": 99.99, } # parse cmd line arguments and get user input if argc >= 2: imgName = argv[1] self.source = argv[1] # will get changed to full path later if argc >= 3: self.algorithm = argv[2] if argc >= 4: self.mode = argv[3] if argc >= 5: self.compression = argv[4] if argc >= 6: try: self.overflow = bool(int(argv[5])) except: self.overflow = not bool( self.getValidInput( "\nAllow overflow?\n\t1) True\n\t2) False", int, valid={1, 2}) - 1) if argc >= 7: try: self.shouldLog = bool(int(argv[6])) except: self.shouldLog = not bool( self.getValidInput( "\nLog data?\n\t1) True\n\t2) False: ", int, valid={1, 2}) - 1) if argc == 8: self.target = argv[7] if not self.validExtension(self.target): self.target = self.getValidInput( "\nInput valid target file name: ", str, isValid=self.validExtension) if self.source is None or not self.validImageFile( self.source): # get valid image file name available = os.listdir(self.resourcePath) if len(available) == 0: print( "No images in \"images\" folder. Add more and try again..." ) return options = "" for imageName in available: options += "\n\t- " + imageName self.source = self.getValidInput( "\nSelect valid file from \"images\" folder." + options, str, isValid=self.validImageFile) self.path = os.path.join(self.resourcePath, self.source) self.imgName = "" for l in imgName: if l != ".": self.imgName += l else: break self.image = Image(self.imgName, self.path) if self.algorithm is None or self.algorithm not in { "pca", "svd" }: # check which algorithm user wants to use choice = self.getValidInput( "\nWhich algorithm would you like to use?\n\t1) PCA\n\t2) SVD", int, valid={1, 2}) if choice == 1: self.algorithm = "pca" else: # choice == 2 self.algorithm = "svd" if self.mode is None or self.mode not in { "v", "c", "q" }: # check which mode user wants to use if self.algorithm == "pca": choice = self.getValidInput( "\nHow would you like to determine compression?\n\tv) Variance\n\tc) Component\n\tq) Qualitative", str, valid={"v", "c", "q"}) else: # self.algorithm == "svd" choice = "c" self.mode = choice if self.algorithm == "svd" and not self.mode == "c": print("Invalid mode for SVD: " + str(self.mode) + "\n\t- setting mode to \"c\", \"components\"") self.mode = "c" self.compression = None if self.compression is None or not self.validCompression( self.mode, self.compression): # get value for compression if self.mode == "v": # mode is variance choice = self.getValidInput( "\nHow much variance would you like to retain? (0, 100): ", float, lower=0, upper=100) elif self.mode == "c": # mode is components choice = self.getValidInput( "\nHow many components would you like to use? (0, " + str(self.image.data.shape[0]) + "): ", int, lower=0, upper=self.image.data.shape[0]) else: # mode is qualitative quality = { 1: "high", 2: "medium", 3: "low", } choice = quality[self.getValidInput( "\nHow much quality would you like?\n\t1) High\n\t2) Medium\n\t3) Low", int, valid={1, 2, 3})] self.compression = choice elif self.mode == "v": # compression passed through command line self.compression = float(self.compression) elif self.mode == "c": # compression passed through command line self.compression = int(self.compression) if self.mode == "q": self.compression = self.variances[self.compression] self.mode = "v" self.initialized = True
class Driver: def __init__(self, argv: list, argc: int): """ argv: ./__main__.py [SOURCE] [ALGORITHM] [MODE] [COMPRESSION] [OVERFLOW] [TARGET] argc: number of command line arguments Methods: validImageFile validExtension validCompression getValidInput saveLog run """ self.name = argv[0] self.validExt = (".jpg", ".jpeg", ".png", ".tif") self.initialized = False if argc == 2: print(self.usage() + "\n") elif argc == 1 or argc > 8: print(self.usage()) return print("Initializing...") self.imgName = None self.source = None self.path = None self.algorithm = None self.mode = None self.compression = None self.overflow = False self.shouldLog = False self.target = None self.resourcePath = os.path.join(os.getcwd(), "input") self.outputPath = os.path.join(os.getcwd(), "output") self.variances = { "low": 90., "medium": 95., "high": 99.99, } # parse cmd line arguments and get user input if argc >= 2: imgName = argv[1] self.source = argv[1] # will get changed to full path later if argc >= 3: self.algorithm = argv[2] if argc >= 4: self.mode = argv[3] if argc >= 5: self.compression = argv[4] if argc >= 6: try: self.overflow = bool(int(argv[5])) except: self.overflow = not bool( self.getValidInput( "\nAllow overflow?\n\t1) True\n\t2) False", int, valid={1, 2}) - 1) if argc >= 7: try: self.shouldLog = bool(int(argv[6])) except: self.shouldLog = not bool( self.getValidInput( "\nLog data?\n\t1) True\n\t2) False: ", int, valid={1, 2}) - 1) if argc == 8: self.target = argv[7] if not self.validExtension(self.target): self.target = self.getValidInput( "\nInput valid target file name: ", str, isValid=self.validExtension) if self.source is None or not self.validImageFile( self.source): # get valid image file name available = os.listdir(self.resourcePath) if len(available) == 0: print( "No images in \"images\" folder. Add more and try again..." ) return options = "" for imageName in available: options += "\n\t- " + imageName self.source = self.getValidInput( "\nSelect valid file from \"images\" folder." + options, str, isValid=self.validImageFile) self.path = os.path.join(self.resourcePath, self.source) self.imgName = "" for l in imgName: if l != ".": self.imgName += l else: break self.image = Image(self.imgName, self.path) if self.algorithm is None or self.algorithm not in { "pca", "svd" }: # check which algorithm user wants to use choice = self.getValidInput( "\nWhich algorithm would you like to use?\n\t1) PCA\n\t2) SVD", int, valid={1, 2}) if choice == 1: self.algorithm = "pca" else: # choice == 2 self.algorithm = "svd" if self.mode is None or self.mode not in { "v", "c", "q" }: # check which mode user wants to use if self.algorithm == "pca": choice = self.getValidInput( "\nHow would you like to determine compression?\n\tv) Variance\n\tc) Component\n\tq) Qualitative", str, valid={"v", "c", "q"}) else: # self.algorithm == "svd" choice = "c" self.mode = choice if self.algorithm == "svd" and not self.mode == "c": print("Invalid mode for SVD: " + str(self.mode) + "\n\t- setting mode to \"c\", \"components\"") self.mode = "c" self.compression = None if self.compression is None or not self.validCompression( self.mode, self.compression): # get value for compression if self.mode == "v": # mode is variance choice = self.getValidInput( "\nHow much variance would you like to retain? (0, 100): ", float, lower=0, upper=100) elif self.mode == "c": # mode is components choice = self.getValidInput( "\nHow many components would you like to use? (0, " + str(self.image.data.shape[0]) + "): ", int, lower=0, upper=self.image.data.shape[0]) else: # mode is qualitative quality = { 1: "high", 2: "medium", 3: "low", } choice = quality[self.getValidInput( "\nHow much quality would you like?\n\t1) High\n\t2) Medium\n\t3) Low", int, valid={1, 2, 3})] self.compression = choice elif self.mode == "v": # compression passed through command line self.compression = float(self.compression) elif self.mode == "c": # compression passed through command line self.compression = int(self.compression) if self.mode == "q": self.compression = self.variances[self.compression] self.mode = "v" self.initialized = True def usage(self) -> str: return f"""\ {"o"+"="*85+"o"} {"IMAGE COMPRESSOR!!!"} Runs lossy image compression on images with choice parameters. Usage: {self.name} [SOURCE] [ALGORITHM] [MODE] [COMPRESSION] [OVERFLOW] [TARGET] {self.name} [SOURCE] [ALGORITHM] [MODE] [COMPRESSION] [OVERFLOW] {self.name} [SOURCE] [ALGORITHM] [MODE] [COMPRESSION] {self.name} [SOURCE] [ALGORITHM] [MODE] {self.name} [SOURCE] Note: If the former is used, user will complete parameters through terminal Run image compression on image with valid extension: {self.validExt} Algorithms: pca: Principal Component Analysis svd: Singular Value Decomposition Modes: v: Select a percentage of variance to keep. Only valid if mode=pca. c: Select a number of components to keep. q: Select compression level from predefined settings. Only valid if mode=pca. Compression ranges: Given mode... v -> float between 0 and 100 c -> int q -> Either low, medium, or high quality Overflow: 1: True, values of pixels on one or more channels may overflow, resulting in cool noise 0: False, prevent cool noise but retain maximum image quality Optional Log: 1: True, log data to logs/ 0: False do not log data to logs/ Optional Target: file name: name with valid extension which will be saved to "output" folder Optional Examples: {self.name} tiger.jpg pca 1 95 1 0 tiger_pca_v_95.tif {self.name} flower.jpg svd 3 min 1 {self.name} knight.png {"o"+"="*85+"o"}""" def validImageFile(self, fileName: str) -> bool: """ Determine whether image file is in "input" folder and whether it has a proper extension fileName: name of file w/o full path Returns: True/ False """ availableImages = os.listdir(self.resourcePath) exists = fileName in availableImages extValid = self.validExtension(fileName) return exists and extValid def validExtension(self, fileName: str) -> bool: """ Determine whether image file has proper extension fileName: name of file w/o full path Returns: True/ False """ extValid = False for ext in self.validExt: if ext in fileName: valid = True for i in range(1, len(ext) + 1): if fileName[-1 * i] != ext[-1 * i]: valid = False if valid: return True return False def validCompression(self, mode: str, compression: int or float or str) -> bool: """ Determines whether "compression" value is valid given "mode" parameter mode: mode to use, either "v", "v", or "q" compression: degree of compression associated with mode Returns: True/ False """ if mode == "v": try: return (0 <= float(compression) <= 100) except ValueError: return False elif mode == "c": try: return (0 <= int(compression) <= self.image.data.shape[0]) except ValueError: return False else: # mode == q return compression in {"low", "medium", "high"} def getValidInput(self, msg: str, dtype: any, lower: float = None, upper: float = None, valid: set = None, isValid: callable = None) -> any: """ Gets input from user contrained by parameters msg: message to print out to user requesting input dtype: type that input will get converted to lower: numerical lower bound upper: numerical upper bound valid: set of possible valid inputs isValid: function returning bool to determine if input is valid Returns: valid input """ print(msg) while True: try: choice = dtype(input("\nChoice: ")) except ValueError: continue if (lower is not None and choice < lower) or \ (upper is not None and choice > upper) or \ (valid is not None and choice not in valid) or \ (isValid is not None and not isValid(choice)): continue return choice def saveLog(self, name: str, data: list): """ Save log data to text file in "logs" folder name: name of log data: data to write to log file """ path = "logs/" + name + ".txt" f = open(path, "w+") print("Writing log files to " + path) for pt in data: f.write(str(pt[0]) + " " + str(pt[1]) + "\n") f.close() def run(self): """ Run compression, handle saving image and logging data. """ if not self.initialized: return logs = self.image.compress(self.algorithm, self.mode, self.compression, overflow=self.overflow) print() if self.shouldLog: for channel, log in logs.items(): name = self.image.name + "_" + self.algorithm + "_" + self.mode + "_" + str( self.compression).replace(".", "-") + "_" + channel + "_" + str( int(self.overflow)) self.saveLog(name, log) if self.target is not None: path = os.path.join(self.outputPath, self.target) self.image.save(path) else: print("\nShowing image...") self.image.show()
def __init__(self, origin_image: Image, mask_marks: FaceMarks): self._cached_image = origin_image.read() self._mask_marks = mask_marks
def histogram_equalization(img: Image) -> Image: # create a CLAHE object (Arguments are optional). clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(2, 2)) equalized = clahe.apply(img.grayscale) return Image(equalized)
def laplacian_gradient(image: Image): tmp = cv2.Laplacian(image.src, cv2.CV_64F) tmp = np.absolute(tmp) return Image(np.uint8(tmp))
def _merge_to_image(image, layers) -> Image: background = image.as_layer() for top_layer in layers: background = background.apply(top_layer) return Image.from_layer(background)
class Control(BaseControl): """ Controla e administra a execução de uma página de processamento de imagens da interface gráfica através dos eventos disparados. """ _init = Image.load("{0}/img/dginit.png".format(root)) _over = Image.load("{0}/img/dgover.png".format(root)) _wait = Image.load("{0}/img/dgwait.png".format(root)) def __init__(self, parent, main=False): """ Inicializa uma nova instância. :param parent Controlador superior na hierarquia. :param main A página a ser controlada é inicial? :return Control """ BaseControl.__init__(self, parent) self.main = main self.selected = set() self.result = {} def bind(self, page): """ Vincula uma página ao controlador. :param page Página a ser vinculada. """ self.pg = page self.initmain() if self.main else self.waitprocess() Event("DropEnter", self.pg.canvas).bind(self.enter) Event("DropLeave", self.pg.canvas).bind(self.leave) Event("DropFiles", self.pg.canvas).bind(self.drop) if not self.main: Event(wx.EVT_TOGGLEBUTTON, self.pg.l_g).bind(e.grid, self) Event(wx.EVT_TOGGLEBUTTON, self.pg.l_1).bind(e.layer, self) Event(wx.EVT_TOGGLEBUTTON, self.pg.l_2).bind(e.layer, self) Event(wx.EVT_TOGGLEBUTTON, self.pg.l_3).bind(e.layer, self) Event(wx.EVT_BUTTON, self.pg.s_done).bind(e.deselect, self) Event(wx.EVT_BUTTON, self.pg.s_add).bind(e.addresult, self) Event(wx.EVT_BUTTON, self.pg.s_del).bind(e.delresult, self) Event(wx.EVT_BUTTON, self.pg.s_fsg).bind(e.patchsegment, self) Event(wx.EVT_BUTTON, self.pg.a_run).bind(e.run, self) Event(wx.EVT_BUTTON, self.pg.a_stop).bind(e.end, self) Event(wx.EVT_MOTION, self.pg.canvas).bind(self.mMotion) Event(wx.EVT_MOUSEWHEEL, self.pg.canvas).bind(self.mWheel) Event(wx.EVT_LEFT_DOWN, self.pg.canvas).bind(self.lDown) Event(wx.EVT_LEFT_UP, self.pg.canvas).bind(self.lUp) Event("Click", self.pg.canvas).bind(e.select, self) Event("ImageSegmented").bind(e.segmented) Event("ImageProcessed").bind(e.processed) def initmain(self): """ Mostra na página o campo de drag-n-drop. Esse campo é preenchido com uma imagem inicial que instrui o usuário a inicializar um processamento. """ for elem in [ self.pg.s_done, self.pg.s_add, self.pg.s_del, self.pg.s_fsg, self.pg.s_txt, self.pg.l_g, self.pg.l_1, self.pg.l_2, self.pg.l_3, self.pg.a_run, self.pg.a_stop ]: elem.Disable() self.pg.canvas.set(self._init) def waitprocess(self): """ Mostra na página uma mensagem de aguardo. Essa imagem somente será mudada quando uma imagem for enviada para essa página. """ self.pg.canvas.set(self._wait) self.pg.l_3.SetValue(True) @ThreadWrapper def initimage(self, fname): """ Inicializa a imagem a ser processada por essa página. :param fname Caminho do arquivo a ser aberto. """ img = Image.load(fname) self.im = LayeredPatchWork((200, 200), img, img.swap(), img.swap(), img.swap()) self.sp = SelectionSpectator(self.im, self.im.psize, self.pg.canvas.size) self.pg.canvas.set(self.sp) self.pg.address = fname self.sp.update() self.pg.canvas.update() self.ex = Algorithm(self.im) self.patchcount = len(self.ex.patch) print "Quantidade de retalhos:", self.patchcount self.pg.r_patch.SetLabel("0/" + str(self.patchcount)) def enter(self, canvas): """ Callback para o evento DropEnter. :param canvas Campo de drag-n-drop. """ self._prev = canvas.set(self._over) def leave(self, canvas): """ Callback para o evento DropLeave. :param canvas Campo de drag-n-drop. """ canvas.set(self._prev) def drop(self, canvas, fnames): """ Callback para o evento DropLeave. :param canvas Campo de drag-n-drop. :param fnames Arquivos a serem processados. """ for fn in fnames: newpg = Event("NewPage", self.parent.win.book).post(self.pg) newpg.initimage(fn) self.leave(canvas) def mMotion(self, canvas, e): """ Callback para o evento de mouse MOTION. :param canvas Campo de exibição de imagens :param e Dados do evento. """ if e.LeftIsDown(): self._move = self._move + 1 diff = self._mstart - (e.x, e.y) canvas.im.move(self._mark, *diff) canvas.update() def mWheel(self, canvas, e): """ Callback para o evento de mouse MOUSEWHEEL. :param canvas Campo de exibição de imagens :param e Dados do evento. """ self._mark = canvas.im.mark() diff = e.GetWheelRotation() // e.GetWheelDelta() canvas.im.zoom(self._mark, diff * 45) canvas.im.update() canvas.update() def lDown(self, canvas, e): """ Callback para o evento de mouse LEFT_DOWN. :param canvas Campo de exibição de imagens :param e Dados do evento. """ self._mstart = Point(e.GetX(), e.GetY()) self._mark = canvas.im.mark() self._move = 0 e.Skip() def lUp(self, canvas, e): """ Callback para o evento de mouse LEFT_UP. :param canvas Campo de exibição de imagens :param e Dados do evento. """ if self._move <= 3: Event("Click", canvas).post(self._mstart)
def _upscale_image(self, image: Image, original_size: tuple) -> Image: inv_size = self._inverse_tuple(original_size) upscaled_pixels = cv2.resize(image._pixels, inv_size, interpolation=cv2.INTER_LANCZOS4) return Image(upscaled_pixels)