This content is powered by Balige Publishing. Visit this link (collaboration with Rismon Hasiholan Sianipar)
Run the script to see detected features as shown in Figure below.
Run feature_detection.py then click Read Image button to see displayed image in labelImage widget as shown in Figure below.
Then, put four Horizontal Slider widgets and set their objectName properties to hsBlockSize, hsKSize, hsK, and hsThreshold. Set minimum property of hsBlockSize and hsKSize widgets to 3. Set maximum property of hsKSize to 31.
Set singleStep property of hsKSize widget to 2. Set value property of hsBlockSize to 2, that of hsKSize to 3, that of hsK to 4, and that of hsThreshold to 1.
Run feature_detection.py then click Read Image button to see displayed image in labelImage widget as shown in Figure below.
Define a new method named initialization() to set state of some widgets as follows:
Invoke initialization() method from inside __init__() to disable widgets when form starts:
Modify read_image() to enable cboFeature widget as shown in line 8:
Run feature_detection.py. Make sure some widgets disabled when form first starts as shown in Figure below.
Connect currentIndexChanged() of cboFeature widget to choose_feature() and place it inside __init__() method as follows:
Define four functions to display each slider handle value in Line Edit widget:
Connect valueChanged event of hsBlockSize widget with set_hsBlockSize() method, that of hsKSize widget with set_hsKSize(), that of hsK widget with set_hsK(), and that of hsThreshold with set_hsThreshold(). Put them inside __init__() method:
Run feature_detection.py. Open an image, choose Harris Corner Detection from combo box, and drag the four horizontal sliders as you like. You will see the value in line edit widgets change as shown in Figure below.
Define display_image() method to display an image on a Label widget as follows:
Define harris_detection() method to perform Harris Corner Detection technique as follows:
Modify these four methods to invoke harris_detection() as follows:
Modify choose_feature() to invoke harris_detection() method when user choose Harris Corner Detection from combo box:
Run feature_detection.py, open an image, and choose Harris Corner Detection from cboFeature. Choose the value of each parameter and see the result as shown in Figure below.
Below is the full script of feature_detection.py so far:
Feature Detection Using Python GUI (PyQt) Part 2
In this tutorial, you will learn how to use OpenCV, NumPy library and other libraries to perform feature extraction with Python GUI (PyQt). The feature detection techniques used in this chapter are Harris Corner Detection, Shi-Tomasi Corner Detector, Scale-Invariant Feature Transform (SIFT), Speeded-Up Robust Features (SURF), Features from Accelerated Segment Test (FAST), Binary Robust Independent Elementary Features (BRIEF), and Oriented FAST and Rotated BRIEF (ORB).
Tutorial Steps To Detect Image Features Using Harris Corner Detection
In this sub chapter, you will find corners that was done by Chris Harris & Mike Stephens in their paper A Combined Corner and Edge Detector in 1988.
OpenCV has the function cv.cornerHarris() for this purpose, whose arguments are:
The script below implement feature detection using Harris Corner Detection algorithm:
#harris_corner.py import numpy as np import cv2 as cv filename = 'chessboard.png' img = cv.imread(filename) gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY) gray = np.float32(gray) dst = cv.cornerHarris(gray,3,5,0.04) #dilated for marking the corners dst = cv.dilate(dst,None) # Threshold for an optimal value, it may vary depending on the image. img[dst>0.01*dst.max()]=[0,0,255] cv.imshow('dst',img) if cv.waitKey(0) & 0xff == 27: cv.destroyAllWindows()
Run the script to see detected features as shown in Figure below.
To find the corners with maximum accuracy. OpenCV comes has a function named cv.cornerSubPix() that refines the corners detected with sub-pixel accuracy.
Below is an example. As usual, we need to find the Harris corners first. Then we pass the centroids of these corners (There may be a bunch of pixels at a corner, we take their centroid) to refine them. Harris corners are marked in red pixels and refined corners are marked in green pixels. For this function, we have to define the criteria when to stop the iteration. We stop it after a specified number of iterations or a certain accuracy is achieved, whichever occurs first. We also need to define the size of the neighbourhood it searches for corners.
#harris_corner_accurate.pyimport numpy as npimport cv2 as cvfilename = 'chessboard.png'img = cv.imread(filename)gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)# find Harris cornersgray = np.float32(gray)dst = cv.cornerHarris(gray,5,5,0.04)dst = cv.dilate(dst,None)ret, dst = cv.threshold(dst,0.01*dst.max(),255,0)dst = np.uint8(dst)# find centroidsret, labels, stats, centroids = cv.connectedComponentsWithStats(dst)# define the criteria to stop and refine the cornerscriteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER,\100, 0.001)corners = cv.cornerSubPix(gray,np.float32(centroids),\(5,5),(-1,-1),criteria)# Now draw themres = np.hstack((centroids,corners))res = np.int0(res)img[res[:,1],res[:,0]]=[0,0,255]img[res[:,3],res[:,2]] = [0,255,0]cv.imshow('dst',img)if cv.waitKey(0) & 0xff == 27:cv.destroyAllWindows()
Now, you will design Python GUI to implement Harris Corner Detection with Qt Designer.
Create a new form using Qt Designer with Main Window template. Set its name as feature_detection.ui.
Add two new Label widgets and set their objectName properties as labelImage and labelResult. Then, add two more Label widgets and set their text properties as Original Image and Detected Features.
Add one Push Button widget onto form, set its ObjectName property as pbReadImage, and set its text property as Read Image. The form now looks as shown in Figure below.
Create a new Python script and name it as feature_detection.py. Write the basic content of the script as follows:
#feature_detection.pyimport sysimport cv2import numpy as npfrom PyQt5.QtWidgets import*from PyQt5 import QtGui, QtCorefrom PyQt5.uic import loadUifrom matplotlib.backends.backend_qt5agg import (NavigationToolbar2QT as NavigationToolbar)from PyQt5.QtWidgets import QDialog, QFileDialogfrom PyQt5.QtGui import QIcon, QPixmap, QImagefrom PyQt5.uic import loadUiclass FormFeatureDetection(QMainWindow):def __init__(self):QMainWindow.__init__(self)loadUi("feature_detection.ui",self)self.setWindowTitle("Feature Detection")if __name__=="__main__":app = QApplication(sys.argv)w = FormFeatureDetection()w.show()sys.exit(app.exec_())
Define a new method, read_image(), to open file dialog, read file name, and display it in labelImage widget as follows:
def read_image(self):self.fname = QFileDialog.getOpenFileName(self, 'Open file','d:\\',"Image Files (*.jpg *.gif *.bmp *.png)")self.pixmap = QPixmap(self.fname[0])self.labelImage.setPixmap(self.pixmap)self.labelImage.setScaledContents(True)self.img = cv2.imread(self.fname[0], cv2.IMREAD_COLOR)
The img variable is then saved in self parameter of the FormFeatureDetection class.
Connect the clicked event of pbReadImage widget to readImage() method and put it inside __init_() method:
self.pbReadImage.clicked.connect(self.read_image)
Run feature_detection.py then click Read Image button to see displayed image in labelImage widget as shown in Figure below.
In feature_detection.ui form, put one Combo Box onto form and its objectName property to cboFeature. Double click on this widget and populate it with seven items as shown in Figure below.
Put one Group Box widget onto form and set its objectName property as gbHarris. Inside the group box, put four Line Edit widgets and set each objectName property to leBlockSize, leKSize, leK, and leThreshold. Set its text property of each to 2, 3, 0.04, and 0.01.
Then, put four Horizontal Slider widgets and set their objectName properties to hsBlockSize, hsKSize, hsK, and hsThreshold. Set minimum property of hsBlockSize and hsKSize widgets to 3. Set maximum property of hsKSize to 31.
Set singleStep property of hsKSize widget to 2. Set value property of hsBlockSize to 2, that of hsKSize to 3, that of hsK to 4, and that of hsThreshold to 1.
In feature_detection.ui form, put one Combo Box onto form and its objectName property to cboFeature. Double click on this widget and populate it with seven items as shown in Figure below.
Define a new method named initialization() to set state of some widgets as follows:
def initialization(self,state): self.cboFeature.setEnabled(state) self.gbHarris.setEnabled(state)
Invoke initialization() method from inside __init__() to disable widgets when form starts:
def __init__(self): QMainWindow.__init__(self) loadUi("feature_detection.ui",self) self.setWindowTitle("Feature Detection") self.pbReadImage.clicked.connect(self.read_image) self.initialization(False)
Modify read_image() to enable cboFeature widget as shown in line 8:
def read_image(self): self.fname = QFileDialog.getOpenFileName(self, 'Open file', \ 'd:\\',"Image Files (*.jpg *.gif *.bmp *.png)") self.pixmap = QPixmap(self.fname[0]) self.labelImage.setPixmap(self.pixmap) self.labelImage.setScaledContents(True) self.img = cv2.imread(self.fname[0], cv2.IMREAD_COLOR) self.cboFeature.setEnabled(True)
Run feature_detection.py. Make sure some widgets disabled when form first starts as shown in Figure below.
Then open one image, then you will see the image and makes sure cboFeature widget enabled as shown in Figure below.
Define a new method, choose_feature(), to read current text chosen and perform relevant task as follows:
def choose_feature(self): strCB = self.cboFeature.currentText() if strCB == 'Harris Corner Detection': self.gbHarris.setEnabled(True)
Connect currentIndexChanged() of cboFeature widget to choose_feature() and place it inside __init__() method as follows:
self.cboFeature.currentIndexChanged.connect(self.choose_feature)
Define four functions to display each slider handle value in Line Edit widget:
def set_hsBlockSize(self, value): self.leBlockSize.setText(str(value)) def set_hsKSize(self, value): self.leKSize.setText(str(value)) def set_hsK(self, value): self.leK.setText(str(round((value/100),2))) def set_hsThreshold(self, value): self.leThreshold.setText(str(round((value/100),2)))
Connect valueChanged event of hsBlockSize widget with set_hsBlockSize() method, that of hsKSize widget with set_hsKSize(), that of hsK widget with set_hsK(), and that of hsThreshold with set_hsThreshold(). Put them inside __init__() method:
def __init__(self): QMainWindow.__init__(self) loadUi("feature_detection.ui",self) self.setWindowTitle("Feature Detection") self.pbReadImage.clicked.connect(self.read_image) self.initialization(False) self.cboFeature.currentIndexChanged.connect(self.choose_feature) self.hsBlockSize.valueChanged.connect(self.set_hsBlockSize) self.hsKSize.valueChanged.connect(self.set_hsKSize) self.hsK.valueChanged.connect(self.set_hsK) self.hsThreshold.valueChanged.connect(self.set_hsThreshold)
Run feature_detection.py. Open an image, choose Harris Corner Detection from combo box, and drag the four horizontal sliders as you like. You will see the value in line edit widgets change as shown in Figure below.
Define display_image() method to display an image on a Label widget as follows:
def display_image(self, img, label): height, width, channel = img.shape bytesPerLine = 3 * width qImg = QImage(img, width, height, \ bytesPerLine, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qImg) label.setPixmap(pixmap) label.setScaledContents(True)
Define harris_detection() method to perform Harris Corner Detection technique as follows:
def harris_detection(self): self.test_im = self.img.copy() gray = cv2.cvtColor(self.test_im,cv2.COLOR_BGR2GRAY) gray = np.float32(gray) blockSize = int(self.leBlockSize.text()) kSize = int(self.leKSize.text()) K = float(self.leK.text()) dst = cv2.cornerHarris(gray,blockSize,kSize,K) #dilated for marking the corners dst = cv2.dilate(dst,None) # Threshold for an optimal value, Thresh = float(self.leThreshold.text()) self.test_im[dst>Thresh*dst.max()]=[0,0,255] cv2.cvtColor(self.test_im, cv2.COLOR_BGR2RGB, self.test_im) self.display_image(self.test_im, self.labelResult)
Modify these four methods to invoke harris_detection() as follows:
def set_hsBlockSize(self, value): self.leBlockSize.setText(str(value)) self.harris_detection() def set_hsKSize(self, value): self.leKSize.setText(str(value)) self.harris_detection() def set_hsK(self, value): self.leK.setText(str(round((value/100),2))) self.harris_detection() def set_hsThreshold(self, value): self.leThreshold.setText(str(round((value/100),2))) self.harris_detection()
Modify choose_feature() to invoke harris_detection() method when user choose Harris Corner Detection from combo box:
def choose_feature(self): strCB = self.cboFeature.currentText() if strCB == 'Harris Corner Detection': self.gbHarris.setEnabled(True) self.harris_detection()
Run feature_detection.py, open an image, and choose Harris Corner Detection from cboFeature. Choose the value of each parameter and see the result as shown in Figure below.
Below is the full script of feature_detection.py so far:
#feature_detection.py import sys import cv2 import numpy as np from PyQt5.QtWidgets import* from PyQt5 import QtGui, QtCore 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 from PyQt5.uic import loadUi class FormFeatureDetection(QMainWindow): def __init__(self): QMainWindow.__init__(self) loadUi("feature_detection.ui",self) self.setWindowTitle("Feature Detection") self.pbReadImage.clicked.connect(self.read_image) self.initialization(False) self.cboFeature.currentIndexChanged.connect(self.choose_feature) self.hsBlockSize.valueChanged.connect(self.set_hsBlockSize) self.hsKSize.valueChanged.connect(self.set_hsKSize) self.hsK.valueChanged.connect(self.set_hsK) self.hsThreshold.valueChanged.connect(self.set_hsThreshold) def read_image(self): self.fname = QFileDialog.getOpenFileName(self, 'Open file', \ 'd:\\',"Image Files (*.jpg *.gif *.bmp *.png)") self.pixmap = QPixmap(self.fname[0]) self.labelImage.setPixmap(self.pixmap) self.labelImage.setScaledContents(True) self.img = cv2.imread(self.fname[0], cv2.IMREAD_COLOR) self.cboFeature.setEnabled(True) def initialization(self,state): self.cboFeature.setEnabled(state) self.gbHarris.setEnabled(state) def set_hsBlockSize(self, value): self.leBlockSize.setText(str(value)) self.harris_detection() def set_hsKSize(self, value): self.leKSize.setText(str(value)) self.harris_detection() def set_hsK(self, value): self.leK.setText(str(round((value/100),2))) self.harris_detection() def set_hsThreshold(self, value): self.leThreshold.setText(str(round((value/100),2))) self.harris_detection() def choose_feature(self): strCB = self.cboFeature.currentText() if strCB == 'Harris Corner Detection': self.gbHarris.setEnabled(True) self.harris_detection() def harris_detection(self): self.test_im = self.img.copy() gray = cv2.cvtColor(self.test_im,cv2.COLOR_BGR2GRAY) gray = np.float32(gray) blockSize = int(self.leBlockSize.text()) kSize = int(self.leKSize.text()) K = float(self.leK.text()) dst = cv2.cornerHarris(gray,blockSize,kSize,K) #dilated for marking the corners dst = cv2.dilate(dst,None) # Threshold for an optimal value, it may vary depending on the image. Thresh = float(self.leThreshold.text()) self.test_im[dst>Thresh*dst.max()]=[0,0,255] cv2.cvtColor(self.test_im, cv2.COLOR_BGR2RGB, self.test_im) self.display_image(self.test_im, self.labelResult) def display_image(self, img, label): height, width, channel = img.shape bytesPerLine = 3 * width qImg = QImage(img, width, height, \ bytesPerLine, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qImg) label.setPixmap(pixmap) label.setScaledContents(True) if __name__=="__main__": app = QApplication(sys.argv) w = FormFeatureDetection() w.show() sys.exit(app.exec_())
Feature Detection Using Python GUI (PyQt) Part 2
No comments:
Post a Comment