This content is powered by Balige Publishing. Visit this link
See Part 1
Modify setState() as follows:
Define new method named do_adapt_thresh() to implement adaptive image thresholding as follows:
Modify thresholding_tech() method by adding code in line 5-6 and 24-31 as follows:
Run image_thresholding.py and see the results of applying adaptive image thresholding as shown in figures below.
See Part 1
Tutorial Steps To Implement Adaptive Image Thresholding
Adaptive thresholding has three ‘special’ input params and only one output argument. It decides how thresholding value is calculated:
Adaptive thresholding has three ‘special’ input params and only one output argument. It decides how thresholding value is calculated:
Put two more Line Edit widgets on form and set their objectName properties to leBlockSize and leConst. Set their text properties to 11 and 2.
Then, put two Spin Box widgets and set their objectName properties to sbBlockSize and sbConst. Set their minimum properties to 1, set their value properties to 11 and 2, and set their singleStep properties to 2 and 1.
Modify setState() as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | def setState(self, state): if state == 'START': self.cboThresholding.setEnabled(False) self.hsMinVal.setEnabled(False) self.hsMaxVal.setEnabled(False) self.leMinVal.setEnabled(False) self.leMaxVal.setEnabled(False) self.lwChannel.setEnabled(False) self.twIntensity.setEnabled(False) self.leBlockSize.setEnabled(False) self.sbBlockSize.setEnabled(False) self.leConst.setEnabled(False) self.sbConst.setEnabled(False) else: self.cboThresholding.setEnabled(True) self.hsMinVal.setEnabled(True) self.hsMaxVal.setEnabled(True) self.leMinVal.setEnabled(True) self.leMaxVal.setEnabled(True) self.lwChannel.setEnabled(True) self.twIntensity.setEnabled(True) self.leBlockSize.setEnabled(True) self.sbBlockSize.setEnabled(True) self.leConst.setEnabled(True) self.sbConst.setEnabled(True) |
Define two new methods, set_blocksize() and set_const(), to display value property of both spin box widgets on line edit widgets. Both methods also invoke image_thresh() method:
1 2 3 4 5 6 7 | def set_blockSize(self): self.leBlockSize.setText(str(self.sbBlockSize.value())) self.image_thresh() def set_const(self): self.leConst.setText(str(self.sbConst.value())) self.image_thresh() |
Inside __init__(), connect valueChanged() signal of sbBlockSize with set_blockSize() method, connect valueChanged() signal of sbConst with set_const() method, connect textEdited() signal of leBlockSize with image_thresh() method, and connect textEdited() signal of leConst with image_thresh() method.
1 2 3 4 | self.sbBlockSize.valueChanged.connect(self.set_blockSize) self.sbConst.valueChanged.connect(self.set_const) self.leBlockSize.textEdited.connect(self.image_thresh) self.leConst.textEdited.connect(self.image_thresh) |
Define new method named do_adapt_thresh() to implement adaptive image thresholding as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | def do_adapt_thresh(self, img, maxVal, blockSize, Const, \ method1, method2,title): channel = len(img.shape) if channel == 2: #grayscale image img_blur = cv2.medianBlur(img,blockSize) thresh = cv2.adaptiveThreshold(img_blur,maxVal,method1, \ method2, blockSize,Const) qmap = QImage(thresh.data, thresh.shape[1], \ thresh.shape[0], QImage.Format_Grayscale8) pixmap = QPixmap.fromImage(qmap) else: # color image img_blur = cv2.medianBlur(img,blockSize) b, g, r = cv2.split(img_blur) threshb = cv2.adaptiveThreshold(b,maxVal,method1, \ method2, blockSize,Const) threshg = cv2.adaptiveThreshold(g,maxVal,method1, \ method2, blockSize,Const) threshr = cv2.adaptiveThreshold(r,maxVal,method1, \ method2, blockSize,Const) thresh = cv2.merge((threshb, threshg, threshr)) height, width, channel = thresh.shape bytesPerLine = 3 * width # To convert back from BGR to RGB space color cv2.cvtColor(thresh, cv2.COLOR_BGR2RGB, thresh) qImg = QImage(thresh.data, width, height, \ bytesPerLine, QImage.Format_RGB888) pixmap = QPixmap.fromImage(qImg) self.display_image(pixmap, thresh, self.labelThresh, \ self.widgetHistThresh, title) |
Modify thresholding_tech() method by adding code in line 5-6 and 24-31 as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | def thresholding_tech(self,img): strCB = self.cboThresholding.currentText() minVal = int(self.leMinVal.text()) maxVal = int(self.leMaxVal.text()) blockSize = int(self.leBlockSize.text()) Const = int(self.leConst.text()) if strCB == 'THRESH_BINARY': self.do_thresh(img, minVal, maxVal, cv2.THRESH_BINARY, \ 'Histogram of Thresholded Image with ' + strCB) if strCB == 'THRESH_BINARY_INV': self.do_thresh(img, minVal, maxVal, cv2.THRESH_BINARY_INV, \ 'Histogram of Thresholded Image with ' + strCB) if strCB == 'THRESH_TRUNC': self.do_thresh(img, minVal, maxVal, cv2.THRESH_TRUNC, \ 'Histogram of Thresholded Image with ' + strCB) if strCB == 'THRESH_TOZERO': self.do_thresh(img, minVal, maxVal, \ cv2.THRESH_TOZERO,\ 'Histogram of Thresholded Image with ' + strCB) if strCB == 'THRESH_TOZERO_INV': self.do_thresh(img, minVal, maxVal, cv2.THRESH_TOZERO_INV, \ 'Histogram of Thresholded Image with ' + strCB) if strCB == 'ADAPTIVE_THRESH_MEAN_C': self.do_adapt_thresh(img, 255, blockSize, Const, \ cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, \ 'Histogram of Thresholded Image with ' + strCB) if strCB == 'ADAPTIVE_THRESH_GAUSSIAN_C': self.do_adapt_thresh(img, 255, blockSize, Const, \ cv2.cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, \ 'Histogram of Thresholded Image with ' + strCB) |
Run image_thresholding.py and see the results of applying adaptive image thresholding as shown in figures below.
The following is the final version of image_thresholding.py:
#image_thresholding.pyimport cv2import numpy as npfrom PyQt5.QtWidgets import*from PyQt5.uic import loadUifrom matplotlib.backends.backend_qt5agg import (NavigationToolbar2QT as NavigationToolbar)from PyQt5.QtWidgets import QDialog, QFileDialogfrom PyQt5.QtGui import QIcon, QPixmap, QImagefrom PIL import Imageimport numpy as npfname = ""class FormThresholding(QMainWindow):def __init__(self):QMainWindow.__init__(self)loadUi("image_thresh.ui",self)self.setWindowTitle("Image Thresholding")self.pbImage.clicked.connect(self.open_file)self.setState('START')self.hsMinVal.valueChanged.connect(self.set_hsMinVal)self.hsMaxVal.valueChanged.connect(self.set_hsMaxVal)self.cboThresholding.currentIndexChanged.connect(self.image_thresh)self.leMinVal.textEdited.connect(self.image_thresh)self.leMaxVal.textEdited.connect(self.image_thresh)self.lwChannel.clicked.connect(self.channel_thresh)self.sbBlockSize.valueChanged.connect(self.set_blockSize)self.sbConst.valueChanged.connect(self.set_const)self.leBlockSize.textEdited.connect(self.image_thresh)self.leConst.textEdited.connect(self.image_thresh)def open_file(self):global fnamefname = 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')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 imagehistr = 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 imagecolor = ('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 set_hsMinVal(self, value):self.leMinVal.setText(str(value))self.image_thresh()def set_hsMaxVal(self, value):self.leMaxVal.setText(str(value))self.image_thresh()def image_thresh(self):img = cv2.imread(fname[0], cv2.IMREAD_COLOR)self.thresholding_tech(img)def thresholding_tech(self,img):strCB = self.cboThresholding.currentText()minVal = int(self.leMinVal.text())maxVal = int(self.leMaxVal.text())blockSize = int(self.leBlockSize.text())Const = int(self.leConst.text())if strCB == 'THRESH_BINARY':self.do_thresh(img, minVal, maxVal, cv2.THRESH_BINARY, \'Histogram of Thresholded Image with ' + strCB)if strCB == 'THRESH_BINARY_INV':self.do_thresh(img, minVal, maxVal, cv2.THRESH_BINARY_INV, \'Histogram of Thresholded Image with ' + strCB)if strCB == 'THRESH_TRUNC':self.do_thresh(img, minVal, maxVal, cv2.THRESH_TRUNC, \'Histogram of Thresholded Image with ' + strCB)if strCB == 'THRESH_TOZERO':self.do_thresh(img, minVal, maxVal, cv2.THRESH_TOZERO,\'Histogram of Thresholded Image with ' + strCB)if strCB == 'THRESH_TOZERO_INV':self.do_thresh(img, minVal, maxVal, cv2.THRESH_TOZERO_INV, \'Histogram of Thresholded Image with ' + strCB)if strCB == 'ADAPTIVE_THRESH_MEAN_C':self.do_adapt_thresh(img, 255, blockSize, Const, \cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, \'Histogram of Thresholded Image with ' + strCB)if strCB == 'ADAPTIVE_THRESH_GAUSSIAN_C':self.do_adapt_thresh(img, 255, blockSize, Const, \cv2.cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, \'Histogram of Thresholded Image with ' + strCB)def do_thresh(self, img, minVal, maxVal, method, title):channel = len(img.shape)if channel == 2: #grayscale imageret, thresh = cv2.threshold(img, minVal, maxVal, method)qmap = QImage(thresh.data, thresh.shape[1], thresh.shape[0], \QImage.Format_Grayscale8)pixmap = QPixmap.fromImage(qmap)else: # color imageret, thresh = cv2.threshold(img, minVal, maxVal, method)height, width, channel = thresh.shapebytesPerLine = 3 * width# To convert back from BGR to RGB space colorcv2.cvtColor(thresh, cv2.COLOR_BGR2RGB, thresh)qImg = QImage(thresh.data, width, height, \bytesPerLine, QImage.Format_RGB888)pixmap = QPixmap.fromImage(qImg)self.display_image(pixmap, thresh, self.labelThresh, \self.widgetHistThresh, title)def do_adapt_thresh(self, img, maxVal, blockSize, Const, method1, \method2,title):channel = len(img.shape)if channel == 2: #grayscale imageimg_blur = cv2.medianBlur(img,blockSize)thresh = cv2.adaptiveThreshold(img_blur,maxVal,method1, \method2, blockSize,Const)qmap = QImage(thresh.data, thresh.shape[1], \thresh.shape[0], QImage.Format_Grayscale8)pixmap = QPixmap.fromImage(qmap)else: # color imageimg_blur = cv2.medianBlur(img,blockSize)b, g, r = cv2.split(img_blur)threshb = cv2.adaptiveThreshold(b,maxVal,method1, \method2, blockSize,Const)threshg = cv2.adaptiveThreshold(g,maxVal,method1, \method2, blockSize,Const)threshr = cv2.adaptiveThreshold(r,maxVal,method1, \method2, blockSize,Const)thresh = cv2.merge((threshb, threshg, threshr))height, width, channel = thresh.shapebytesPerLine = 3 * width# To convert back from BGR to RGB space colorcv2.cvtColor(thresh, cv2.COLOR_BGR2RGB, thresh)qImg = QImage(thresh.data, width, height, \bytesPerLine, QImage.Format_RGB888)pixmap = QPixmap.fromImage(qImg)self.display_image(pixmap, thresh, self.labelThresh, \self.widgetHistThresh, title)def setState(self, state):if state == 'START':self.cboThresholding.setEnabled(False)self.hsMinVal.setEnabled(False)self.hsMaxVal.setEnabled(False)self.leMinVal.setEnabled(False)self.leMaxVal.setEnabled(False)self.lwChannel.setEnabled(False)self.twIntensity.setEnabled(False)self.leBlockSize.setEnabled(False)self.sbBlockSize.setEnabled(False)self.leConst.setEnabled(False)self.sbConst.setEnabled(False)else:self.cboThresholding.setEnabled(True)self.hsMinVal.setEnabled(True)self.hsMaxVal.setEnabled(True)self.leMinVal.setEnabled(True)self.leMaxVal.setEnabled(True)self.lwChannel.setEnabled(True)self.twIntensity.setEnabled(True)self.leBlockSize.setEnabled(True)self.sbBlockSize.setEnabled(True)self.leConst.setEnabled(True)self.sbConst.setEnabled(True)def channel_thresh(self):img = cv2.imread(fname[0], cv2.IMREAD_COLOR)# splitting into individual colorsb, g, r = cv2.split(img)item = self.lwChannel.currentItem()channel = item.text()if channel == 'Blue':self.thresholding_tech(b)self.labelTableTitle.setText(\'Image intensities of '+channel+' channel')self.populate_table(b)if channel == 'Green':self.labelTableTitle.setText(\'Image intensities of '+channel+' channel')self.thresholding_tech(g)if channel == 'Red':self.labelTableTitle.setText(\'Image intensities of '+channel+' channel')self.thresholding_tech(r)def populate_table(self, matrix):self.twIntensity.setRowCount(len(matrix))self.twIntensity.setColumnCount(len(matrix[0]))for i,row in enumerate(matrix):for j,val in enumerate(row):self.twIntensity.setItem(i,j,QTableWidgetItem(str(val)))def set_blockSize(self):self.leBlockSize.setText(str(self.sbBlockSize.value()))self.image_thresh()def set_const(self):self.leConst.setText(str(self.sbConst.value()))self.image_thresh()if __name__=="__main__":import sysapp = QApplication(sys.argv)w = FormThresholding()w.show()sys.exit(app.exec_())
No comments:
Post a Comment