예제 #1
0
    def build_speed_scale(self):
        """
        Construit la barre de reglage de la vitesse d'animation

        :return: Scale
        """
        speed_label = Label(self, text="Vitesse")
        speed_label.configure(font=font.Font(family=Config.FONT["main"],
                                             size=Config.SIZE["large"]),
                              background=Config.COLOR["main-bg"],
                              foreground=Config.COLOR["main-fg"])
        speed_label.grid(sticky='w', padx=10)

        scale = Scale(self,
                      from_=-1,
                      to=1,
                      resolution=0.1,
                      tickinterval=0.5,
                      command=self.on_move_scale)
        scale.configure(length=Config.LEFT_MENU_WIDTH - 10,
                        orient='horizontal',
                        font=font.Font(family=Config.FONT["main"],
                                       size=Config.SIZE["small"]),
                        background=Config.COLOR["main-bg"],
                        foreground=Config.COLOR["main-fg"],
                        activebackground=Config.COLOR["main-bg"],
                        troughcolor=Config.COLOR["main-fg"],
                        highlightthickness=0)
        scale.set(1)
        scale.grid(padx=10)

        return scale
예제 #2
0
class ipGUI:
    def __init__(self, master):
        self.master = master
        self.master.minsize(width=800, height=600)

        menu = Menu(self.master)
        master.config(menu=menu)

        # ***** Main Menu *****
        # *** file menu ***
        fileMenu = Menu(menu)
        menu.add_cascade(label='File', menu=fileMenu)
        fileMenu.add_command(label="Open", command=self.openImage)
        fileMenu.add_command(label="Load Blur Kernel", command=self.loadKernel)
        fileMenu.add_command(label="Save", command=self.saveImage)
        fileMenu.add_command(label="Exit", command=master.destroy)

        # *** edit menu ***
        editMenu = Menu(menu)
        menu.add_cascade(label='Space', menu=editMenu)
        editMenu.add_command(label="Histogram Equalization",
                             command=self.histWrap)
        editMenu.add_command(label="Gamma Correction",
                             command=self.gammaCorWrap)
        editMenu.add_command(label="Log Transform", command=self.logTranWrap)
        editMenu.add_command(label="Sharpen", command=self.sharpWrap)
        editMenu.add_command(label="Cartoonify", command=self.cartoonifyWrap)

        # *** blur menu ***
        blurMenu = Menu(editMenu)
        editMenu.add_cascade(label='Blur', menu=blurMenu)
        blurMenu.add_command(label="Box", command=self.boxBlurWrap)
        blurMenu.add_command(label="Gaussian", command=self.gaussianBlurWrap)
        blurMenu.add_command(label="Median", command=self.medianBlurWrap)

        # *** frequency filtering ***
        freqMenu = Menu(menu)
        menu.add_cascade(label='Frequency', menu=freqMenu)
        freqMenu.add_command(label="DFT", command=self.dftWrap)
        freqMenu.add_command(label="Load Mask", command=self.freqMaskWrap)

        # *** Mask Menu ***
        maskMenu = Menu(freqMenu)
        freqMenu.add_cascade(label='Create Mask', menu=maskMenu)
        maskMenu.add_command(label='Low Pass', command=self.lpmWrap)
        maskMenu.add_command(label='High Pass', command=self.hpmWrap)
        maskMenu.add_command(label='Band Pass', command=self.bppmWrap)
        maskMenu.add_command(label='Band Stop', command=self.bspmWrap)

        # *** frequency filtering ***
        restorationMenu = Menu(menu)
        menu.add_cascade(label='Restoration', menu=restorationMenu)
        restorationMenu.add_command(label="Full Inverse",
                                    command=self.fullInverseWrap)
        restorationMenu.add_command(label="Radially Limited Inverse",
                                    command=self.truncatedInverseWrap)
        restorationMenu.add_command(label="Approximate Weiner",
                                    command=self.approximateWeinerWrap)
        restorationMenu.add_command(label="Constrained LS",
                                    command=self.contrainedLSWrap)

        # ***** Toolbar *****
        toolbar = Frame(master, bg="grey")
        undoButton = Button(toolbar, text="Undo", command=self.undoFunc)
        undoButton.pack(side=LEFT)
        origButton = Button(toolbar, text="Original", command=self.origFunc)
        origButton.pack(side=LEFT)
        toolbar.pack(side=TOP, fill=X)

        # ***** Image Display Area *****
        self.frame = Frame(self.master)
        self.frame.pack()
        self.panel = Label(self.frame)
        self.panel.pack(padx=10, pady=10)
        self.img = None
        self.origImg = None
        self.prevImg = None

        # ***** Gamma Controls *****
        self.gammaFrame = Frame(self.master)
        self.gammaSlider = Scale(self.gammaFrame,
                                 from_=0.1,
                                 to=2,
                                 orient=HORIZONTAL,
                                 resolution=0.1)
        self.gammaSlider.pack(side=TOP)
        self.gammaExitButton = Button(self.gammaFrame,
                                      text="Exit",
                                      command=self.gammaFrame.pack_forget)
        self.gammaExitButton.pack(side=TOP)

        # ***** Box Blur Controls *****
        self.boxFrame = Frame(self.master)
        self.boxSlider = Scale(self.boxFrame, from_=1, to=5, orient=HORIZONTAL)
        self.boxSlider.pack(side=TOP)
        self.boxExitButton = Button(self.boxFrame,
                                    text="Exit",
                                    command=self.boxFrame.pack_forget)
        self.boxExitButton.pack(side=TOP)

        # ***** Truncated Inverse Controls *****
        self.truncatedInverseFrame = Frame(self.master)
        self.truncatedInverseSlider = Scale(self.truncatedInverseFrame,
                                            from_=-3,
                                            to=2,
                                            orient=HORIZONTAL,
                                            resolution=0.1)
        self.truncatedInverseSlider.pack(side=TOP)
        self.truncatedInverseExitButton = Button(
            self.truncatedInverseFrame,
            text="Exit",
            command=self.truncatedInverseFrame.pack_forget)
        self.truncatedInverseExitButton.pack(side=TOP)

        # ***** Weiner Controls *****
        self.weinerFrame = Frame(self.master)
        self.weinerSlider = Scale(self.weinerFrame,
                                  from_=-3,
                                  to=2,
                                  orient=HORIZONTAL,
                                  resolution=0.1)
        self.weinerSlider.pack(side=TOP)
        self.weinerExitButton = Button(self.weinerFrame,
                                       text="Exit",
                                       command=self.weinerFrame.pack_forget)
        self.weinerExitButton.pack(side=TOP)

        # ***** CLS Controls *****
        self.clsFrame = Frame(self.master)
        self.clsSlider = Scale(self.clsFrame,
                               from_=-3,
                               to=2,
                               orient=HORIZONTAL,
                               resolution=0.1)
        self.clsSlider.pack(side=TOP)
        self.clsExitButton = Button(self.clsFrame,
                                    text="Exit",
                                    command=self.clsFrame.pack_forget)
        self.clsExitButton.pack(side=TOP)

        # ***** DFT Display Area ******
        self.dftFrame = Frame(self.master)
        self.magPanel = Label(self.dftFrame)
        self.magPanel.pack(padx=10, pady=10, side=TOP)
        self.freqPanel = Label(self.dftFrame)
        self.freqPanel.pack(padx=10, pady=10, side=TOP)
        self.dftExitButton = Button(
            self.dftFrame,
            text="Exit",
            command=lambda: self.displayImg(np.array(self.img)))
        self.dftExitButton.pack(side=TOP, fill=X)

        # ***** Low Pass Mask Creation *****
        self.lpmFrame = Frame(self.master)
        self.lpmPanel = Label(self.lpmFrame)
        self.lpmPanel.pack(padx=10, pady=10, side=TOP)
        self.lpmSubButton = Button(self.lpmFrame, text="submit")
        self.lpmSubButton.pack(side=TOP)
        self.lpmExitButton = Button(
            self.lpmFrame,
            text="Exit",
            command=lambda: self.displayImg(np.array(self.img)))
        self.lpmExitButton.pack(side=TOP)
        self.lpmSlider = Scale(self.lpmFrame,
                               from_=1,
                               to=2,
                               orient=HORIZONTAL,
                               resolution=1)

        # ***** High Pass Mask Creation *****
        self.hpmFrame = Frame(self.master)
        self.hpmPanel = Label(self.hpmFrame)
        self.hpmPanel.pack(padx=10, pady=10, side=TOP)
        self.hpmSubButton = Button(self.hpmFrame, text="submit")
        self.hpmSubButton.pack(side=TOP)
        self.hpmExitButton = Button(
            self.hpmFrame,
            text="Exit",
            command=lambda: self.displayImg(np.array(self.img)))
        self.hpmExitButton.pack(side=TOP)
        self.hpmSlider = Scale(self.hpmFrame,
                               from_=1,
                               to=2,
                               orient=HORIZONTAL,
                               resolution=1)

        # ***** Band Pass Mask Creation *****
        self.bppmFrame = Frame(self.master)
        self.bppmPanel = Label(self.bppmFrame)
        self.bppmPanel.pack(padx=10, pady=10, side=TOP)
        self.bppmSubButton = Button(self.bppmFrame, text="submit")
        self.bppmSubButton.pack(side=TOP)
        self.bppmExitButton = Button(
            self.bppmFrame,
            text="Exit",
            command=lambda: self.displayImg(np.array(self.img)))
        self.bppmExitButton.pack(side=TOP)
        self.bppmSliderLow = Scale(self.bppmFrame,
                                   from_=1,
                                   to=2,
                                   orient=HORIZONTAL,
                                   resolution=1)
        self.bppmSliderHigh = Scale(self.bppmFrame,
                                    from_=1,
                                    to=2,
                                    orient=HORIZONTAL,
                                    resolution=1)

        # ***** Band Pass Mask Creation *****
        self.bspmFrame = Frame(self.master)
        self.bspmPanel = Label(self.bspmFrame)
        self.bspmPanel.pack(padx=10, pady=10, side=TOP)
        self.bspmSubButton = Button(self.bspmFrame, text="submit")
        self.bspmSubButton.pack(side=TOP)
        self.bspmExitButton = Button(
            self.bspmFrame,
            text="exit",
            command=lambda: self.displayImg(np.array(self.img)))
        self.bspmExitButton.pack(side=TOP)
        self.bspmSliderLow = Scale(self.bspmFrame,
                                   from_=1,
                                   to=2,
                                   orient=HORIZONTAL,
                                   resolution=1)
        self.bspmSliderHigh = Scale(self.bspmFrame,
                                    from_=1,
                                    to=2,
                                    orient=HORIZONTAL,
                                    resolution=1)

    def displayImg(self, img):
        # input image in RGB
        self.frame.pack()
        self.dftFrame.pack_forget()
        self.lpmFrame.pack_forget()
        self.hpmFrame.pack_forget()
        self.bppmFrame.pack_forget()
        self.bspmFrame.pack_forget()
        self.img = Image.fromarray(img)
        imgtk = ImageTk.PhotoImage(self.img)

        self.panel.configure(image=imgtk)
        self.panel.image = imgtk

    def openImage(self):
        # can change the image
        path = filedialog.askopenfilename()
        if len(path) > 0:
            imgRead = cv2.imread(path)
            if imgRead is not None:
                imgRead = cv2.cvtColor(imgRead, cv2.COLOR_BGR2RGB)
                self.origImg = Image.fromarray(imgRead)
                self.prevImg = Image.fromarray(imgRead)
                self.displayImg(imgRead)
            else:
                raise ValueError("Not a valid image")
        else:
            raise ValueError("Not a valid path")

    def loadKernel(self):
        path = filedialog.askopenfilename()
        if len(path) > 0:
            self.filter_kernel = np.mean(cv2.imread(path), axis=-1)
            self.filter_kernel = self.filter_kernel / np.sum(
                self.filter_kernel)
        else:
            raise ValueError("Not a valid path")

    def saveImage(self):
        if self.img is not None:
            toSave = filedialog.asksaveasfilename()
            self.img.save(toSave)
        else:
            messagebox.showerror(title="Save Error",
                                 message="No image to be saved!")

    def histWrap(self):
        img = np.array(self.img)
        self.prevImg = self.img
        imgNew = image_utils.histEqlFunc(img)
        self.displayImg(imgNew)

    # Gamma Correction
    def gammaCallback(self, event, img):
        gamma = self.gammaSlider.get()
        self.prevImg = self.img
        imgNew = image_utils.gammaCorFunc(img, 255.0 / (255.0**gamma), gamma)
        self.displayImg(imgNew)

    def truncatedInverseCallback(self, event, img):
        th = 10**self.truncatedInverseSlider.get()
        imgNew = self.truncatedInverseFilter(th)
        self.displayImg(imgNew)

    def weinerCallback(self, event, img):
        gamma = 10**self.weinerSlider.get()
        imgNew = self.weinerFilter(gamma)
        self.displayImg(imgNew)

    def clsCallback(self, event, img):
        K = 10**self.clsSlider.get()
        imgNew = self.clsFilter(K)
        self.displayImg(imgNew)

    def gammaCorWrap(self):
        img = np.array(self.img)
        self.gammaFrame.pack()
        self.gammaSlider.set(1.0)
        self.gammaSlider.bind(
            "<ButtonRelease-1>",
            lambda event, img=img: self.gammaCallback(event, img))

    def logTranWrap(self):
        img = np.array(self.img)
        self.prevImg = self.img
        imgNew = image_utils.logTranFunc(img, 255.0 / np.log10(256))
        self.displayImg(imgNew)

    def sharpWrap(self):
        # Sharpen Wrapper
        img = np.array(self.img)
        self.prevImg = self.img
        imgNew = image_utils.sharpFunc(img)
        self.displayImg(imgNew)

    def boxBlurWrap(self):
        # Box Blur Wrapper
        img = np.array(self.img)
        self.prevImg = self.img
        self.boxFrame.pack()
        self.boxSlider.set(1)
        self.boxSlider.bind("<ButtonRelease-1>",
                            lambda event, img=img: self.displayImg(
                                image_utils.boxBlurFunc(
                                    event, img, 2 * self.boxSlider.get() + 1)))

    def gaussianBlurWrap(self):
        # Gaussian Blur Wrapper
        img = np.array(self.img)
        self.prevImg = self.img
        imgNew = image_utils.gaussianBlurFunc(img)
        self.displayImg(imgNew)

    def medianBlurWrap(self):
        # Median Blur Wrapper
        img = np.array(self.img)
        self.prevImg = self.img
        imgNew = image_utils.medianBlurFunc(img)
        self.displayImg(imgNew)

    def cartoonifyWrap(self):
        img = np.array(self.img)
        self.prevImg = self.img
        imgNew = image_utils.cartoonifyFunc(img)
        self.displayImg(imgNew)

    def undoFunc(self):
        self.img = self.prevImg
        self.displayImg(np.array(self.img))

    def origFunc(self):
        self.prevImg = self.img
        self.img = self.origImg
        self.displayImg(np.array(self.img))

    def displayDFT(self, x_fft):
        m, n = x_fft.shape[:]
        self.frame.pack_forget()
        self.dftFrame.pack()

        x_mag = np.log10(np.absolute(x_fft)) * 255 / np.log10(m * n * 255)
        x_mag = Image.fromarray(x_mag)
        x_mag = x_mag.resize((min(256, m), min(int(256 * n / m), n)),
                             Image.ANTIALIAS)
        x_mag = ImageTk.PhotoImage(x_mag)

        x_freq = (np.angle(x_fft) % 360) * 255 / 360
        x_freq = Image.fromarray(x_freq)
        x_freq = x_freq.resize((min(256, m), min(int(256 * n / m), n)),
                               Image.ANTIALIAS)
        x_freq = ImageTk.PhotoImage(x_freq)

        self.magPanel.configure(image=x_mag)
        self.magPanel.image = x_mag

        self.freqPanel.configure(image=x_freq)
        self.freqPanel.image = x_freq

    def dftWrap(self):
        img = np.array(self.img)
        x = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        x_outp_img = fft.fft2d_img(x)
        self.displayDFT(x_outp_img)

    def freqMaskWrap(self):
        m, n = np.array(self.img).shape[:2]
        lm, ln = np.log2(m), np.log2(m)
        dm, dn = int(2**np.ceil(lm)) + 1, int(2**np.ceil(ln)) + 1
        messagebox.showinfo(
            "Mask Size",
            "Mask Size should be (" + str(dm) + "," + str(dn) + ")")
        path = filedialog.askopenfilename()
        if len(path) > 0:
            maskRead = cv2.imread(path, 0)
            if (maskRead.shape != (dm, dn)):
                messagebox.showerror(
                    title="Shape Error",
                    message="Shape of mask and image don't match")
            else:
                self.prevImg = self.img
                self.display(image_utils.freqMask(np.array(self.img),
                                                  maskRead))
        else:
            raise ValueError("Not a valid path")

    def maskWrap(self):
        img = np.array(self.img)
        x = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
        x_outp_img = fft.fft2d_img(x)
        x_mag = image_utils.xMagCreate(x_outp_img)

        return x_outp_img, x_mag

    def maskFinal(self, x_outp_img):
        self.prevImg = self.img
        img = np.array(self.img)
        img = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
        m = len(img)
        res = fft.ifft2d_img(x_outp_img)
        res = np.array(res * 255 / np.max(res), dtype=np.uint8)
        res = np.array([[[img[i][j][0], img[i][j][1], res[i][j]]
                         for j in range(m)] for i in range(m)])
        res = cv2.cvtColor(res, cv2.COLOR_HSV2RGB)
        self.displayImg(res)

    def lpmCallBack(self, event, slider, x_outp_img):
        m = len(x_outp_img)
        m2 = int((m - 1) / 2)
        r = slider.get()
        x_outp_copy = np.copy(x_outp_img)

        nCircle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(m)]
                            for i in range(m)])
        nCircle = np.where(nCircle > r**2)
        x_outp_copy[nCircle] = 1

        x_mag = image_utils.xMagCreate(x_outp_copy)

        self.lpmPanel.configure(image=x_mag)
        self.lpmPanel.image = x_mag

    def lpmFinal(self, x_outp_img):
        mx = len(x_outp_img)
        m2 = int((mx - 1) / 2)
        r = self.lpmSlider.get()
        nCircle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)]
                            for i in range(mx)])
        nCircle = np.where(nCircle > r**2)
        x_outp_img[nCircle] = 0

        self.maskFinal(x_outp_img)

    def lpmWrap(self):
        x_outp_img, x_mag = self.maskWrap()
        m = len(x_outp_img)

        self.lpmPanel.configure(image=x_mag)
        self.lpmPanel.image = x_mag

        self.lpmSlider.configure(to=int(np.ceil(m / 2)))
        self.lpmSlider.set(1)
        self.lpmSlider.pack(side=TOP)
        self.lpmSlider.bind(
            "<ButtonRelease-1>",
            lambda event, slider=self.lpmSlider, x_outp_img=x_outp_img: self.
            lpmCallBack(event, slider, x_outp_img))

        self.lpmSubButton.configure(
            command=lambda x_outp_img=x_outp_img: self.lpmFinal(x_outp_img))

        self.dftFrame.pack_forget()
        self.frame.pack_forget()
        self.hpmFrame.pack_forget()
        self.bppmFrame.pack_forget()
        self.bspmFrame.pack_forget()
        self.lpmFrame.pack()

    def hpmCallBack(self, event, slider, x_outp_img):
        mx = len(x_outp_img)
        m2 = int((mx - 1) / 2)
        r = slider.get()
        x_outp_copy = np.copy(x_outp_img)

        circle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)]
                           for i in range(mx)])
        circle = np.where(circle <= r**2)
        x_outp_copy[circle] = 1

        x_mag = image_utils.xMagCreate(x_outp_copy)

        self.hpmPanel.configure(image=x_mag)
        self.hpmPanel.image = x_mag

    def hpmFinal(self, x_outp_img):
        mx = len(x_outp_img)
        m2 = int((mx - 1) / 2)
        r = self.hpmSlider.get()
        circle = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)]
                           for i in range(mx)])
        circle = np.where(circle <= r**2)
        x_outp_img[circle] = 0

        self.maskFinal(x_outp_img)

    def hpmWrap(self):
        x_outp_img, x_mag = self.maskWrap()
        m = len(x_outp_img)

        self.hpmPanel.configure(image=x_mag)
        self.hpmPanel.image = x_mag

        self.hpmSlider.configure(to=m // 2)
        self.hpmSlider.set(1)
        self.hpmSlider.pack(side=TOP)
        self.hpmSlider.bind(
            "<ButtonRelease-1>",
            lambda event, slider=self.hpmSlider, x_outp_img=x_outp_img: self.
            hpmCallBack(event, slider, x_outp_img))

        self.hpmSubButton.configure(
            command=lambda x_outp_img=x_outp_img: self.hpmFinal(x_outp_img))

        self.dftFrame.pack_forget()
        self.frame.pack_forget()
        self.lpmFrame.pack_forget()
        self.bppmFrame.pack_forget()
        self.bspmFrame.pack_forget()
        self.hpmFrame.pack()

    def bppmCallBack(self, event, x_outp_img):
        mx = len(x_outp_img)
        m2 = int((mx - 1) / 2)
        r1 = self.bppmSliderLow.get()
        r2 = self.bppmSliderHigh.get()
        assert (r1 <= r2)

        self.bppmSliderLow.configure(to=r2)
        self.bppmSliderHigh.configure(from_=r1)

        x_outp_copy = np.copy(x_outp_img)
        allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)]
                            for i in range(mx)])
        nullVals = np.where(allVals < r1**2)
        x_outp_copy[nullVals] = 1
        nullVals = np.where(allVals > r2**2)
        x_outp_copy[nullVals] = 1

        x_mag = image_utils.xMagCreate(x_outp_copy)

        self.bppmPanel.configure(image=x_mag)
        self.bppmPanel.image = x_mag

    def bppmFinal(self, x_outp_img):
        mx = len(x_outp_img)
        m2 = int((mx - 1) / 2)
        r1 = self.bppmSliderLow.get()
        r2 = self.bppmSliderHigh.get()

        allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)]
                            for i in range(mx)])
        nullVals = np.where(allVals < r1**2)
        x_outp_img[nullVals] = 0
        nullVals = np.where(allVals > r2**2)
        x_outp_img[nullVals] = 0

        self.maskFinal(x_outp_img)

    def bppmWrap(self):
        x_outp_img, x_mag = self.maskWrap()
        m = len(x_outp_img)

        self.bppmPanel.configure(image=x_mag)
        self.bppmPanel.image = x_mag

        self.bppmSliderHigh.configure(from_=1)
        self.bppmSliderHigh.configure(to=m // 2)
        self.bppmSliderHigh.set(m // 2)
        self.bppmSliderHigh.pack(side=TOP)
        self.bppmSliderHigh.bind("<ButtonRelease-1>",
                                 lambda event, x_outp_img=x_outp_img: self.
                                 bppmCallBack(event, x_outp_img))

        self.bppmSliderLow.configure(from_=1)
        self.bppmSliderLow.configure(to=m // 2)
        self.bppmSliderLow.set(1)
        self.bppmSliderLow.pack(side=TOP)
        self.bppmSliderLow.bind("<ButtonRelease-1>",
                                lambda event, x_outp_img=x_outp_img: self.
                                bppmCallBack(event, x_outp_img))

        self.bppmSubButton.configure(
            command=lambda x_outp_img=x_outp_img: self.bppmFinal(x_outp_img))

        self.dftFrame.pack_forget()
        self.frame.pack_forget()
        self.lpmFrame.pack_forget()
        self.hpmFrame.pack_forget()
        self.bspmFrame.pack_forget()
        self.bppmFrame.pack()

    def bspmCallBack(self, event, x_outp_img):
        mx = len(x_outp_img)
        m2 = int((mx - 1) / 2)
        r1 = self.bspmSliderLow.get()
        r2 = self.bspmSliderHigh.get()
        assert (r1 <= r2)

        self.bspmSliderLow.configure(to=r2)
        self.bspmSliderHigh.configure(from_=r1)

        x_outp_copy = np.copy(x_outp_img)
        allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)]
                            for i in range(mx)])
        nullVals = np.where((allVals - r1**2) * (allVals - r2**2) < 0)
        x_outp_copy[nullVals] = 1

        x_mag = image_utils.xMagCreate(x_outp_copy)

        self.bspmPanel.configure(image=x_mag)
        self.bspmPanel.image = x_mag

    def bspmFinal(self, x_outp_img):
        mx = len(x_outp_img)
        m2 = int((mx - 1) / 2)
        r1 = self.bspmSliderLow.get()
        r2 = self.bspmSliderHigh.get()

        allVals = np.array([[(i - m2)**2 + (j - m2)**2 for j in range(mx)]
                            for i in range(mx)])
        nullVals = np.where((allVals - r1**2) * (allVals - r2**2) < 0)
        x_outp_img[nullVals] = 0

        self.maskFinal(x_outp_img)

    def bspmWrap(self):
        x_outp_img, x_mag = self.maskWrap()
        m = len(x_outp_img)

        self.bspmPanel.configure(image=x_mag)
        self.bspmPanel.image = x_mag

        self.bspmSliderHigh.configure(from_=1)
        self.bspmSliderHigh.configure(to=m // 2)
        self.bspmSliderHigh.set(m // 2)
        self.bspmSliderHigh.pack(side=TOP)
        self.bspmSliderHigh.bind("<ButtonRelease-1>",
                                 lambda event, x_outp_img=x_outp_img: self.
                                 bspmCallBack(event, x_outp_img))

        self.bspmSliderLow.configure(from_=1)
        self.bspmSliderLow.configure(to=m // 2)
        self.bspmSliderLow.set(1)
        self.bspmSliderLow.pack(side=TOP)
        self.bspmSliderLow.bind("<ButtonRelease-1>",
                                lambda event, x_outp_img=x_outp_img: self.
                                bspmCallBack(event, x_outp_img))

        self.bspmSubButton.configure(
            command=lambda x_outp_img=x_outp_img: self.bspmFinal(x_outp_img))

        self.dftFrame.pack_forget()
        self.frame.pack_forget()
        self.lpmFrame.pack_forget()
        self.hpmFrame.pack_forget()
        self.bppmFrame.pack_forget()
        self.bspmFrame.pack()

    def fullInverseWrap(self):
        img = np.array(self.img)
        self.prevImg = self.img
        imgNew = filtering.inverseFilter2D(img, self.filter_kernel)
        self.displayImg(imgNew)

    def truncatedInverseWrap(self):
        img = np.array(self.img)
        self.prevImg = self.img
        self.truncatedInverseFilter = filtering.getTruncatedInverseFilter2D(
            img, self.filter_kernel)
        self.truncatedInverseFrame.pack()
        self.truncatedInverseSlider.set(1.0)
        self.truncatedInverseSlider.bind(
            "<ButtonRelease-1>",
            lambda event, img=img: self.truncatedInverseCallback(event, img))

    def approximateWeinerWrap(self):
        img = np.array(self.img)
        self.prevImg = self.img
        self.weinerFilter = filtering.getApproximateWeinerFilter2D(
            img, self.filter_kernel)
        self.weinerFrame.pack()
        self.weinerSlider.set(1.0)
        self.weinerSlider.bind(
            "<ButtonRelease-1>",
            lambda event, img=img: self.weinerCallback(event, img))

    def contrainedLSWrap(self):  # TODO: implement
        img = np.array(self.img)
        self.prevImg = self.img
        self.clsFilter = filtering.getConstrainedLSFilter2D(
            img, self.filter_kernel)
        self.clsFrame.pack()
        self.clsSlider.set(1.0)
        self.clsSlider.bind(
            "<ButtonRelease-1>",
            lambda event, img=img: self.clsCallback(event, img))
예제 #3
0
class Gui:
    """
    This class is built to let the user have a better interaction with
    game.
    inputs =>
    root = Tk() => an object which inherits the traits of Tkinter class
    agent = an object which inherit the traits of mctsagent class.

    """

    agent_type = {1: "UCT", 2: "RAVE", 3: "LAST-GOOD-REPLY", 4: "POOLRAVE", 5: "DECISIVE-MOVE", 6: "UCB1-TUNED"}

    AGENTS = {"UCT": UctMctsAgent,
              "RAVE": RaveMctsAgent,
              "LAST-GOOD-REPLY": LGRMctsAgent,
              "POOLRAVE": PoolRaveMctsAgent,
              "DECISIVE-MOVE": DecisiveMoveMctsAgent,
              "UCB1-TUNED": UCB1TunedMctsAgent}

    def __init__(self, root, agent_name='UCT'):
        self.root = root
        self.root.geometry('1366x690+0+0')
        self.agent_name = agent_name
        try:
            self.agent = self.AGENTS[agent_name]()
        except KeyError:
            print("Unknown agent defaulting to basic")
            self.agent_name = "uct"
            self.agent = self.AGENTS[agent_name]()
        self.game = GameState(8)
        self.agent.set_gamestate(self.game)
        self.time = 1
        self.root.configure(bg='#363636')
        self.colors = {'white': '#ffffff',
                       'milk': '#e9e5e5',
                       'red': '#9c0101',
                       'orange': '#ee7600',
                       'yellow': '#f4da03',
                       'green': '#00ee76',
                       'cyan': '#02adfd',
                       'blue': '#0261fd',
                       'purple': '#9c02fd',
                       'gray1': '#958989',
                       'gray2': '#3e3e3e',
                       'black': '#000000'}
        global BG
        BG = self.colors['gray2']
        self.last_move = None
        self.frame_board = Frame(self.root)  # main frame for the play board
        self.canvas = Canvas(self.frame_board, bg=BG)
        self.scroll_y = ttk.Scrollbar(self.frame_board, orient=VERTICAL)
        self.scroll_x = ttk.Scrollbar(self.frame_board, orient=HORIZONTAL)

        # the notebook frame which holds the left panel frames

        self.notebook = ttk.Notebook(self.frame_board, width=350)
        self.panel_game = Frame(self.notebook, highlightbackground=self.colors['white'])
        self.developers = Frame(self.notebook, highlightbackground=self.colors['white'])

        # Registering variables for:

        self.game_size_value = IntVar()  # size of the board
        self.game_time_value = IntVar()  # time of CPU player
        self.game_turn_value = IntVar()  # defines whose turn is it

        self.switch_agent_value = IntVar()  # defines which agent to play against
        self.switch_agent_value.set(1)

        self.game_turn_value.set(1)
        self.turn = {1: 'white', 2: 'black'}

        self.game_size = Scale(self.panel_game)
        self.game_time = Scale(self.panel_game)
        self.game_turn = Scale(self.panel_game)
        self.generate = Button(self.panel_game)
        self.reset_board = Button(self.panel_game)

        self.switch_agent = Scale(self.panel_game)
        self.agent_show = Label(self.panel_game, font=('Calibri', 14, 'bold'), fg='white', justify=LEFT,
                                bg=BG, text='Agent Policy: ' + self.agent_name + '\n')

        self.hex_board = []
        # Holds the IDs of hexagons in the main board for implementing the click and play functions
        self.game_size_value.set(8)
        self.game_time_value.set(1)
        self.size = self.game_size_value.get()
        self.time = self.game_time_value.get()
        self.board = self.game.board
        self.board = int_(self.board).tolist()
        self.gameboard2hexagons(self.board)  # building the game board
        self.logo = PhotoImage(file='image/hex.png')
        self.uut_logo = PhotoImage(file='image/uut_2.png')
        self.generate_black_edge()
        self.generate_white_edge()

        # Frame_content

        self.frame_board.configure(bg=BG, width=1366, height=760)
        self.frame_board.pack(fill=BOTH)
        self.notebook.add(self.panel_game, text='       Game       ')
        self.notebook.add(self.developers, text='    Developers    ')
        self.notebook.pack(side=LEFT, fill=Y)
        self.canvas.configure(width=980, bg=BG, cursor='hand2')
        self.canvas.pack(side=LEFT, fill=Y)
        self.canvas.configure(yscrollcommand=self.scroll_y.set)
        self.scroll_y.configure(command=self.canvas.yview)
        self.scroll_x.configure(command=self.canvas.xview)
        self.scroll_y.place(x=387, y=482)
        self.scroll_x.place(x=370, y=500)

        # Frame_left_panel

        """
        the left panel notebook ---->   Game

        """
        self.panel_game.configure(bg=BG)
        Label(self.panel_game, text='Board size',
              font=('Calibri', 14, 'bold'),
              foreground='white', bg=BG, pady=10).pack(fill=X, side=TOP)  # label ---> Board size
        self.game_size.configure(from_=3, to=20, tickinterval=1, bg=BG, fg='white',
                                 orient=HORIZONTAL, variable=self.game_size_value)
        self.game_size.pack(side=TOP, fill=X)
        Label(self.panel_game, text='Time',
              font=('Calibri', 14, 'bold'),
              foreground='white', bg=BG, pady=10).pack(side=TOP, fill=X)  # label ---> Time
        self.game_time.configure(from_=1, to=20, tickinterval=1, bg=BG, fg='white',
                                 orient=HORIZONTAL, variable=self.game_time_value)
        self.game_time.pack(side=TOP, fill=X)
        Label(self.panel_game, text='Player',
              font=('Calibri', 14, 'bold'),
              foreground='white', bg=BG, pady=10).pack(side=TOP, fill=X)  # label ---> Turn
        self.game_turn.configure(from_=1, to=2, tickinterval=1, bg=BG, fg='white',
                                 orient=HORIZONTAL, variable=self.game_turn_value)
        self.game_turn.pack(side=TOP)
        Label(self.panel_game, text='   ',
              font=('Calibri', 14, 'bold'),
              foreground='white', bg=BG).pack(side=TOP, fill=X)

        #  ################################## AGENT CONTROLS #############################

        self.agent_show.pack(fill=X, side=TOP)
        self.switch_agent.configure(from_=1, to=len(self.agent_type), tickinterval=1, bg=BG, fg='white',
                                    orient=HORIZONTAL, variable=self.switch_agent_value, )
        self.switch_agent.pack(side=TOP, fill=X)

        #  ################################## MOVE LABELS ################################
        self.move_label = Label(self.panel_game, font=('Calibri', 15, 'bold'), height=5, fg='white', justify=LEFT,
                                bg=BG, text='PLAY : CLICK A CELL ON GAME BOARD \nMCTS BOT: CLICK GENERATE')
        self.move_label.pack(side=TOP, fill=X)

        self.reset_board.configure(text='Reset Board', pady=10,
                                   cursor='hand2', width=22,
                                   font=('Calibri', 12, 'bold'))
        self.reset_board.pack(side=LEFT)
        self.generate.configure(text='Generate', pady=10,
                                cursor='hand2', width=22,
                                font=('Calibri', 12, 'bold'))
        self.generate.pack(side=LEFT)

        """
        the left panel notebook ---> Developers

        """
        self.developers.configure(bg=BG)
        Label(self.developers,
              text='HEXPY',
              font=('Calibri', 18, 'bold'),
              foreground='white', bg=BG, pady=5).pack(side=TOP, fill=X)
        Label(self.developers,
              text='DEVELOPED BY:\n'
                   + 'Masoud Masoumi Moghadam\n\n'
                   + 'SUPERVISED BY:\n'
                   + 'Dr.Pourmahmoud Aghababa\n'
                   + 'Dr.Bagherzadeh\n\n'
                   + 'SPECIAL THANKS TO:\n'
                   + 'Nemat Rahmani\n',
              font=('Calibri', 16, 'bold'), justify=LEFT,
              foreground='white', bg=BG, pady=10).pack(side=TOP, fill=X)
        Label(self.developers, image=self.uut_logo, bg=BG).pack(side=TOP, fill=X)
        Label(self.developers, text='Summer 2016',
              font=('Calibri', 17, 'bold'), wraplength=350, justify=LEFT,
              foreground='white', bg=BG, pady=30).pack(side=TOP, fill=X)

        # Binding Actions

        """
        Binding triggers for the actions defined in the class.

        """
        self.canvas.bind('<1>', self.click2play)
        self.game_size.bind('<ButtonRelease>', self.set_size)
        self.game_time.bind('<ButtonRelease>', self.set_time)
        self.generate.bind('<ButtonRelease>', self.click_to_bot_play)
        self.reset_board.bind('<ButtonRelease>', self.reset)
        self.switch_agent.bind('<ButtonRelease>', self.set_agent)

    @staticmethod
    def top_left_hexagon():
        """
        Returns the points which the first hexagon has to be created based on.

        """
        return [[85, 50], [105, 65], [105, 90], [85, 105], [65, 90], [65, 65]]

    def hexagon(self, points, color):
        """
        Creates a hexagon by getting a list of points and their assigned colors
        according to the game board
        """
        if color is 0:
            hx = self.canvas.create_polygon(points[0], points[1], points[2],
                                            points[3], points[4], points[5],
                                            fill=self.colors['gray1'], outline='black', width=2, activefill='cyan')
        elif color is 1:
            hx = self.canvas.create_polygon(points[0], points[1], points[2],
                                            points[3], points[4], points[5],
                                            fill=self.colors['yellow'], outline='black', width=2, activefill='cyan')
        elif color is 2:
            hx = self.canvas.create_polygon(points[0], points[1], points[2],
                                            points[3], points[4], points[5],
                                            fill=self.colors['red'], outline='black', width=2, activefill='cyan')
        elif color is 3:
            hx = self.canvas.create_polygon(points[0], points[1], points[2],
                                            points[3], points[4], points[5],
                                            fill=self.colors['black'], outline='black', width=2)
        else:
            hx = self.canvas.create_polygon(points[0], points[1], points[2],
                                            points[3], points[4], points[5],
                                            fill=self.colors['white'], outline='black', width=2)
        return hx

    def generate_row(self, points, colors):
        """
        By getting a list of points as the starting point of each row and a list of
        colors as the dedicated color for each item in row, it generates a row of
        hexagons by calling hexagon functions multiple times.
        """
        x_offset = 40
        row = []
        temp_array = []
        for i in range(len(colors)):
            for point in points:
                temp_points_x = point[0] + x_offset * i
                temp_points_y = point[1]
                temp_array.append([temp_points_x, temp_points_y])
            if colors[i] is 0:
                hx = self.hexagon(temp_array, 0)
            elif colors[i] is 1:
                hx = self.hexagon(temp_array, 4)
            else:
                hx = self.hexagon(temp_array, 3)
            row.append(hx)
            temp_array = []
        return row

    def gameboard2hexagons(self, array):
        """
        Simply gets the game_board and generates the hexagons by their dedicated colors.
        """
        initial_offset = 20
        y_offset = 40
        temp = []
        for i in range(len(array)):
            points = self.top_left_hexagon()
            for point in points:
                point[0] += initial_offset * i
                point[1] += y_offset * i
                temp.append([point[0], point[1]])
            row = self.generate_row(temp, self.board[i])
            temp.clear()
            self.hex_board.append(row)

    def generate_white_edge(self):
        """
        Generates the white zones in the left and right of the board.

        """
        init_points = self.top_left_hexagon()
        for pt in init_points:
            pt[0] -= 40
        for pt in init_points:
            pt[0] -= 20
            pt[1] -= 40
        label_x, label_y = 0, 0
        init_offset = 20
        y_offset = 40
        temp_list = []
        for i in range(len(self.board)):
            for pt in range(len(init_points)):
                init_points[pt][0] += init_offset
                init_points[pt][1] += y_offset
                label_x += init_points[pt][0]
                label_y += init_points[pt][1]
            label_x /= 6
            label_y /= 6
            self.hexagon(init_points, 4)
            self.canvas.create_text(label_x, label_y, fill=self.colors['black'], font="Times 20 bold",
                                    text=chr(ord('A') + i))
            label_x, label_y = 0, 0
            for j in init_points:
                temp_list.append([j[0] + (len(self.board) + 1) * 40, j[1]])
            self.hexagon(temp_list, 4)
            temp_list.clear()

    def generate_black_edge(self):
        """
        Generates the black zones in the top and bottom of the board.

        """
        init_points = self.top_left_hexagon()
        label_x, label_y = 0, 0
        temp_list = []
        for pt in init_points:
            pt[0] -= 60
            pt[1] -= 40
        for t in range(len(init_points)):
            init_points[t][0] += 40
            label_x += init_points[t][0]
            label_y += init_points[t][1]
        label_x /= 6
        label_y /= 6
        for i in range(len(self.board)):
            self.hexagon(init_points, 3)
            self.canvas.create_text(label_x, label_y, fill=self.colors['white'], font="Times 20 bold", text=i + 1)
            label_x, label_y = 0, 0
            for pt in init_points:
                temp_list.append([pt[0] + (len(self.board) + 1) * 20, pt[1] + (len(self.board) + 1) * 40])
            self.hexagon(temp_list, 3)
            temp_list.clear()
            for j in range(len(init_points)):
                init_points[j][0] += 40
                label_x += init_points[j][0]
                label_y += init_points[j][1]
            label_x /= 6
            label_y /= 6

    def click2play(self, event):
        """
        Whenever any of the hexagons in the board is clicked, depending
        on the player turns, it changes the color of hexagon to the player
        assigned color.

        """
        if self.winner() == 'none':
            x = self.canvas.canvasx(event.x)
            y = self.canvas.canvasy(event.y)
            idd = self.canvas.find_overlapping(x, y, x, y)
            idd = list(idd)
            if len(idd) is not 0:
                clicked_cell = idd[0]
                if any([clicked_cell in x for x in self.hex_board]):
                    coordinated_cell = clicked_cell - self.hex_board[0][0]
                    col = (coordinated_cell % self.size)
                    turn = self.turn[self.game_turn_value.get()]
                    if coordinated_cell % self.size == 0:
                        row = int(coordinated_cell / self.size)
                    else:
                        row = int(coordinated_cell / self.size)
                        cell = str(chr(65 + row)) + str(col + 1)
                        self.move_label.configure(text=str(turn) + ' played ' + cell, justify=LEFT, height=5)
                    if self.board[row][col] == 0:
                        self.board[row][col] = self.game_turn_value.get()
                        if self.game_turn_value.get() == 1:
                            self.game_turn_value.set(2)
                        else:
                            self.game_turn_value.set(1)
                    self.refresh()
                    y = row
                    x = col
                    if turn[0].lower() == 'w':
                        self.last_move = (x, y)
                        if self.game.turn() == GameMeta.PLAYERS["white"]:
                            self.game.play((x, y))
                            self.agent.move((x, y))
                            if self.winner() != 'none':
                                messagebox.showinfo(" GAME OVER", " Wow, You won! \n Winner is %s" % self.winner())
                            return
                        else:
                            self.game.place_white((x, y))
                            self.agent.set_gamestate(self.game)
                            if self.winner() != 'none':
                                messagebox.showinfo(" GAME OVER", " Wow, You won! \n Winner is %s" % self.winner())
                            return
                    elif turn[0].lower() == 'b':
                        self.last_move = (x, y)
                        if self.game.turn() == GameMeta.PLAYERS["black"]:
                            self.game.play((x, y))
                            self.agent.move((x, y))
                            if self.winner() != 'none':
                                messagebox.showinfo(" GAME OVER", " Wow, You won! \n Winner is %s" % self.winner())
                            return
                        else:
                            self.game.place_black((x, y))
                            self.agent.set_gamestate(self.game)
                            if self.winner() != 'none':
                                messagebox.showinfo(" GAME OVER", " Wow, You won! \n Winner is %s" % self.winner())
                            return
        else:
            messagebox.showinfo(" GAME OVER ", " The game is already over! Winner is %s" % self.winner())

    def set_size(self, event):
        """
        It changes the board size and reset the whole game.

        """
        self.canvas.delete('all')
        self.size = self.game_size_value.get()
        self.game = GameState(self.size)
        self.agent.set_gamestate(self.game)
        self.board = self.game.board
        self.board = int_(self.board).tolist()
        self.last_move = None
        self.move_label.config(text='PLAY : CLICK A CELL ON GAME BOARD \nMCTS BOT: CLICK GENERATE', justify='left',
                               height=5)
        self.refresh()

    def set_time(self, event) -> None:
        """
        It changes the time for CPU player to think and generate a move.

        """
        self.time = self.game_time_value.get()
        print('The CPU time = ', self.time, ' seconds')

    def set_agent(self, event) -> None:
        """
        It changes the time for CPU player to think and generate a move.

        """
        agent_num = self.switch_agent_value.get()
        self.agent_name = self.agent_type[agent_num]
        self.agent = self.AGENTS[self.agent_name](self.game)
        self.agent_show.config(font=('Calibri', 14, 'bold'), justify=LEFT,
                               text='Agent Policy: ' + self.agent_name + '\n')

    def winner(self) -> str:
        """
        Return the winner of the current game (black or white), none if undecided.

        """
        if self.game.winner == GameMeta.PLAYERS["white"]:
            return "white"
        elif self.game.winner == GameMeta.PLAYERS["black"]:
            return "black"
        else:
            return "none"

    def click_to_bot_play(self, event):
        """
        By pushing the generate button, It produces an appropriate move
        by using monte carlo tree search algorithm for the player which
        turn is his/hers! .

        """
        if self.winner() == 'none':
            self.agent.search(self.time)
            num_rollouts, node_count, run_time = self.agent.statistics()
            move = self.agent.best_move()  # the move is tuple like (3, 1)
            self.game.play(move)
            self.agent.move(move)
            row, col = move  # Relating the 'move' tuple with index of self.board
            self.board[col][row] = self.game_turn_value.get()
            if self.game_turn_value.get() == 1:  # change the turn of players
                self.game_turn_value.set(2)
            else:
                self.game_turn_value.set(1)
            self.refresh()
            player = self.turn[self.game_turn_value.get()]
            cell = chr(ord('A') + move[1]) + str(move[0] + 1)
            self.move_label.config(font=('Calibri', 15, 'bold'), justify='left',
                                   text=str(num_rollouts) + ' Game Simulations ' + '\n'
                                                          + 'In ' + str(run_time) + ' seconds ' + '\n'
                                                          + 'Node Count : ' + str(node_count) + '\n'
                                                          + player + ' played at ' + cell, height=5)
            print('move = ', cell)
            if self.winner() != 'none':
                messagebox.showinfo(" GAME OVER", " Oops!\n You lost! \n Winner is %s" % self.winner())
        else:
            messagebox.showinfo(" GAME OVER", " The game is already over! Winner is %s" % self.winner())

    def refresh(self):
        """
        Delete the whole world and recreate it again

        """
        self.canvas.delete('all')
        self.hex_board.clear()
        self.gameboard2hexagons(self.board)
        self.generate_black_edge()
        self.generate_white_edge()

    def reset(self, event):
        """
        By clicking on the Reset button game board would be cleared
        for a new game

        """
        self.game = GameState(self.game.size)
        self.agent.set_gamestate(self.game)
        self.set_size(event)
        self.last_move = None
        self.game_turn_value.set(1)
        self.move_label.config(text='PLAY : CLICK A CELL ON GAME BOARD \nMCTS BOT: CLICK GENERATE', justify='left',
                               height=5)
예제 #4
0
class ImageSlider(Frame):
    try:
        NOIMAGE = PILImage.open(
            open(
                os.path.join(os.path.dirname(__file__), 'images/noimages.png'),
                'rb'))
        BUTTONLEFT = PILImage.open(
            open(os.path.join(os.path.dirname(__file__), 'images/left.png'),
                 'rb'))
        BUTTONRIGHT = PILImage.open(
            open(os.path.join(os.path.dirname(__file__), 'images/right.png'),
                 'rb'))
    except FileNotFoundError as e:
        try:
            NOIMAGE = PILImage.open(open('images/noimages.png', 'rb'))
            BUTTONLEFT = PILImage.open(open('images/left.png', 'rb'))
            BUTTONRIGHT = PILImage.open(open('images/right.png', 'rb'))
        except Exception as f:
            raise f

    def __init__(self,
                 parent,
                 directory=os.getcwd(),
                 placeholder=NOIMAGE,
                 leftarrow=BUTTONLEFT,
                 rightarrow=BUTTONRIGHT,
                 *args,
                 **kw):
        Frame.__init__(self, parent, *args, **kw)
        self.directory = directory
        if placeholder != ImageSlider.NOIMAGE:
            placeholder = PILImage.open(open(placeholder, 'rb'))
        if leftarrow != ImageSlider.BUTTONLEFT:
            leftarrow = PILImage.open(open(leftarrow, 'rb'))
        if rightarrow != ImageSlider.BUTTONRIGHT:
            rightarrow = PILImage.open(open(rightarrow, 'rb'))
        self.placeholder = ImageTk.PhotoImage(placeholder)
        self.leftarrow, self.rightarrow = ImageTk.PhotoImage(
            leftarrow), ImageTk.PhotoImage(rightarrow)
        self.pics, self.photoims = None, None
        self.scalevar = IntVar()
        tf = Frame(self, bg=self['bg'])
        tf.pack(fill='both', expand=True)
        t1 = Frame(tf, bg=self['bg'])
        t1.pack(side='left', fill='y')
        Button(
            t1,
            image=self.leftarrow,
            command=lambda: self.scalevar.set(self.scalevar.get() - 1)).pack(
                side='left')
        t2 = Frame(tf, bg=self['bg'])
        t2.pack(side='left', fill='both', expand=True)
        self.imagelabel = Label(t2,
                                image=self.placeholder,
                                text='',
                                compound='top')
        self.imagelabel.pack(side='bottom')
        t3 = Frame(tf, bg=self['bg'])
        t3.pack(side='right', fill='y')
        Button(
            t3,
            image=self.rightarrow,
            command=lambda: self.scalevar.set(self.scalevar.get() + 1)).pack(
                side='right')
        self.scalevar.trace('w', lambda *event: self.changepic())
        self.slider = Scale(self, variable=self.scalevar, orient='horizontal')
        self.slider.pack(side='bottom')
        self.loaddirectory(directory)

    def loaddirectory(self, directory):
        self.directory = directory
        self.pics = [
            directory + '/' + pic for pic in os.listdir(directory)
            if pic.split('.')[-1] in ('gif', 'png', 'jpg')
        ]
        pics = [PILImage.open(open(pic, 'rb')) for pic in self.pics]
        for pic in pics:
            if max(pic.size) > 200:
                pic.thumbnail((200, 200), PILImage.ANTIALIAS)
        self.photoims = [ImageTk.PhotoImage(pic) for pic in pics]
        if not self.photoims:
            self.scalevar.set(0)
            self.slider.configure(from_=0, to_=0)
            self.imagelabel.configure(image=self.placeholder, text='')
        else:
            self.slider.configure(from_=1, to=len(self.photoims))
            self.scalevar.set(1)

    def changepic(self):
        if not self.photoims: return
        index = self.scalevar.get()
        if index == 0: self.scalevar.set(len(self.photoims))
        elif index > len(self.photoims): self.scalevar.set(1)
        else:
            self.imagelabel.configure(image=self.photoims[index - 1],
                                      text=self.pics[index - 1].rsplit(
                                          '/', maxsplit=1)[-1])

    def getpic(self):
        return self.pics[self.scalevar.get() - 1]
예제 #5
0
class CameraWindow(Frame):
    def __init__(self, root=0, video_source=None):
        Frame.__init__(self)
        self.root = root
        self.cam = video_source
        self.pic = Canvas(root, width=1000, height=800)
        self.pic.pack(side='top', fill='both', expand=True)
        self.memory = deque(maxlen=30 * 1)
        self.refresh_interval = 20
        self.config = {
                'grayscale': False,
                'gc_on': False,
                'xmin': 0,
                'xmax': 0,
                'ymin': 0,
                'ymax': 0,
                'zmin': 0,
                'zmax': 0,
                'draw_rect': False,
        }

        button_frame = Frame(root)
        button_frame.pack(fill='both', expand=True)

        add_button(button_frame, f'GrayScale', 'black', row=0, col=0, sticky="wse").configure(
                command=lambda: self.toggle_config('grayscale'))
        add_button(button_frame, f'Draw Rectangle', 'black', row=0, col=1, sticky="wse").configure(
                command=lambda: self.toggle_config('draw_rect'))
        add_button(button_frame, f'Foreground', 'black', row=0, col=2, sticky="wse").configure(
                command=lambda: self.toggle_config('gc_on'))
        add_button(button_frame, f'{3 + 1}', 'black', row=0, col=3, sticky="wse").configure(
                command=lambda: print(3 + 1))
        add_button(button_frame, f'{4 + 1}', 'black', row=0, col=4, sticky="wse").configure(
                command=lambda: print(4 + 1))
        add_button(button_frame, f'{5 + 1}', 'black', row=0, col=5, sticky="wse").configure(
                command=lambda: print(5 + 1))
        add_button(button_frame, f'{6 + 1}', 'black', row=0, col=6, sticky="wse").configure(
                command=lambda: print(6 + 1))
        add_button(button_frame, f'{7 + 1}', 'black', row=0, col=7, sticky="wse").configure(
                command=lambda: print(7 + 1))
        add_button(button_frame, f'{8 + 1}', 'black', row=0, col=8, sticky="wse").configure(
                command=lambda: print(8 + 1))
        add_button(button_frame, f'{9 + 1}', 'black', row=0, col=9, sticky="wse").configure(
                command=lambda: print(9 + 1))

        quit = add_button(button_frame, f'Quit', 'black', row=0, col=9, sticky="wse")
        quit.configure(
                command=lambda: sys.exit(0))

        for _col in range(10):
            button_frame.grid_columnconfigure(_col, weight=1)

        button_frame.grid_rowconfigure(0, weight=1)

        self.scale1 = Scale(root, label="Refresh", from_=10, to=500, command=self.set_refresh_interval)
        self.scale1.pack(side="left")

        self.scale2 = Scale(root, label="X-Min", to=255)
        self.scale2.pack(side="left")
        self.scale2.configure(command=lambda val: self.set_int_value('xmin', val))

        self.scale4 = Scale(root, label="X-Max", to=255)
        self.scale4.pack(side="left")
        self.scale4.configure(command=lambda val: self.set_int_value('xmax', val))

        self.scale3 = Scale(root, label="Y-Min", to=255)
        self.scale3.pack(side="left")
        self.scale3.configure(command=lambda val: self.set_int_value('ymin', val))

        self.scale5 = Scale(root, label="Y-Max", to=255)
        self.scale5.pack(side="left")
        self.scale5.configure(command=lambda val: self.set_int_value('ymax', val))

        self.scale3 = Scale(root, label="Z-Min", to=255)
        self.scale3.pack(side="left")
        self.scale3.configure(command=lambda val: self.set_int_value('zmin', val))

        self.scale5 = Scale(root, label="Z-Max", to=255)
        self.scale5.pack(side="left")
        self.scale5.configure(command=lambda val: self.set_int_value('zmax', val))

        self.scale8 = Scale(root, label="_8")
        self.scale8.pack(side="left")

        self.update()

    def set_refresh_interval(self, new_value):
        self.refresh_interval = int(new_value)

    def toggle_config(self, param):
        self.config.update({param: self.config[param] ^ True})
        print(f"{param} is now: {self.config[param]}")

    def set_int_value(self, param, new_value):
        self.config.update({param: int(new_value)})
        print(f"{param} is now: {self.config[param]}")

    def set_pic_size(self, width, height):
        self.pic.configure(width=width, height=height)

    def update(self):
        ret, frame = self.cam.get_frame()
        image = self.process_image(frame)
        photo = Image.fromarray(image)
        photo = ImageTk.PhotoImage(image=photo)
        self.memory.append(photo)  # reference to photo must persist
        self.pic.create_image(0, 0, image=photo, anchor='nw')
        self.root.after(self.refresh_interval, self.update)

    def process_image(self, image):
        """Returns Tkinter Canvas photo object"""
        xmin = self.config['xmin']
        xmax = self.config['xmax']
        ymin = self.config['ymin']
        ymax = self.config['ymax']
        zmin = self.config['zmin']
        zmax = self.config['zmax']

        image = self.strip_color(image, xmin, xmax, ymin, ymax, zmin, zmax)
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        return image

    def strip_color(self, image, hmin, hmax, smin, smax, vmin, vmax):
        frame_hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)

        lower_orange = np.array([hmin, smin, vmin])
        upper_orange = np.array([hmax, smax, vmax])

        mask_alpha = cv2.inRange(frame_hsv, lower_orange, upper_orange)
        mask = mask_alpha < 1

        frame = cv2.cvtColor(frame_hsv, cv2.COLOR_HSV2BGR)
        return frame

    def grab_cut(self, image, rect):
        mask = np.zeros(image.shape[:2], np.uint8)

        bdgModel = np.zeros((1, 65), np.float64)
        fgdModel = np.zeros((1, 65), np.float64)

        cv2.grabCut(image, mask, rect, bdgModel, fgdModel, 5, cv2.GC_INIT_WITH_RECT)
        mask2 = np.where((mask == 2) | (mask == 0), 0, 1).astype('uint8')[:, :, np.newaxis]
        image = image * mask2

        return image
예제 #6
0
               command=lambda t: update(2, t),
               variable=int_vars[2])

    # scales for 6 servos
    servos = []
    for i in range(6):
        servo = (lambda i: Scale(root,
                                 from_=0,
                                 to_=180,
                                 orient=HORIZONTAL,
                                 length=600,
                                 command=lambda t: update(3 + i, t),
                                 variable=int_vars[3 + i]))(i)  # closure
        servo.configure(background="white")
        servos.append(servo)
        servo.set(arm.position[i])
        servo.grid(row=3 + i, column=1)

    sx.set(100)
    sy.set(100)
    sz.set(100)
    sx.configure(background="white")
    sy.configure(background="white")
    sz.configure(background="white")
    sx.grid(row=0, column=1)
    sy.grid(row=1, column=1)
    sz.grid(row=2, column=1)

    plt.show()
    root.mainloop()
class PlayerControlPanel(Frame, IPlayerStateListener):
    def __init__(self, parent):
        super().__init__(parent)
        self.trackNameLabel: Label = None
        self.volumeScale: Scale = None

        self.muted = False

        self.__initView()

    def __initView(self):
        self.configure(borderwidth=3, relief=RIDGE)
        self.configure(height=HEIGHT)

        ###################################################################################

        image = Image.open(PLAY_ICON)
        image = image.resize((32, 32), Image.ANTIALIAS)
        self.play_icon = PhotoImage(image=image)

        image = Image.open(PAUSE_ICON)
        image = image.resize((32, 32), Image.ANTIALIAS)
        self.pause_icon = PhotoImage(image=image)

        self.playPauseButton = Button(self, image=self.play_icon)
        self.playPauseButton.grid(row=0, column=0)

        ###################################################################################

        image = Image.open(NEXT_TRACK_ICON)
        image = image.resize((32, 32), Image.ANTIALIAS)
        self.next_track_icon = PhotoImage(image=image)

        self.nextTrackButton = Button(self, image=self.next_track_icon)
        self.nextTrackButton.grid(row=0, column=1)

        ###################################################################################

        image = Image.open(LINEAR_ICON)
        image = image.resize((32, 32), Image.ANTIALIAS)
        self.linear_icon = PhotoImage(image=image)

        image = Image.open(REPEAT_ICON)
        image = image.resize((32, 32), Image.ANTIALIAS)
        self.repeat_icon = PhotoImage(image=image)

        self.musicSelectionModeButton = Button(self,
                                               image=self.next_track_icon)
        self.musicSelectionModeButton.grid(row=0, column=2)

        ###################################################################################

        image = Image.open(MUTE_ICON)
        image = image.resize((32, 32), Image.ANTIALIAS)
        self.mute_icon = PhotoImage(image=image)

        image = Image.open(UNMUTE_ICON)
        image = image.resize((32, 32), Image.ANTIALIAS)
        self.unmute_icon = PhotoImage(image=image)

        self.muteButton = Button(self,
                                 image=self.mute_icon,
                                 command=self.__muteButtonPressed)
        self.muteButton.grid(row=0, column=3)

        ###################################################################################

        self.volumeScale = Scale(self, from_=0, to=100, orient=HORIZONTAL)
        self.volumeScale.set(50)
        self.volumeScale.grid(row=0, column=4)

        ###################################################################################

        self.trackProgressBar = Progressbar(self,
                                            orient=HORIZONTAL,
                                            length=300,
                                            mode='determinate',
                                            maximum=MAXIMUM)
        self.trackProgressBar.grid(row=0, column=5)

        ###################################################################################

        self.timeLabel = Label(self, text='--:--/--:--')
        self.timeLabel.grid(row=0, column=6)

        self.trackNameLabel = Label(self)
        self.trackNameLabel.grid(row=0, column=7)

    def onPlayerStateUpdated(self, state: PlayerState):
        self.trackNameLabel.configure(text=state.trackName)

        if state.trackType is TrackType.MUSIC:
            self.trackProgressBar.configure(value=int(MAXIMUM *
                                                      state.trackPosition))
            self.playPauseButton.configure(state=NORMAL)
        else:
            self.trackProgressBar.configure(value=0)
            self.playPauseButton.configure(state=DISABLED)

        if state.playbackState is PlaybackState.PLAYING:
            self.playPauseButton.configure(image=self.pause_icon)
        else:
            self.playPauseButton.configure(image=self.play_icon)

        if state.musicSelectionMode is MusicSelectionMode.LINEAR:
            self.musicSelectionModeButton.configure(image=self.linear_icon)
        else:
            self.musicSelectionModeButton.configure(image=self.repeat_icon)

        self.__displayTime(state)

    def __displayTime(self, state: PlayerState):
        trackMinutes = int(state.trackLength / 60)
        trackSeconds = state.trackLength % 60

        played = int(state.trackPosition * state.trackLength)
        playedMinutes = int(played / 60)
        playedSeconds = played % 60

        if state.trackType is not TrackType.MUSIC:
            self.timeLabel.configure(text='--:--/--:--')
        else:
            self.timeLabel.configure(
                text=
                f'{playedMinutes:02d}:{playedSeconds:02d}/{trackMinutes:02d}:{trackSeconds:02d}'
            )

    def setPlayerController(self, playerController: IPlayerController):
        self.playerController = playerController

        self.volumeScale.configure(command=lambda v: self.__sendVolume())
        self.__sendVolume()

        self.trackProgressBar.bind(
            "<Button-1>",
            lambda e: self.onProgressBarClicked(e, playerController))
        self.playPauseButton.configure(
            command=playerController.onPlayPauseClicked)
        self.nextTrackButton.configure(
            command=playerController.nextTrackClicked)
        self.musicSelectionModeButton.configure(
            command=playerController.changeMusicSelectionModeClicked)

    def __sendVolume(self):
        if self.playerController is None:
            return

        if self.muted:
            self.playerController.onVolumeSelected(0)
        else:
            self.playerController.onVolumeSelected(self.volumeScale.get())

    def __muteButtonPressed(self):
        self.muted = not self.muted

        if self.muted:
            self.muteButton.configure(image=self.unmute_icon)
        else:
            self.muteButton.configure(image=self.mute_icon)

        self.__sendVolume()

    def onProgressBarClicked(self, event, playerController: IPlayerController):
        percentage = event.x / event.widget.winfo_width()
        playerController.seekTo(percentage)

    def onPlayerEndReached(self):
        pass