Sunday, May 12, 2019

Using Checkbox PyQt and OpenCV

To know more about Python GUI and MySQL database, you can purchase my book (indonesian version) titled "LANGKAH DEMI LANGKAH| MEMBANGUN SISTEM MANAJEMEN DATABASE DENGAN PYTHON/MYSQL" on Google Play Books.




In this tutorial, you will use five CheckBox widget from Qt Designer to perform kernel filters with different size. The resulting image and its histogram will be displayed. Follow these steps below:
  1. Open Qt Designer. Create the form using the Main Window template:


  2. Click the Create button.
  3. Then, place a Push Button widget and two Label widgets on the form.
  4. Specify the text property of the Push Button widget to Read Image dan that of two Label widget to labelImage and labelFilter in the Property Editor window.
  5. Set the property of the objectName from the Push Button widget in the Property Editor window to pbImage.
  6. Place two Widget widgets from the Containers panel on the form. Set the objectName property of the two Widget to be the widgetDisplay and widgetDisplay2.
  7. Place five CheckBox widgets onto form. Specify the text property of each CheckBox widget to Kernel 3 x 3, Kernel 5 x 5, Kernel 7 x 7, Kernel 9 x 9, and Kernel 11 x 11.
  8. Set the objectName property of each CheckBox widget to cbKernel3x3cbKernel5x5cbKernel7x7cbKernel9x9, and cbKernel11x11.
  9. Save the form with the name histogram2.ui. Now, the form looks like it looks in the following figure:


  10. Next, right-click on the two Widget and from  the context menu displayed select Promoted widgets and select checkbox available (as before, Histogram).
  11. Define the Histogram class in a Python file with the same name as before:

  12. from PyQt5.QtWidgets import*
    from matplotlib.backends.backend_qt5agg import FigureCanvas
    from matplotlib.figure import Figure
        
    class Histogram(QWidget):    
        def __init__(self, parent = None):
            QWidget.__init__(self, parent)        
            self.canvas = FigureCanvas(Figure())
           
            vertical_layout = QVBoxLayout()
            vertical_layout.addWidget(self.canvas)
            
            self.canvas.axes1 = self.canvas.figure.add_subplot(111)
            self.canvas.figure.set_facecolor("xkcd:beige")
            self.setLayout(vertical_layout)
    

  13. Define the new Python script with name main_histogram2.py that defines five methods relating to kernel filtering and connect it with the stateChanged() event from corresponding CheckBox widget:

  14. #main_histogram2.py
    import cv2
    import numpy as np
    from PyQt5.QtWidgets import*
    from PyQt5.uic import loadUi
    from matplotlib.backends.backend_qt5agg import (NavigationToolbar2QT as NavigationToolbar)
    from PyQt5.QtWidgets import QDialog, QFileDialog
    from PyQt5.QtGui import QIcon, QPixmap, QImage
    
    import numpy as np
    fname = ""
         
    class Display_Histogram(QMainWindow):   
        def __init__(self):
            QMainWindow.__init__(self)
            loadUi("histogram2.ui",self)
    
            self.setWindowTitle("Image Histogram")
            self.pbImage.clicked.connect(self.display_histogram)
            self.cbKernel3x3.stateChanged.connect(lambda:self.btnstate(self.cbKernel3x3))
            self.cbKernel5x5.stateChanged.connect(lambda:self.btnstate(self.cbKernel5x5))
            self.cbKernel7x7.stateChanged.connect(lambda:self.btnstate(self.cbKernel7x7))
            self.cbKernel9x9.stateChanged.connect(lambda:self.btnstate(self.cbKernel9x9))
            self.cbKernel11x11.stateChanged.connect(lambda:self.btnstate(self.cbKernel11x11))
            self.addToolBar(NavigationToolbar(self.widgetDisplay.canvas, self))
    
        def display_histogram(self):
            global fname
            fname = QFileDialog.getOpenFileName(self, 'Open file', 
               'd:\\',"Image Files (*.jpg *.gif *.bmp *.png *.tiff)")
            pixmap = QPixmap(fname[0])
            self.labelImage.setPixmap(pixmap)
            self.labelImage.setScaledContents(True);
            
    
            self.widgetDisplay.canvas.axes1.clear()
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            color = ('b','g','r')
            for i,col in enumerate(color):
                histr = cv2.calcHist([read_img],[i],None,[256],[0,256])
                self.widgetDisplay.canvas.axes1.plot(histr,color = col,linewidth=3.0)
                self.widgetDisplay.canvas.axes1.set_ylabel('Y', color='blue')
                self.widgetDisplay.canvas.axes1.set_xlabel('X', color='blue')
                self.widgetDisplay.canvas.axes1.set_title('Histogram')
                self.widgetDisplay.canvas.axes1.set_facecolor('xkcd:wheat')
                self.widgetDisplay.canvas.axes1.grid()
            self.widgetDisplay.canvas.draw()
    
        def kernel3x3(self):
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            
            # To filter image using kernel 3x3
            kernel_3x3 = np.ones((3,3), np.float32) / 9.0
            self.output = cv2.filter2D(read_img, -1, kernel_3x3)
            
            return self.output
    
        def kernel5x5(self):
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            
            # To filter image using kernel 5x5
            kernel_5x5 = np.ones((5,5), np.float32) / 25.0
            self.output = cv2.filter2D(read_img, -1, kernel_5x5)
            
            return self.output
    
        def kernel7x7(self):
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            
            # To filter image using kernel 7x7
            kernel_7x7 = np.ones((7,7), np.float32) / 49.0
            self.output = cv2.filter2D(read_img, -1, kernel_7x7)
            
            return self.output
    
        def kernel9x9(self):
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            
            # To filter image using kernel 9x9
            kernel_9x9 = np.ones((9,9), np.float32) / 81.0
            self.output = cv2.filter2D(read_img, -1, kernel_9x9)
            
            return self.output
    
        def kernel11x11(self):
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            
            # To filter image using kernel 11x11
            kernel_11x11 = np.ones((11,11), np.float32) / 121.0
            self.output = cv2.filter2D(read_img, -1, kernel_11x11)
            
            return self.output
        
        def display_output(self, output, title):
            # To convert back from BGR to RGB space color
            cv2.cvtColor(output, cv2.COLOR_BGR2RGB, output)
            
            # To display image in label widget
            height, width, channel = output.shape
            bytesPerLine = 3 * width
            qImg = QImage(output.data, width, height, bytesPerLine, QImage.Format_RGB888)
            pixmap = QPixmap.fromImage(qImg)
            self.labelFilter.setPixmap(pixmap)
            self.labelFilter.setScaledContents(True);        
    
            self.widgetDisplay2.canvas.axes1.clear()
            color = ('b','g','r')
            for i,col in enumerate(color):
                histr = cv2.calcHist([output],[i],None,[256],[0,256])
                self.widgetDisplay2.canvas.axes1.plot(histr,color = col,linewidth=3.0)
                self.widgetDisplay2.canvas.axes1.set_ylabel('Y', color='blue')
                self.widgetDisplay2.canvas.axes1.set_xlabel('X', color='blue')
                self.widgetDisplay2.canvas.axes1.set_title(title)
                self.widgetDisplay2.canvas.axes1.set_facecolor('xkcd:wheat')
                self.widgetDisplay2.canvas.axes1.grid()
            self.widgetDisplay2.canvas.draw()
    
        def btnstate(self,b):
            if b.text() == "Kernel 3 x 3":
                if b.isChecked() == True:
                    self.cbKernel5x5.setChecked(False)
                    self.cbKernel7x7.setChecked(False)
                    self.cbKernel9x9.setChecked(False)
                    self.cbKernel11x11.setChecked(False)
                    self.output = self.kernel3x3()
                    self.display_output(self.output, 'Histogram of Filtered Image Using Kernel 3 x 3')
                else:
                    print b.text()+" is deselected"
        
            if b.text() == "Kernel 5 x 5":
                if b.isChecked() == True:
                    self.cbKernel3x3.setChecked(False)
                    self.cbKernel7x7.setChecked(False)
                    self.cbKernel9x9.setChecked(False)
                    self.cbKernel11x11.setChecked(False)
                    self.output = self.kernel5x5()
                    self.display_output(self.output, 'Histogram of Filtered Image Using Kernel 5 x 5')
                else:
                    print b.text()+" is deselected"
    
            if b.text() == "Kernel 7 x 7":
                if b.isChecked() == True:
                    self.cbKernel3x3.setChecked(False)
                    self.cbKernel5x5.setChecked(False)
                    self.cbKernel9x9.setChecked(False)
                    self.cbKernel11x11.setChecked(False)
                    self.output = self.kernel7x7()
                    self.display_output(self.output, 'Histogram of Filtered Image Using Kernel 7 x 7')
                else:
                    print b.text()+" is deselected"
                    
            if b.text() == "Kernel 9 x 9":
                if b.isChecked() == True:
                    self.cbKernel3x3.setChecked(False)
                    self.cbKernel7x7.setChecked(False)
                    self.cbKernel5x5.setChecked(False)
                    self.cbKernel11x11.setChecked(False)
                    self.output = self.kernel9x9()
                    self.display_output(self.output, 'Histogram of Filtered Image Using Kernel 9 x 9')
                else:
                    print b.text()+" is deselected"
                    
            if b.text() == "Kernel 11 x 11":
                if b.isChecked() == True:
                    self.cbKernel3x3.setChecked(False)
                    self.cbKernel7x7.setChecked(False)
                    self.cbKernel9x9.setChecked(False)
                    self.cbKernel5x5.setChecked(False)
                    self.output = self.kernel11x11()
                    self.display_output(self.output, 'Histogram of Filtered Image Using Kernel 11 x 11')
                else:
                    print b.text()+" is deselected"
                    
    if __name__ == '__main__':
        import sys
        app = QApplication(sys.argv)
        ex = Display_Histogram()
        ex.show()
        sys.exit(app.exec_())
    

  15. Click on Read Image and select one of five checkboxes available. You now can see the filtered image and its each histogram:





Saturday, May 11, 2019

Image Histogram with OpenCV and PyQt

To know more about Python GUI, you can visit my book (LEARN FROM SCRATCH SIGNAL AND IMAGE PROCESSING WITH PYTHON GUI) on Amazon or Google Books.



In this tutorial, you will display image histogram with OpenCV and PyQt. Follow these steps below:
  1. Open Qt Designer. Create the form using the Main Window template:


  2. Click the Create button.
  3. Then, place a Push Button widget and a Label widget on the form.
  4. Specify the text property of the Push Button widget to Read Image dan that of Label widget to labelImage in the Property Editor window.
  5. Set the property of the objectName from the Push Button widget in the Property Editor window to pbImage.
  6. Place a Widget from the Containers panel on the form. Set the objectName property to be the widgetDisplay.
  7. Save the form with the name histogram.ui. Now, the form looks like it looks in the following figure:


  8. Next, right-click on the Widget and from  the context menu displayed select Promote to ...:


  9. Name the Promoted class name as Histogram:


  10. Then click the Add button and click the Promote button. In the Object Inspector window, you can see that widgetDisplay (Histogram class) along with the pbImage object (QPushButton class) is now in the centralwidget object (QWidget class).
  11. Define the Histogram class in a Python file with the same name:

  12. from PyQt5.QtWidgets import*
    from matplotlib.backends.backend_qt5agg import FigureCanvas
    from matplotlib.figure import Figure
        
    class Histogram(QWidget):    
        def __init__(self, parent = None):
            QWidget.__init__(self, parent)        
            self.canvas = FigureCanvas(Figure())
           
            vertical_layout = QVBoxLayout()
            vertical_layout.addWidget(self.canvas)
            
            self.canvas.sumbu1 = self.canvas.figure.add_subplot(111)
            self.canvas.figure.set_facecolor("xkcd:wheat")
            self.setLayout(vertical_layout)
    

  13. Define the new Python script with name main_histogram.py that defines the method display_histogram() and connect it with the clicked() event from pbImage widget:

  14. #main_histogram.py
    import cv2
    import numpy as np
    from PyQt5.QtWidgets import*
    from PyQt5.uic import loadUi
    from matplotlib.backends.backend_qt5agg import (NavigationToolbar2QT as NavigationToolbar)
    from PyQt5.QtWidgets import QDialog, QFileDialog
    from PyQt5.QtGui import QIcon, QPixmap, QImage
    
    import numpy as np
    fname = ""
         
    class Display_Histogram(QMainWindow):   
        def __init__(self):
            
            QMainWindow.__init__(self)
            loadUi("histogram.ui",self)
    
            self.setWindowTitle("Image Histogram")
            self.pbImage.clicked.connect(self.display_histogram)
            self.addToolBar(NavigationToolbar(self.widgetDisplay.canvas, self))
    
        def display_histogram(self):
            global fname
            fname = QFileDialog.getOpenFileName(self, 'Open file', 
               'd:\\',"Image Files (*.jpg *.gif *.bmp *.png *.tiff)")
            pixmap = QPixmap(fname[0])
            self.labelImage.setPixmap(pixmap)
            self.labelImage.setScaledContents(True);
            
    
            self.widgetDisplay.canvas.sumbu1.clear()
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            color = ('b','g','r')
            for i,col in enumerate(color):
                histr = cv2.calcHist([read_img],[i],None,[256],[0,256])
                self.widgetDisplay.canvas.sumbu1.plot(histr,color = col,linewidth=3.0)
                self.widgetDisplay.canvas.sumbu1.set_ylabel('Y', color='blue')
                self.widgetDisplay.canvas.sumbu1.set_xlabel('X', color='blue')
                self.widgetDisplay.canvas.sumbu1.set_title('Histogram')
                self.widgetDisplay.canvas.sumbu1.set_facecolor('xkcd:wheat')
                self.widgetDisplay.canvas.sumbu1.grid()
            self.widgetDisplay.canvas.draw()
                
    if __name__ == '__main__':
        import sys
        app = QApplication(sys.argv)
        ex = Display_Histogram()
        ex.show()
        sys.exit(app.exec_())
    

  15. Click on Read Image button. You now can see the image and its histogram:



  16. Place another Push Button widget and Label widget onto form. 
  17. Set the property of the objectName from the Push Button widget in the Property Editor window to pbFilter.
  18. Set the property of the objectName from the Label widget in the Property Editor window to labelFilter.
  19. Place another Widget from the Containers panel on the form. Set the objectName property to be the widgetDisplay2
  20. Next, right-click on the Widget and from  the context menu displayed select Promoter widgets and select checkbox available:


  21. Modify main_histogram.py that defines the method filter_histogram() and connect it with the clicked() event from pbFilter widget:

  22. #main_histogram.py
    import cv2
    import numpy as np
    from PyQt5.QtWidgets import*
    from PyQt5.uic import loadUi
    from matplotlib.backends.backend_qt5agg import (NavigationToolbar2QT as NavigationToolbar)
    from PyQt5.QtWidgets import QDialog, QFileDialog
    from PyQt5.QtGui import QIcon, QPixmap, QImage
    
    import numpy as np
    fname = ""
         
    class Display_Histogram(QMainWindow):   
        def __init__(self):
            
            QMainWindow.__init__(self)
            loadUi("histogram.ui",self)
    
            self.setWindowTitle("Image Histogram")
            self.pbImage.clicked.connect(self.display_histogram)
            self.pbFilter.clicked.connect(self.filter_histogram)
            self.addToolBar(NavigationToolbar(self.widgetDisplay.canvas, self))
    
        def display_histogram(self):
            global fname
            fname = QFileDialog.getOpenFileName(self, 'Open file', 
               'd:\\',"Image Files (*.jpg *.gif *.bmp *.png *.tiff)")
            pixmap = QPixmap(fname[0])
            self.labelImage.setPixmap(pixmap)
            self.labelImage.setScaledContents(True);
            
    
            self.widgetDisplay.canvas.axes1.clear()
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            color = ('b','g','r')
            for i,col in enumerate(color):
                histr = cv2.calcHist([read_img],[i],None,[256],[0,256])
                self.widgetDisplay.canvas.axes1.plot(histr,color = col,linewidth=3.0)
                self.widgetDisplay.canvas.axes1.set_ylabel('Y', color='blue')
                self.widgetDisplay.canvas.axes1.set_xlabel('X', color='blue')
                self.widgetDisplay.canvas.axes1.set_title('Histogram')
                self.widgetDisplay.canvas.axes1.set_facecolor('xkcd:wheat')
                self.widgetDisplay.canvas.axes1.grid()
            self.widgetDisplay.canvas.draw()
    
        def filter_histogram(self):
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            
            # To filter image using kernel 5x5
            kernel_5x5 = np.ones((5,5), np.float32) / 25.0
            output = cv2.filter2D(read_img, -1, kernel_5x5)
            
            # To convert back from BGR to RGB space color
            cv2.cvtColor(output, cv2.COLOR_BGR2RGB, output)
            
            # To display image in label widget
            height, width, channel = output.shape
            bytesPerLine = 3 * width
            qImg = QImage(output.data, width, height, bytesPerLine, QImage.Format_RGB888)
            pixmap = QPixmap.fromImage(qImg)
            self.labelFilter.setPixmap(pixmap)
            self.labelFilter.setScaledContents(True);        
    
            self.widgetDisplay2.canvas.axes1.clear()
            color = ('b','g','r')
            for i,col in enumerate(color):
                histr = cv2.calcHist([output],[i],None,[256],[0,256])
                self.widgetDisplay2.canvas.axes1.plot(histr,color = col,linewidth=3.0)
                self.widgetDisplay2.canvas.axes1.set_ylabel('Y', color='blue')
                self.widgetDisplay2.canvas.axes1.set_xlabel('X', color='blue')
                self.widgetDisplay2.canvas.axes1.set_title('Histogram of Filtered Image')
                self.widgetDisplay2.canvas.axes1.set_facecolor('xkcd:wheat')
                self.widgetDisplay2.canvas.axes1.grid()
            self.widgetDisplay2.canvas.draw()
                
    if __name__ == '__main__':
        import sys
        app = QApplication(sys.argv)
        ex = Display_Histogram()
        ex.show()
        sys.exit(app.exec_())
    

  23. Click on Read Image and Filter Image buttons. You now can see the image and its each histogram:



Image Filter with OpenCV and PyQt

In this tutorial, you will learn how to use OpenCV module to filter image using kernels and to display the resulting image with PyQt. 

Follow these steps below:
  1. Open Qt Designer. Put four Label widgets dan four Push Button widgets onto form.
  2. Set objectName property of the four Label widgets by name labelImage, labelIdentitylabelKernel3x3, and labelKernel5x5.
  3. Set objectName property of the four Push Button widgets by name pbOriginalImagepbIdentityImagepbKernel3x3, and pbKernel5x5.
  4. Name form as image_filter.ui.
  5. Form now looks as follows:


  6. Write this script and name it as image_filter.py:

  7. import sys
    import cv2
    import numpy as np
    from PyQt5.QtWidgets import QApplication, QWidget, QLabel
    from PyQt5.QtWidgets import QDialog, QFileDialog
    from PyQt5.QtGui import QIcon, QPixmap, QImage
    from PyQt5.uic import loadUi
    
    fname = ""
        
    class FormImageFilter(QDialog):
    
        def __init__(self):
            QDialog.__init__(self)
            loadUi("image_filter.ui",self)
    
            self.setWindowTitle("Image Filter")
            self.pbOriginalImage.clicked.connect(self.display_image)
            self.pbIdentityImage.clicked.connect(self.image_identity)
            self.pbKernel3x3.clicked.connect(self.kernel3x3)
            self.pbKernel5x5.clicked.connect(self.kernel5x5)
    
        def display_image(self):
            global fname
            fname = QFileDialog.getOpenFileName(self, 'Open file', 
               'd:\\',"Image Files (*.jpg *.gif *.bmp *.png *.tiff)")
            pixmap = QPixmap(fname[0])
            self.labelImage.setPixmap(pixmap)
            self.labelImage.setScaledContents(True);
    
        def image_identity(self, b=None):
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            kernel_identity = np.array([[0,0,0], [0,1,0], [0,0,0]])
            
            # To filter image using identity kernel
            output = cv2.filter2D(read_img, -1, kernel_identity)
            
            # To convert back from BGR to RGB space color
            cv2.cvtColor(output, cv2.COLOR_BGR2RGB, output)
            
            # To display image in label widget
            height, width, channel = output.shape
            bytesPerLine = 3 * width
            qImg = QImage(output.data, width, height, bytesPerLine, QImage.Format_RGB888)
            pixmap = QPixmap.fromImage(qImg)
            self.labelIdentity.setPixmap(pixmap)
            self.labelIdentity.setScaledContents(True);
    
        def kernel3x3(self):
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            
            # To filter image using kernel 3x3
            kernel_3x3 = np.ones((3,3), np.float32) / 9.0
            output = cv2.filter2D(read_img, -1, kernel_3x3)
            
            # To convert back from BGR to RGB space color
            cv2.cvtColor(output, cv2.COLOR_BGR2RGB, output)
            
            # To display image in label widget
            height, width, channel = output.shape
            bytesPerLine = 3 * width
            qImg = QImage(output.data, width, height, bytesPerLine, QImage.Format_RGB888)
            pixmap = QPixmap.fromImage(qImg)
            self.labelKernel3x3.setPixmap(pixmap)
            self.labelKernel3x3.setScaledContents(True);
    
        def kernel5x5(self):
            read_img = cv2.imread(fname[0], cv2.IMREAD_COLOR)
            
            # To filter image using kernel 5x5
            kernel_5x5 = np.ones((5,5), np.float32) / 25.0
            output = cv2.filter2D(read_img, -1, kernel_5x5)
            
            # To convert back from BGR to RGB space color
            cv2.cvtColor(output, cv2.COLOR_BGR2RGB, output)
            
            # To display image in label widget
            height, width, channel = output.shape
            bytesPerLine = 3 * width
            qImg = QImage(output.data, width, height, bytesPerLine, QImage.Format_RGB888)
            pixmap = QPixmap.fromImage(qImg)
            self.labelKernel5x5.setPixmap(pixmap)
            self.labelKernel5x5.setScaledContents(True);
            
    if __name__=="__main__":
        app = QApplication(sys.argv)    
        w = FormImageFilter()
        w.show()
        sys.exit(app.exec_())
    

  8. Run the program and you now can see the resulting images (identity image and two kernel images):