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)
示例#2
0
 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)
示例#4
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))
示例#5
0
 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)
示例#6
0
文件: retina.py 项目: jromang/retina
    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()
示例#7
0
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)
示例#8
0
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)
示例#9
0
    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))
示例#10
0
    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
示例#11
0
    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))
示例#12
0
    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
示例#13
0
    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
示例#14
0
    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
示例#15
0
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()
示例#16
0
 def __init__(self, origin_image: Image, mask_marks: FaceMarks):
     self._cached_image = origin_image.read()
     self._mask_marks = mask_marks
示例#17
0
 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)
示例#18
0
 def laplacian_gradient(image: Image):
     tmp = cv2.Laplacian(image.src, cv2.CV_64F)
     tmp = np.absolute(tmp)
     return Image(np.uint8(tmp))
示例#19
0
 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)
示例#20
0
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)