This content is powered by Balige Publishing. Visit this link
Add a new statement to import KMeans algorithm from sklearn package:
Define a new method, kmeans_seg(), to implement K-Means algorithm as follows:
Define a new method, seg_output(), to display segmented image and its histogram as follows:
Define rbstate() method to determine which radio button is clicked by user as follows:
Connect toggled() event of rbMultiple and rbKMeans to rbState() method and put them inside __init__() method as follows:
Run image_processing.py. Choose test image and click on rbMultiple widget. The result is shown in Figure below.
The following is image_processing.py script so far:
Edge Detection, Segmentation, and Denoising on Images with Python GUI (PyQt): Part 4
Part 1 Part 2
Tutorial Steps To Implement Image Segmentation Using Multiple Thresholding and K-Means Algorithm
Modify image_proc.ui, put two Radio Button widgets onto form and set their objectName properties to rbMultiple and rbKMeans. Set their text properties to Multiple Thresholding and K-Means Algorithm. Then, save form with the same name. Now, the form looks as shown in Figure below.
Define two new methods, multiple_thresh() and thresh_seg(), to implement multiple thresholding segmentation as follows:
def thresh_seg(self,img): img_seg = np.zeros(img.shape, np.float32) if len(img.shape) == 2: img_seg = self.multiple_thresh(img) else: img_seg[:, :, 0] = self.multiple_thresh(img[:, :, 0]) img_seg[:, :, 1] = self.multiple_thresh(img[:, :, 1]) img_seg[:, :, 2] = self.multiple_thresh(img[:, :, 2]) cv2.normalize(img_seg, img_seg, 0, 255, \ cv2.NORM_MINMAX, dtype=-1) img_seg = img_seg.astype(np.uint8) return img_seg def multiple_thresh(self, img): img_thresh= 255*img.reshape(img.shape[0]*img.shape[1]) thresh_mean = img_thresh.mean() for i in range(img_thresh.shape[0]): if img_thresh[i] > thresh_mean: img_thresh[i] = 3 elif img_thresh[i] > 0.5: img_thresh[i] = 2 elif img_thresh[i] > 0.25: img_thresh[i] = 1 else: img_thresh[i] = 0 img_mul = img_thresh.reshape(img.shape[0],img.shape[1]) return img_mul
Add a new statement to import KMeans algorithm from sklearn package:
from sklearn.cluster import KMeans
Define a new method, kmeans_seg(), to implement K-Means algorithm as follows:
def kmeans_seg(self,img): img_seg = np.zeros(img.shape, np.float32) img_n = img.reshape(img.shape[0]*img.shape[1], img.shape[2]) kmeans = KMeans(n_clusters=5, random_state=0).fit(img_n) pic2show = kmeans.cluster_centers_[kmeans.labels_] img_seg = pic2show.reshape(img.shape[0], img.shape[1], \ img.shape[2]) cv2.normalize(img_seg, img_seg, 0, 255, \ cv2.NORM_MINMAX, dtype=-1) img_seg = img_seg.astype(np.uint8) return img_seg
Define a new method, seg_output(), to display segmented image and its histogram as follows:
def seg_output(self,output): height, width, channel = output.shape bytesPerLine = 3 * width cv2.cvtColor(output, cv2.COLOR_BGR2RGB, output) qImg = QImage(output, width, height, \ bytesPerLine, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qImg) self.display_image(pixmap, output, self.labelFilter, \ self.widgetHistFilter, 'Histogram of Segmented Image')
Define rbstate() method to determine which radio button is clicked by user as follows:
def rbstate(self): noisy = self.choose_noise(img) if self.rbMultiple.isChecked() == True: output = self.thresh_seg(noisy) self.seg_output(output) if self.rbKMeans.isChecked() == True: output = self.kmeans_seg(noisy) self.seg_output(output)
Connect toggled() event of rbMultiple and rbKMeans to rbState() method and put them inside __init__() method as follows:
self.rbMultiple.toggled.connect(self.rbstate) self.rbKMeans.toggled.connect(self.rbstate)
Run image_processing.py. Choose test image and click on rbMultiple widget. The result is shown in Figure 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 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 PIL import Image from skimage.util import random_noise from sklearn.cluster import KMeans from skimage.segmentation import active_contour from skimage.filters import gaussian import skimage.color as color 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) self.rbMultiple.toggled.connect(self.rbstate) self.rbKMeans.toggled.connect(self.rbstate) def thresh_seg(self,img): img_seg = np.zeros(img.shape, np.float32) if len(img.shape) == 2: img_seg = self.multiple_thresh(img) else: img_seg[:, :, 0] = self.multiple_thresh(img[:, :, 0]) img_seg[:, :, 1] = self.multiple_thresh(img[:, :, 1]) img_seg[:, :, 2] = self.multiple_thresh(img[:, :, 2]) cv2.normalize(img_seg, img_seg, 0, 255, cv2.NORM_MINMAX, dtype=-1) img_seg = img_seg.astype(np.uint8) return img_seg def multiple_thresh(self, img): img_thresh= 255*img.reshape(img.shape[0]*img.shape[1]) thresh_mean = img_thresh.mean() for i in range(img_thresh.shape[0]): if img_thresh[i] > thresh_mean: img_thresh[i] = 3 elif img_thresh[i] > 0.5: img_thresh[i] = 2 elif img_thresh[i] > 0.25: img_thresh[i] = 1 else: img_thresh[i] = 0 img_mul = img_thresh.reshape(img.shape[0],img.shape[1]) return img_mul def kmeans_seg(self,img): img_seg = np.zeros(img.shape, np.float32) img_n = img.reshape(img.shape[0]*img.shape[1], img.shape[2]) kmeans = KMeans(n_clusters=5, random_state=0).fit(img_n) pic2show = kmeans.cluster_centers_[kmeans.labels_] img_seg = pic2show.reshape(img.shape[0], img.shape[1], img.shape[2]) cv2.normalize(img_seg, img_seg, 0, 255, cv2.NORM_MINMAX, dtype=-1) img_seg = img_seg.astype(np.uint8) return img_seg def rbstate(self): noisy = self.choose_noise(img) if self.rbMultiple.isChecked() == True: output = self.thresh_seg(noisy) self.seg_output(output) if self.rbKMeans.isChecked() == True: output = self.kmeans_seg(noisy) self.seg_output(output) def seg_output(self,output): height, width, channel = output.shape bytesPerLine = 3 * width cv2.cvtColor(output, cv2.COLOR_BGR2RGB, output) qImg = QImage(output, width, height, \ bytesPerLine, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qImg) self.display_image(pixmap, output, self.labelFilter, self.widgetHistFilter, 'Histogram of Segmented Image') def open_file(self): global img self.fname = QFileDialog.getOpenFileName(self, 'Open file', 'd:\\',"Image Files (*.jpg *.gif *.bmp *.png)") pixmap = QPixmap(self.fname[0]) img = cv2.imread(self.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)) # np.zeros((224, 224), np.float32) 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)) # np.zeros((224, 224), np.float32) 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 4
No comments:
Post a Comment