This content is powered by Balige Publishing. Visit this link
The following is image_processing.py script so far:
Edge Detection, Segmentation, and Denoising on Images with Python GUI (PyQt): Part 3
Part 1
Modify image_proc.ui, put one Combo Box onto form and its objectName property to cboEdge. Double click on this widget and populate it with four items as shown in Figure below.
Then, put three Spin Box widgets and set their objectName properties to sbMinVal, sbMaxVal, and sbKernel. Set minimum property of each widget to 0, 0, and 3. Set maximum property of each widget to 255. Set singleStep property of each widget to 1, 1, and 2.
Put three Line Edit widgets onto form and set each objectName property to leMinVal, leMaxVal, and leKernel. Set its text property of each to 0, 0, and 3.
Save form with the same name. Now, the form looks as shown in Figure above.
Modify setState() to set state’s application as follows:
def setState(self, state):if state == 'START':self.cboNoise.setEnabled(False)self.hsMean.setEnabled(False)self.hsVar.setEnabled(False)self.hsAmount.setEnabled(False)self.leMean.setEnabled(False)self.leVar.setEnabled(False)self.leAmount.setEnabled(False)self.leMinVal.setEnabled(False)self.leMaxVal.setEnabled(False)self.leKernel.setEnabled(False)self.sbMinVal.setEnabled(False)self.sbMaxVal.setEnabled(False)self.sbKernel.setEnabled(False)self.cboEdge.setEnabled(False)else:self.cboNoise.setEnabled(True)self.hsMean.setEnabled(True)self.hsVar.setEnabled(True)self.hsAmount.setEnabled(True)self.leMean.setEnabled(True)self.leVar.setEnabled(True)self.leAmount.setEnabled(True)self.leMinVal.setEnabled(True)self.leMaxVal.setEnabled(True)self.leKernel.setEnabled(True)self.sbMinVal.setEnabled(True)self.sbMaxVal.setEnabled(True)self.sbKernel.setEnabled(True)self.cboEdge.setEnabled(True)
Define the two new methods named do_edge() and choose_edge() as follows:
def choose_edge(self,img):strCB = self.cboEdge.currentText()minVal = float(self.leMinVal.text())maxVal = float(self.leMaxVal.text())kernel = int(self.leKernel.text())noisy = self.choose_noise(img)if strCB == 'Canny':self.leKernel.setEnabled(False)self.sbKernel.setEnabled(False)self.leMinVal.setEnabled(True)self.sbMinVal.setEnabled(True)self.leMaxVal.setEnabled(True)self.sbMaxVal.setEnabled(True)edge_im = self.canny_edge(noisy, minVal, maxVal)return edge_imif strCB == 'Sobel X':self.leKernel.setEnabled(True)self.sbKernel.setEnabled(True)self.leMinVal.setEnabled(False)self.sbMinVal.setEnabled(False)self.leMaxVal.setEnabled(False)self.sbMaxVal.setEnabled(False)edge_im = self.sobelx_edge(noisy, 1, 0, kernel)return edge_imif strCB == 'Sobel Y':self.leKernel.setEnabled(True)self.sbKernel.setEnabled(True)self.leMinVal.setEnabled(False)self.sbMinVal.setEnabled(False)self.leMaxVal.setEnabled(False)self.sbMaxVal.setEnabled(False)edge_im = self.sobelx_edge(noisy, 0, 1, kernel)return edge_imif strCB == 'Laplacian':self.leKernel.setEnabled(True)self.sbKernel.setEnabled(True)self.leMinVal.setEnabled(False)self.sbMinVal.setEnabled(False)self.leMaxVal.setEnabled(False)self.sbMaxVal.setEnabled(False)edge_im = self.laplacian_edge(noisy, kernel)return edge_im
def do_edge(self):edges = self.choose_edge(img)height, width, channel = edges.shapebytesPerLine = 3 * widthcv2.cvtColor(edges, cv2.COLOR_BGR2RGB, edges)qImg = QImage(edges, width, height, \bytesPerLine, QImage.Format_RGB888)pixmap = QPixmap.fromImage(qImg)self.display_image(pixmap, edges, self.labelFilter, \self.widgetHistFilter, 'Histogram of Edge Detection')
In choose_edge(), there are four methods invoking to perform edge detection on image:
def canny_edge(self, img, minVal, maxVal):edge_im = np.zeros(img.shape, np.float32)if len(img.shape) == 2:edge_im = cv2.Canny(img,minVal, maxVal)else:edge_im[:, :, 0] = cv2.Canny(img[:, :, 0],minVal, maxVal)edge_im[:, :, 1] = cv2.Canny(img[:, :, 1],minVal, maxVal)edge_im[:, :, 2] = cv2.Canny(img[:, :, 2],minVal, maxVal)cv2.normalize(edge_im, edge_im, 0, 255, \cv2.NORM_MINMAX, dtype=-1)edge_im = edge_im.astype(np.uint8)return edge_imdef sobelx_edge(self, img, d1, d2, kernel):edge_im = np.zeros(img.shape, np.float32)if len(img.shape) == 2:edge_im = cv2.Sobel(img,cv2.CV_64F, d1, d2, kernel)else:edge_im[:, :, 0] = cv2.Sobel(img[:, :, 0],\cv2.CV_64F, d1, d2, kernel)edge_im[:, :, 1] = cv2.Sobel(img[:, :, 1],\cv2.CV_64F, d1, d2, kernel)edge_im[:, :, 2] = cv2.Sobel(img[:, :, 2],\cv2.CV_64F, d1, d2, kernel)cv2.normalize(edge_im, edge_im, 0, 255, \cv2.NORM_MINMAX, dtype=-1)edge_im = edge_im.astype(np.uint8)return edge_imdef laplacian_edge(self, img, kernel):edge_im = np.zeros(img.shape, np.float32)if len(img.shape) == 2:edge_im = cv2.Laplacian(img, cv2.CV_64F, kernel)else:edge_im[:, :, 0] = cv2.Laplacian(img[:, :, 0], \cv2.CV_64F, kernel)edge_im[:, :, 1] = cv2.Laplacian(img[:, :, 1], \cv2.CV_64F, kernel)edge_im[:, :, 2] = cv2.Laplacian(img[:, :, 2], \cv2.CV_64F, kernel)cv2.normalize(edge_im, edge_im, 0, 255, \cv2.NORM_MINMAX, dtype=-1)edge_im = edge_im.astype(np.uint8)return edge_im
Connect currentIndexChanged() of cboEdge widget to do_edge() and place it inside __init__() method as follows:
self.cboEdge.currentIndexChanged.connect(self.do_edge)
Define set_minval(), set_maxval(), and set_kernel() to invoke do_edge() as follows:
def set_minval(self):self.leMinVal.setText(str(self.sbMinVal.value()))self.do_edge()def set_maxval(self):self.leMaxVal.setText(str(self.sbMaxVal.value()))self.do_edge()def set_kernel(self):self.leKernel.setText(str(self.sbKernel.value()))self.do_edge()
Connect textEdited() event of leMinVal, MaxVal and leKernel widgets to do_edge(). Connect valueChanged() signal of sbMinVal to set_minval() method. Connect valueChanged() signal of sbMaxVal to set_maxval(). Connect valueChanged() signal of sbKernel to set_kernel().
place them all inside __init__() method as follows:
def __init__(self):QMainWindow.__init__(self)loadUi("image_proc.ui",self)self.setWindowTitle("Image Processing")self.pbImage.clicked.connect(self.open_file)self.setState('START')self.hsMean.valueChanged.connect(self.set_hsMean)self.hsVar.valueChanged.connect(self.set_hsVar)self.hsAmount.valueChanged.connect(self.set_hsAmount)self.leMean.textEdited.connect(self.do_noise)self.leVar.textEdited.connect(self.do_noise)self.leAmount.textEdited.connect(self.do_noise)self.cboNoise.currentIndexChanged.connect(self.do_noise)self.sbMinVal.valueChanged.connect(self.set_minval)self.sbMaxVal.valueChanged.connect(self.set_maxval)self.sbKernel.valueChanged.connect(self.set_kernel)self.leMinVal.textEdited.connect(self.do_edge)self.leMaxVal.textEdited.connect(self.do_edge)self.leKernel.textEdited.connect(self.do_edge)self.cboEdge.currentIndexChanged.connect(self.do_edge)
Run image_processing.py. Choose input image and you can choose mean, variance, or amount/peak values to generate noisy image using horizontal sliders. Then, you can choose edge detector by selecting different item in cboEdge as shown in both figures below.
The following is image_processing.py script so far:
#image_processing.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 from PIL import Image from skimage.util import random_noise import numpy as np fname = "" class FormImageProcessing(QMainWindow): def __init__(self): QMainWindow.__init__(self) loadUi("image_proc.ui",self) self.setWindowTitle("Image Processing") self.pbImage.clicked.connect(self.open_file) self.setState('START') self.hsMean.valueChanged.connect(self.set_hsMean) self.hsVar.valueChanged.connect(self.set_hsVar) self.hsAmount.valueChanged.connect(self.set_hsAmount) self.leMean.textEdited.connect(self.do_noise) self.leVar.textEdited.connect(self.do_noise) self.leAmount.textEdited.connect(self.do_noise) self.cboNoise.currentIndexChanged.connect(self.do_noise) self.sbMinVal.valueChanged.connect(self.set_minval) self.sbMaxVal.valueChanged.connect(self.set_maxval) self.sbKernel.valueChanged.connect(self.set_kernel) self.leMinVal.textEdited.connect(self.do_edge) self.leMaxVal.textEdited.connect(self.do_edge) self.leKernel.textEdited.connect(self.do_edge) self.cboEdge.currentIndexChanged.connect(self.do_edge) def open_file(self): global img fname = QFileDialog.getOpenFileName(self, 'Open file', 'd:\\',"Image Files (*.jpg *.gif *.bmp *.png)") pixmap = QPixmap(fname[0]) img = cv2.imread(fname[0], cv2.IMREAD_COLOR) self.display_image(pixmap, img, self.labelImage, self.widgetHistIm,\ 'Histogram of Original Image') self.setState('RUN') self.hsAmount.setEnabled(False) self.leAmount.setEnabled(False) def display_image(self, pixmap, img, label, qwidget1, title): label.setPixmap(pixmap) label.setScaledContents(True); self.display_histogram(img, qwidget1, title) def display_histogram(self, img, qwidget1, title): qwidget1.canvas.axes1.clear() channel = len(img.shape) if channel == 2: #grayscale image histr = cv2.calcHist([img],[0],None,[256],[0,256]) qwidget1.canvas.axes1.plot(histr,\ color = 'yellow',linewidth=3.0) qwidget1.canvas.axes1.set_ylabel('Frequency',\ color='white') qwidget1.canvas.axes1.set_xlabel('Intensity', \ color='white') qwidget1.canvas.axes1.tick_params(axis='x', colors='white') qwidget1.canvas.axes1.tick_params(axis='y', colors='white') qwidget1.canvas.axes1.set_title(title,color='white') qwidget1.canvas.axes1.set_facecolor('xkcd:black') qwidget1.canvas.axes1.grid() qwidget1.canvas.draw() else : #color image color = ('b','g','r') for i,col in enumerate(color): histr = cv2.calcHist([img],[i],None,[256],[0,256]) qwidget1.canvas.axes1.plot(histr,\ color = col,linewidth=3.0) qwidget1.canvas.axes1.set_ylabel('Frequency',\ color='white') qwidget1.canvas.axes1.set_xlabel('Intensity', \ color='white') qwidget1.canvas.axes1.tick_params(axis='x', colors='white') qwidget1.canvas.axes1.tick_params(axis='y', colors='white') qwidget1.canvas.axes1.set_title(title,color='white') qwidget1.canvas.axes1.set_facecolor('xkcd:black') qwidget1.canvas.axes1.grid() qwidget1.canvas.draw() def setState(self, state): if state == 'START': self.cboNoise.setEnabled(False) self.hsMean.setEnabled(False) self.hsVar.setEnabled(False) self.hsAmount.setEnabled(False) self.leMean.setEnabled(False) self.leVar.setEnabled(False) self.leAmount.setEnabled(False) self.leMinVal.setEnabled(False) self.leMaxVal.setEnabled(False) self.leKernel.setEnabled(False) self.sbMinVal.setEnabled(False) self.sbMaxVal.setEnabled(False) self.sbKernel.setEnabled(False) self.cboEdge.setEnabled(False) else: self.cboNoise.setEnabled(True) self.hsMean.setEnabled(True) self.hsVar.setEnabled(True) self.hsAmount.setEnabled(True) self.leMean.setEnabled(True) self.leVar.setEnabled(True) self.leAmount.setEnabled(True) self.leMinVal.setEnabled(True) self.leMaxVal.setEnabled(True) self.leKernel.setEnabled(True) self.sbMinVal.setEnabled(True) self.sbMaxVal.setEnabled(True) self.sbKernel.setEnabled(True) self.cboEdge.setEnabled(True) def set_hsMean(self, value): self.leMean.setText(str(round((value/64),2))) self.do_noise() def set_hsVar(self, value): self.leVar.setText(str(round((value/64),2))) self.do_noise() def set_hsAmount(self, value): self.leAmount.setText(str(round((value/10),2))) self.do_noise() def choose_noise(self,img): strCB = self.cboNoise.currentText() mean = float(self.leMean.text()) var = float(self.leVar.text()) amount = float(self.leAmount.text()) sigma = var**0.5 row,col,ch= img.shape if strCB == 'Gaussian': self.hsAmount.setEnabled(False) self.leAmount.setEnabled(False) self.hsMean.setEnabled(True) self.leMean.setEnabled(True) self.hsVar.setEnabled(True) self.leVar.setEnabled(True) noisy_image = self.gaussian_noise(img, mean, sigma, row, col) return noisy_image if strCB == 'Speckle': self.hsAmount.setEnabled(False) self.leAmount.setEnabled(False) self.hsMean.setEnabled(True) self.leMean.setEnabled(True) self.hsVar.setEnabled(True) self.leVar.setEnabled(True) noisy_image = self.speckle_noise(img, mean, sigma, row, col) return noisy_image if strCB == 'Poisson': self.hsMean.setEnabled(False) self.leMean.setEnabled(False) self.hsVar.setEnabled(False) self.leVar.setEnabled(False) self.hsAmount.setEnabled(True) self.leAmount.setEnabled(True) noisy_image = self.poisson_noise(img, amount) return noisy_image if strCB == 'Salt & Pepper': self.hsMean.setEnabled(False) self.leMean.setEnabled(False) self.hsVar.setEnabled(False) self.leVar.setEnabled(False) self.hsAmount.setEnabled(True) self.leAmount.setEnabled(True) noisy_image = self.salt_pepper_noise(img, amount) return noisy_image def gaussian_noise2(self,img, mean, sigma, row, col): gaussian = np.random.normal(mean, sigma, (row,col)) noisy_image = np.zeros(img.shape, np.float32) if len(img.shape) == 2: noisy_image = img + gaussian else: noisy_image[:, :, 0] = img[:, :, 0] + gaussian noisy_image[:, :, 1] = img[:, :, 1] + gaussian noisy_image[:, :, 2] = img[:, :, 2] + gaussian cv2.normalize(noisy_image, noisy_image, 0, 255, \ cv2.NORM_MINMAX, dtype=-1) noisy_image = noisy_image.astype(np.uint8) return noisy_image def speckle_noise2(self,img, mean, sigma, row, col): gaussian = np.random.normal(mean, sigma, (row,col)) noisy_image = np.zeros(img.shape, np.float32) if len(img.shape) == 2: noisy_image = img + img*gaussian else: noisy_image[:, :, 0] = img[:, :, 0] + gaussian * img[:, :, 0] noisy_image[:, :, 1] = img[:, :, 1] + gaussian * img[:, :, 1] noisy_image[:, :, 2] = img[:, :, 2] + gaussian * img[:, :, 2] cv2.normalize(noisy_image, noisy_image, 0, 255, \ cv2.NORM_MINMAX, dtype=-1) noisy_image = noisy_image.astype(np.uint8) return noisy_image def gaussian_noise(self,img, mean, sigma, row, col): # Generate Gaussian noise gauss = np.random.normal(mean,sigma,img.size) gauss = gauss.reshape(img.shape[0],\ img.shape[1],img.shape[2]).astype('uint8') # Add the Gaussian noise to the image img_gauss = cv2.add(img,gauss) return img_gauss def speckle_noise(self,img, mean, sigma, row, col): # Generate Gaussian noise gauss = np.random.normal(mean,sigma,img.size) gauss = gauss.reshape(img.shape[0],\ img.shape[1],img.shape[2]).astype('uint8') # Add the Gaussian noise to the image img_sp = cv2.add(img,img*gauss) return img_sp def salt_pepper_noise(self, img, val): # Add salt-and-pepper noise to the image. noise_img = random_noise(img, mode='s&p',amount=val) # The above function returns a floating-point image # on the range [0, 1], thus we changed it to 'uint8' # and from [0,255] imgsnp = np.array(255*noise_img, dtype = 'uint8') return imgsnp def poisson_noise(self, img, peak): pois = np.random.poisson(img / 255.0 * peak) / peak * 255 # The above function returns a floating-point image # on the range [0, 1], thus we changed it to 'uint8' # and from [0,255] imgpois = np.array(255*pois, dtype = 'uint8') return imgpois def do_noise(self): noisy = self.choose_noise(img) height, width, channel = noisy.shape bytesPerLine = 3 * width cv2.cvtColor(noisy, cv2.COLOR_BGR2RGB, noisy) qImg = QImage(noisy, width, height, \ bytesPerLine, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qImg) self.display_image(pixmap, noisy, self.labelFilter, \ self.widgetHistFilter, 'Histogram of Noisy Image') def choose_edge(self,img): strCB = self.cboEdge.currentText() minVal = float(self.leMinVal.text()) maxVal = float(self.leMaxVal.text()) kernel = int(self.leKernel.text()) noisy = self.choose_noise(img) if strCB == 'Canny': self.leKernel.setEnabled(False) self.sbKernel.setEnabled(False) self.leMinVal.setEnabled(True) self.sbMinVal.setEnabled(True) self.leMaxVal.setEnabled(True) self.sbMaxVal.setEnabled(True) edge_im = self.canny_edge(noisy, minVal, maxVal) return edge_im if strCB == 'Sobel X': self.leKernel.setEnabled(True) self.sbKernel.setEnabled(True) self.leMinVal.setEnabled(False) self.sbMinVal.setEnabled(False) self.leMaxVal.setEnabled(False) self.sbMaxVal.setEnabled(False) edge_im = self.sobelx_edge(noisy, 1, 0, kernel) return edge_im if strCB == 'Sobel Y': self.leKernel.setEnabled(True) self.sbKernel.setEnabled(True) self.leMinVal.setEnabled(False) self.sbMinVal.setEnabled(False) self.leMaxVal.setEnabled(False) self.sbMaxVal.setEnabled(False) edge_im = self.sobelx_edge(noisy, 0, 1, kernel) return edge_im if strCB == 'Laplacian': self.leKernel.setEnabled(True) self.sbKernel.setEnabled(True) self.leMinVal.setEnabled(False) self.sbMinVal.setEnabled(False) self.leMaxVal.setEnabled(False) self.sbMaxVal.setEnabled(False) edge_im = self.laplacian_edge(noisy, kernel) return edge_im def canny_edge(self, img, minVal, maxVal): edge_im = np.zeros(img.shape, np.float32) if len(img.shape) == 2: edge_im = cv2.Canny(img,minVal, maxVal) else: edge_im[:, :, 0] = cv2.Canny(img[:, :, 0],minVal, maxVal) edge_im[:, :, 1] = cv2.Canny(img[:, :, 1],minVal, maxVal) edge_im[:, :, 2] = cv2.Canny(img[:, :, 2],minVal, maxVal) cv2.normalize(edge_im, edge_im, 0, 255, cv2.NORM_MINMAX, dtype=-1) edge_im = edge_im.astype(np.uint8) return edge_im def sobelx_edge(self, img, d1, d2, kernel): edge_im = np.zeros(img.shape, np.float32) if len(img.shape) == 2: edge_im = cv2.Sobel(img,cv2.CV_64F, d1, d2, kernel) else: edge_im[:, :, 0] = cv2.Sobel(img[:, :, 0],\ cv2.CV_64F, d1, d2, kernel) edge_im[:, :, 1] = cv2.Sobel(img[:, :, 1],\ cv2.CV_64F, d1, d2, kernel) edge_im[:, :, 2] = cv2.Sobel(img[:, :, 2],\ cv2.CV_64F, d1, d2, kernel) cv2.normalize(edge_im, edge_im, 0, 255, cv2.NORM_MINMAX, dtype=-1) edge_im = edge_im.astype(np.uint8) return edge_im def laplacian_edge(self, img, kernel): edge_im = np.zeros(img.shape, np.float32) if len(img.shape) == 2: edge_im = cv2.Laplacian(img, cv2.CV_64F, kernel) else: edge_im[:, :, 0] = cv2.Laplacian(img[:, :, 0], cv2.CV_64F, kernel) edge_im[:, :, 1] = cv2.Laplacian(img[:, :, 1], cv2.CV_64F, kernel) edge_im[:, :, 2] = cv2.Laplacian(img[:, :, 2], cv2.CV_64F, kernel) cv2.normalize(edge_im, edge_im, 0, 255, cv2.NORM_MINMAX, dtype=-1) edge_im = edge_im.astype(np.uint8) return edge_im def do_edge(self): edges = self.choose_edge(img) height, width, channel = edges.shape bytesPerLine = 3 * width cv2.cvtColor(edges, cv2.COLOR_BGR2RGB, edges) qImg = QImage(edges, width, height, \ bytesPerLine, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qImg) self.display_image(pixmap, edges, self.labelFilter, \ self.widgetHistFilter, 'Histogram of Edge Detection') def set_minval(self): self.leMinVal.setText(str(self.sbMinVal.value())) self.do_edge() def set_maxval(self): self.leMaxVal.setText(str(self.sbMaxVal.value())) self.do_edge() def set_kernel(self): self.leKernel.setText(str(self.sbKernel.value())) self.do_edge() if __name__=="__main__": import sys app = QApplication(sys.argv) w = FormImageProcessing() w.show() sys.exit(app.exec_())
Edge Detection, Segmentation, and Denoising on Images with Python GUI (PyQt): Part 3