├── HP.jpg ├── Pyqt5ui.py ├── Quit.png ├── README.md ├── SaveAs.png ├── Soc.jpg ├── demo.ui ├── lanelines.png ├── open.png ├── print.png ├── python-icon.png └── save.png /HP.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyhoang1905/Image-Processing-with-OpenCV-Python-and-PyQt5/b22fcaeb8ad63fa177b318f4029661a7542eb9d6/HP.jpg -------------------------------------------------------------------------------- /Pyqt5ui.py: -------------------------------------------------------------------------------- 1 | from PyQt5 import QtCore 2 | from PyQt5 import QtGui 3 | from PyQt5.QtCore import pyqtSlot 4 | from PyQt5.QtGui import QImage, QPixmap 5 | from PyQt5.QtWidgets import QMainWindow, QApplication, QFileDialog, QMessageBox 6 | from PyQt5.QtPrintSupport import QPrintDialog, QPrinter 7 | from PyQt5.uic import loadUi 8 | from butterworth import Butter 9 | import sys 10 | import cv2 11 | import numpy as np 12 | import scipy.signal as sig 13 | import scipy.ndimage as ndi 14 | import matplotlib.pyplot as plt 15 | 16 | class LoadQt(QMainWindow): 17 | def __init__(self): 18 | super(LoadQt, self).__init__() 19 | loadUi('demo.ui', self) 20 | self.setWindowIcon(QtGui.QIcon("python-icon.png")) 21 | 22 | self.image = None 23 | self.actionOpen.triggered.connect(self.open_img) 24 | self.actionSave.triggered.connect(self.save_img) 25 | self.actionPrint.triggered.connect(self.createPrintDialog) 26 | self.actionQuit.triggered.connect(self.QuestionMessage) 27 | self.actionBig.triggered.connect(self.big_Img) 28 | self.actionSmall.triggered.connect(self.small_Img) 29 | self.actionQt.triggered.connect(self.AboutMessage) 30 | self.actionAuthor.triggered.connect(self.AboutMessage2) 31 | 32 | # Chương 2 33 | self.actionRotation.triggered.connect(self.rotation) 34 | self.actionAffine.triggered.connect(self.shearing) 35 | self.actionTranslation.triggered.connect(self.translation) 36 | 37 | # Chương 3 38 | self.actioAnhXam.triggered.connect(self.anh_Xam) 39 | self.actionNegative.triggered.connect(self.anh_Negative) 40 | self.actionHistogram.triggered.connect(self.histogram_Equalization) 41 | self.actionLog.triggered.connect(self.Log) 42 | self.actionGamma.triggered.connect(self.gamma) 43 | 44 | # Image Restoration 45 | self.actionGaussian.triggered.connect(self.gaussian_noise) 46 | self.actionRayleigh.triggered.connect(self.rayleigh_noise) 47 | self.actionErlang.triggered.connect(self.erlang_noise) 48 | self.actionUniform.triggered.connect(self.uniform_noise) 49 | self.actionImpluse.triggered.connect(self.impulse_noise) 50 | self.actionHistogram_PDF.triggered.connect(self.hist) 51 | 52 | # Image Restoration 1 53 | self.actionAdaptive_Wiener_Filtering.triggered.connect(self.weiner_filter) 54 | self.actionMedian_Filtering.triggered.connect(self.median_filtering) 55 | self.actionAdaptive_Median_Filtering.triggered.connect(self.adaptive_median_filtering) 56 | 57 | # Image Restoration 2 58 | self.actionInverse_Filter.triggered.connect(self.inv_filter) 59 | 60 | # Simple Edge Detection 61 | self.actionSHT.triggered.connect(self.simple_edge_detection) 62 | 63 | # Smoothing 64 | self.actionBlur.triggered.connect(self.blur) 65 | self.actionBox_Filter.triggered.connect(self.box_filter) 66 | self.actionMedian_Filter.triggered.connect(self.median_filter) 67 | self.actionBilateral_Filter.triggered.connect(self.bilateral_filter) 68 | self.actionGaussian_Filter.triggered.connect(self.gaussian_filter) 69 | 70 | # Filter 71 | self.actionMedian_threshold_2.triggered.connect(self.median_threshold) 72 | self.actionDirectional_Filtering_2.triggered.connect(self.directional_filtering) 73 | self.actionDirectional_Filtering_3.triggered.connect(self.directional_filtering2) 74 | self.actionDirectional_Filtering_4.triggered.connect(self.directional_filtering3) 75 | self.action_Butterworth.triggered.connect(self.butter_filter) 76 | self.action_Notch_filter.triggered.connect(self.notch_filter) 77 | 78 | # Cartooning of an Image 79 | self.actionCartoon.triggered.connect(self.cartoon) 80 | 81 | # Set input 82 | self.dial.valueChanged.connect(self.rotation2) 83 | self.horizontalSlider.valueChanged.connect(self.Gamma_) 84 | self.gaussian_QSlider.valueChanged.connect(self.gaussian_filter2) 85 | self.erosion.valueChanged.connect(self.erode) 86 | self.Qlog.valueChanged.connect(self.Log) 87 | self.size_Img.valueChanged.connect(self.SIZE) 88 | self.canny.stateChanged.connect(self.Canny) 89 | self.canny_min.valueChanged.connect(self.Canny) 90 | self.canny_max.valueChanged.connect(self.Canny) 91 | self.pushButton.clicked.connect(self.reset) 92 | 93 | @pyqtSlot() 94 | def loadImage(self, fname): 95 | self.image = cv2.imread(fname) 96 | self.tmp = self.image 97 | self.displayImage() 98 | 99 | def displayImage(self, window=1): 100 | qformat = QImage.Format_Indexed8 101 | 102 | if len(self.image.shape) == 3: 103 | if(self.image.shape[2]) == 4: 104 | qformat = QImage.Format_RGBA8888 105 | else: 106 | qformat = QImage.Format_RGB888 107 | img = QImage(self.image, self.image.shape[1], self.image.shape[0], self.image.strides[0], qformat) 108 | # image.shape[0] là số pixel theo chiều Y 109 | # image.shape[1] là số pixel theo chiều X 110 | # image.shape[2] lưu số channel biểu thị mỗi pixel 111 | img = img.rgbSwapped() # chuyển đổi hiệu quả một ảnh RGB thành một ảnh BGR. 112 | if window == 1: 113 | self.imgLabel.setPixmap(QPixmap.fromImage(img)) 114 | self.imgLabel.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter)# căn chỉnh vị trí xuất hiện của hình trên lable 115 | if window == 2: 116 | self.imgLabel2.setPixmap(QPixmap.fromImage(img)) 117 | self.imgLabel2.setAlignment(QtCore.Qt.AlignHCenter | QtCore.Qt.AlignVCenter) 118 | 119 | def open_img(self): 120 | fname, filter = QFileDialog.getOpenFileName(self, 'Open File', 'C:\\Users\DELL\PycharmProjects\DemoPro', "Image Files (*)") 121 | if fname: 122 | self.loadImage(fname) 123 | else: 124 | print("Invalid Image") 125 | 126 | def save_img(self): 127 | fname, filter = QFileDialog.getSaveFileName(self, 'Save File', 'C:\\', "Image Files (*.png)") 128 | if fname: 129 | cv2.imwrite(fname, self.image) # Lưu trữ ảnh 130 | print("Error") 131 | 132 | def createPrintDialog(self): 133 | printer = QPrinter(QPrinter.HighResolution) 134 | dialog = QPrintDialog(printer, self) 135 | 136 | if dialog.exec_() == QPrintDialog.Accepted: 137 | self.imgLabel2.print_(printer) 138 | 139 | def big_Img(self): 140 | self.image = cv2.resize(self.image, None, fx=1.5, fy=1.5, interpolation=cv2.INTER_CUBIC) 141 | self.displayImage(2) 142 | 143 | def small_Img(self): 144 | self.image = cv2.resize(self.image, None, fx=0.75, fy=0.75, interpolation=cv2.INTER_CUBIC) 145 | self.displayImage(2) 146 | 147 | def SIZE(self , c): 148 | self.image = self.tmp 149 | self.image = cv2.resize(self.image, None, fx=c, fy=c, interpolation=cv2.INTER_CUBIC) 150 | self.displayImage(2) 151 | 152 | def reset(self): 153 | self.image = self.tmp 154 | self.displayImage(2) 155 | 156 | def AboutMessage(self): 157 | QMessageBox.about(self, "About Qt - Qt Designer", 158 | "Qt is a multiplatform C + + GUI toolkit created and maintained byTrolltech.It provides application developers with all the functionality needed to build applications with state-of-the-art graphical user interfaces.\n" 159 | "Qt is fully object-oriented, easily extensible, and allows true component programming.Read the Whitepaper for a comprehensive technical overview.\n\n" 160 | 161 | "Since its commercial introduction in early 1996, Qt has formed the basis of many thousands of successful applications worldwide.Qt is also the basis of the popular KDE Linux desktop environment, a standard component of all major Linux distributions.See our Customer Success Stories for some examples of commercial Qt development.\n\n" 162 | 163 | "Qt is supported on the following platforms:\n\n" 164 | 165 | "\tMS / Windows - - 95, 98, NT\n" 166 | "\t4.0, ME, 2000, and XP\n" 167 | "\tUnix / X11 - - Linux, Sun\n" 168 | "\tSolaris, HP - UX, Compaq Tru64 UNIX, IBM AIX, SGI IRIX and a wide range of others\n" 169 | "\tMacintosh - - Mac OS X\n" 170 | "\tEmbedded - - Linux platforms with framebuffer support.\n\n" 171 | 172 | "Qt is released in different editions:\n\n" 173 | 174 | "\tThe Qt Enterprise Edition and the Qt Professional Edition provide for commercial software development.They permit traditional commercial software distribution and include free upgrades and Technical Support.For the latest prices, see the Trolltech web site, Pricing and Availability page, or contact sales @ trolltech.com.The Enterprise Edition offers additional modules compared to the Professional Edition.\n\n" 175 | "\tThe Qt Open Source Edition is available for Unix / X11, Macintosh and Embedded Linux.The Open Source Edition is for the development of Free and Open Source software only.It is provided free of charge under the terms of both the Q Public License and the GNU General Public License." 176 | ) 177 | def AboutMessage2(self): 178 | QMessageBox.about(self, "About Author", "Người hướng dẫn: NGÔ QUỐC VIỆT \n\n" 179 | "Người thực hiện:\n" 180 | "\tPhan Hoàng Việt - 42.01.104.189" 181 | ) 182 | 183 | def QuestionMessage(self): 184 | message = QMessageBox.question(self, "Exit", "Bạn có chắc muốn thoát", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) 185 | if message == QMessageBox.Yes: 186 | print("Yes") 187 | self.close() 188 | else: 189 | print("No") 190 | 191 | ################################ Chương 2 ############################################################################## 192 | def rotation(self): 193 | rows, cols, steps = self.image.shape 194 | M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 90, 1) #thay đổi chiều của ảnh 195 | self.image = cv2.warpAffine(self.image, M, (cols, rows)) 196 | self.displayImage(2) 197 | 198 | def rotation2(self, angle): 199 | self.image = self.tmp 200 | rows, cols, steps = self.image.shape 201 | M = cv2.getRotationMatrix2D((cols / 2, rows / 2), angle, 1) 202 | self.image = cv2.warpAffine(self.image, M, (cols, rows)) 203 | self.displayImage(2) 204 | 205 | def shearing(self): 206 | self.image = self.tmp 207 | rows, cols, ch = self.image.shape 208 | pts1 = np.float32([[50, 50], [200, 50], [50, 200]]) 209 | pts2 = np.float32([[10, 100], [200, 50], [100, 250]]) 210 | 211 | M = cv2.getAffineTransform(pts1, pts2) 212 | self.image = cv2.warpAffine(self.image, M, (cols, rows)) 213 | 214 | self.displayImage(2) 215 | 216 | def translation(self): 217 | self.image = self.tmp 218 | num_rows, num_cols = self.image.shape[:2] 219 | 220 | translation_matrix = np.float32([[1, 0, 70], [0, 1, 110]]) 221 | img_translation = cv2.warpAffine(self.image, translation_matrix, (num_cols, num_rows)) 222 | self.image = img_translation 223 | self.displayImage(2) 224 | 225 | def erode(self , iter): 226 | self.image = self.tmp 227 | if iter > 0 : 228 | kernel = np.ones((4, 7), np.uint8) 229 | self.image = cv2.erode(self.tmp, kernel, iterations=iter) 230 | else : 231 | kernel = np.ones((2, 6), np.uint8) 232 | self.image = cv2.dilate(self.image, kernel, iterations=iter*-1) 233 | self.displayImage(2) 234 | 235 | def Canny(self): 236 | self.image = self.tmp 237 | if self.canny.isChecked(): 238 | can = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) 239 | self.image = cv2.Canny(can, self.canny_min.value(), self.canny_max.value()) 240 | self.displayImage(2) 241 | 242 | ################################ Chương 3 ############################################################################## 243 | def anh_Xam(self): 244 | self.image = self.tmp 245 | self.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) 246 | self.displayImage(2) 247 | 248 | def anh_Xam2(self): 249 | self.image = self.tmp 250 | if self.gray.isChecked(): 251 | self.image = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) 252 | self.image = cv2.cvtColor(self.image, cv2.COLOR_GRAY2RGB) 253 | self.displayImage(2) 254 | 255 | def anh_Negative(self): 256 | self.image = self.tmp 257 | self.image = ~self.image 258 | self.displayImage(2) 259 | 260 | def histogram_Equalization(self): 261 | self.image = self.tmp 262 | img_yuv = cv2.cvtColor(self.image, cv2.COLOR_RGB2YUV) 263 | img_yuv[:, :, 0] = cv2.equalizeHist(img_yuv[:, :, 0]) 264 | self.image = cv2.cvtColor(img_yuv, cv2.COLOR_YUV2RGB) 265 | self.displayImage(2) 266 | 267 | def Log(self): 268 | self.image = self.tmp 269 | img_2 = np.uint8(np.log(self.image)) 270 | c = 2 271 | self.image = cv2.threshold(img_2, c, 225, cv2.THRESH_BINARY)[1] 272 | self.displayImage(2) 273 | 274 | def Gamma_(self, gamma): 275 | self.image = self.tmp 276 | gamma = gamma*0.1 277 | invGamma = 1.0 /gamma 278 | table = np.array([((i / 255.0) ** invGamma) * 255 279 | for i in np.arange(0, 256)]).astype("uint8") 280 | 281 | self.image = cv2.LUT(self.image, table) 282 | self.displayImage(2) 283 | 284 | def gamma(self): 285 | self.image = self.tmp 286 | gamma = 1.5 287 | invGamma = 1.0 / gamma 288 | table = np.array([((i / 255.0) ** invGamma) * 255 289 | for i in np.arange(0, 256)]).astype("uint8") 290 | 291 | self.image = cv2.LUT(self.image, table) 292 | self.displayImage(2) 293 | 294 | #######################################Image Restoration################################################################ 295 | def gaussian_noise(self): 296 | self.image = self.tmp 297 | row, col, ch = self.image.shape 298 | mean = 0 299 | var = 0.1 300 | sigma = var * 0.5 301 | gauss = np.random.normal(mean, sigma, (row, col, ch)) 302 | gauss = gauss.reshape(row, col, ch) 303 | self.image = self.image + gauss 304 | self.displayImage(2) 305 | def erlang_noise(self): 306 | self.image = self.tmp 307 | gamma = 1.5 308 | invGamma = 1.0 / gamma 309 | table = np.array([((i / 255.0) ** invGamma) * 255 310 | for i in np.arange(0, 256)]).astype("uint8") 311 | cv2.randu(table, 1, 1) 312 | self.image = cv2.LUT(self.image, table) 313 | self.displayImage(2) 314 | def rayleigh_noise(self): 315 | self.image = self.tmp 316 | r = np.zeros((self.image.shape[0], self.image.shape[1]), dtype=np.uint8) 317 | self.image = cv2.randu(r, 1, 1) 318 | self.displayImage(2) 319 | def uniform_noise(self): 320 | self.image = self.tmp 321 | uniform_noise = np.zeros((self.image.shape[0], self.image.shape[1]), dtype=np.uint8) 322 | cv2.randu(uniform_noise, 0, 255) 323 | self.image = (uniform_noise * 0.5).astype(np.uint8) 324 | self.displayImage(2) 325 | def impulse_noise(self): 326 | self.image = self.tmp 327 | s_vs_p = 0.5 328 | amount = 0.004 329 | out = np.copy(self.image) 330 | # Salt mode 331 | num_salt = np.ceil(amount * self.image.size * s_vs_p) 332 | coords = [np.random.randint(0, i - 1, int(num_salt)) 333 | for i in self.image.shape] 334 | out[coords] = 1 335 | 336 | # Pepper mode 337 | num_pepper = np.ceil(amount * self.image.size * (1. - s_vs_p)) 338 | coords = [np.random.randint(0, i - 1, int(num_pepper)) 339 | for i in self.image.shape] 340 | out[coords] = 0 341 | self.image = out 342 | self.displayImage(2) 343 | 344 | def hist(self): 345 | self.image = self.tmp 346 | histg = cv2.calcHist([self.image], [0], None, [256], [0, 256]) 347 | self.image = histg 348 | plt.plot(self.image) 349 | plt.show() 350 | self.displayImage(2) 351 | 352 | ####################################Image Restoration 1################################################################# 353 | def median_filtering(self): 354 | self.image = self.tmp 355 | self.image = cv2.medianBlur(self.image, 5) 356 | self.displayImage(2) 357 | 358 | def adaptive_median_filtering(self): 359 | self.image = self.tmp 360 | temp = [] 361 | filter_size = 5 362 | indexer = filter_size // 2 363 | for i in range(len(self.image)): 364 | 365 | for j in range(len(self.image[0])): 366 | 367 | for z in range(filter_size): 368 | if i + z - indexer < 0 or i + z - indexer > len(self.image) - 1: 369 | for c in range(filter_size): 370 | temp.append(0) 371 | else: 372 | if j + z - indexer < 0 or j + indexer > len(self.image[0]) - 1: 373 | temp.append(0) 374 | else: 375 | for k in range(filter_size): 376 | temp.append(self.image[i + z - indexer][j + k - indexer]) 377 | 378 | temp.sort() 379 | self.image[i][j] = temp[len(temp) // 2] 380 | temp = [] 381 | self.displayImage(2) 382 | 383 | def weiner_filter(self): 384 | self.image = self.tmp 385 | M = 256 # length of Wiener filter 386 | Om0 = 0.1 * np.pi # frequency of original signal 387 | N0 = 0.1 # PSD of additive white noise 388 | 389 | # generate original signal 390 | s = np.cos(Om0 * np.ndarray(self.image)) 391 | # generate observed signal 392 | g = 1 / 20 * np.asarray([1, 2, 3, 4, 5, 4, 3, 2, 1]) 393 | n = np.random.normal(size=self.image, scale=np.sqrt(N0)) 394 | x = np.convolve(s, g, mode='same') + n 395 | # estimate (cross) PSDs using Welch technique 396 | f, Pxx = sig.csd(x, x, nperseg=M) 397 | f, Psx = sig.csd(s, x, nperseg=M) 398 | # compute Wiener filter 399 | H = Psx / Pxx 400 | H = H * np.exp(-1j * 2 * np.pi / len(H) * np.arange(len(H)) * (len(H) // 2)) # shift for causal filter 401 | h = np.fft.irfft(H) 402 | # apply Wiener filter to observation 403 | self.image = np.convolve(x, h, mode='same') 404 | self.displayImage(2) 405 | 406 | ####################################Image Restoration 2################################################################# 407 | def inv_filter(self): 408 | self.image = self.tmp 409 | for i in range(0, 3): 410 | g = self.image[:, :, i] 411 | G = (np.fft.fft2(g)) 412 | 413 | # h = cv2.imread(self.image, 0) 414 | h_padded = np.zeros(g.shape) 415 | h_padded[:self.image.shape[0], :self.image.shape[1]] = np.copy(self.image) 416 | H = (np.fft.fft2(h_padded)) 417 | 418 | # normalize to [0,1] 419 | H_norm = H / abs(H.max()) 420 | G_norm = G / abs(G.max()) 421 | F_temp = G_norm / H_norm 422 | F_norm = F_temp / abs(F_temp.max()) 423 | 424 | # rescale to original scale 425 | F_hat = F_norm * abs(G.max()) 426 | 427 | # 3. apply Inverse Filter and compute IFFT 428 | self.image = np.fft.ifft2(F_hat) 429 | self.image[:, :, i] = abs(self.image) 430 | self.displayImage(2) 431 | 432 | ##################################Simple Edge Detection################################################################# 433 | def simple_edge_detection(self): 434 | self.image = self.tmp 435 | 436 | # Convert the img to grayscale 437 | gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) 438 | 439 | # Apply edge detection method on the image 440 | edges = cv2.Canny(gray, 50, 150, apertureSize=3) 441 | 442 | # This returns an array of r and theta values 443 | lines = cv2.HoughLines(edges, 1, np.pi / 180, 200) 444 | 445 | # The below for loop runs till r and theta values 446 | # are in the range of the 2d array 447 | for r, theta in lines[0]: 448 | # Stores the value of cos(theta) in a 449 | a = np.cos(theta) 450 | 451 | # Stores the value of sin(theta) in b 452 | b = np.sin(theta) 453 | 454 | # x0 stores the value rcos(theta) 455 | x0 = a * r 456 | 457 | # y0 stores the value rsin(theta) 458 | y0 = b * r 459 | 460 | # x1 stores the rounded off value of (rcos(theta)-1000sin(theta)) 461 | x1 = int(x0 + 1000 * (-b)) 462 | 463 | # y1 stores the rounded off value of (rsin(theta)+1000cos(theta)) 464 | y1 = int(y0 + 1000 * (a)) 465 | 466 | # x2 stores the rounded off value of (rcos(theta)+1000sin(theta)) 467 | x2 = int(x0 - 1000 * (-b)) 468 | 469 | # y2 stores the rounded off value of (rsin(theta)-1000cos(theta)) 470 | y2 = int(y0 - 1000 * (a)) 471 | 472 | # cv2.line draws a line in img from the point(x1,y1) to (x2,y2). 473 | # (0,0,255) denotes the colour of the line to be 474 | # drawn. In this case, it is red. 475 | cv2.line(self.image, (x1, y1), (x2, y2), (0, 0, 255), 2) 476 | self.displayImage(2) 477 | 478 | #####################################Smoothing########################################################################## 479 | def blur(self): 480 | self.image = self.tmp 481 | self.image = cv2.blur(self.image, (5, 5)) 482 | self.displayImage(2) 483 | def box_filter(self): 484 | self.image = self.tmp 485 | self.image = cv2.boxFilter(self.image, -1,(20,20)) 486 | self.displayImage(2) 487 | def median_filter(self): 488 | self.image = self.tmp 489 | self.image = cv2.medianBlur(self.image,5) 490 | self.displayImage(2) 491 | def bilateral_filter(self): 492 | self.image = self.tmp 493 | self.image = cv2.bilateralFilter(self.image,9,75,75) 494 | self.displayImage(2) 495 | def gaussian_filter(self): 496 | self.image = self.tmp 497 | self.image = cv2.GaussianBlur(self.image,(5,5),0) 498 | self.displayImage(2) 499 | def gaussian_filter2(self, g): 500 | self.image = self.tmp 501 | self.image = cv2.GaussianBlur(self.image, (5, 5), g) 502 | self.displayImage(2) 503 | ########################################Filter########################################################################## 504 | def median_threshold(self): 505 | self.image = self.tmp 506 | grayscaled = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY) 507 | self.image = cv2.medianBlur(self.image,5) 508 | retval, threshold = cv2.threshold(grayscaled,125,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU) 509 | self.image = threshold 510 | self.displayImage(2) 511 | def directional_filtering(self): 512 | self.image = self.tmp 513 | kernel = np.ones((3, 3), np.float32) / 9 514 | self.image = cv2.filter2D(self.image, -1, kernel) 515 | self.displayImage(2) 516 | def directional_filtering2(self): 517 | self.image = self.tmp 518 | kernel = np.ones((5, 5), np.float32) / 9 519 | self.image = cv2.filter2D(self.image, -1, kernel) 520 | self.displayImage(2) 521 | def directional_filtering3(self): 522 | self.image = self.tmp 523 | kernel = np.ones((7, 7), np.float32) / 9 524 | self.image = cv2.filter2D(self.image, -1, kernel) 525 | self.displayImage(2) 526 | 527 | def butter_filter(self): 528 | self.image = self.tmp 529 | img_float32 = np.float32(self.image) 530 | 531 | dft = cv2.dft(img_float32, flags=cv2.DFT_COMPLEX_OUTPUT) 532 | self.image = np.fft.fftshift(dft) 533 | 534 | self.image = 20 * np.log(cv2.magnitude(self.image[:, :, 0], self.image[:, :, 1])) 535 | self.displayImage(2) 536 | def notch_filter(self): 537 | self.image = self.tmp 538 | 539 | self.displayImage(2) 540 | 541 | ########################################Cartooning of an Image########################################################## 542 | def cartoon(self): 543 | num_down = 2 544 | num_bilateral = 7 545 | 546 | img_color = self.image 547 | for _ in range(num_down): 548 | img_color = cv2.pyrDown(img_color) 549 | 550 | for _ in range(num_bilateral): 551 | img_color = cv2.bilateralFilter(img_color, d=9, sigmaColor=9, sigmaSpace=7) 552 | 553 | for _ in range(num_down): 554 | img_color = cv2.pyrUp(img_color) 555 | 556 | img_gray = cv2.cvtColor(self.image, cv2.COLOR_RGB2GRAY) 557 | img_blur = cv2.medianBlur(img_gray, 7) 558 | 559 | img_edge = cv2.adaptiveThreshold(img_blur, 255, 560 | cv2.ADAPTIVE_THRESH_MEAN_C, 561 | cv2.THRESH_BINARY, 562 | blockSize=9, 563 | C=2) 564 | img_edge = cv2.cvtColor(img_edge, cv2.COLOR_GRAY2RGB) 565 | self.image = cv2.bitwise_and(img_color, img_edge) 566 | 567 | self.displayImage(2) 568 | 569 | ########################################Moire Pattern########################################################## 570 | 571 | 572 | app = QApplication(sys.argv) 573 | win = LoadQt() 574 | win.show() 575 | sys.exit(app.exec()) 576 | 577 | -------------------------------------------------------------------------------- /Quit.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyhoang1905/Image-Processing-with-OpenCV-Python-and-PyQt5/b22fcaeb8ad63fa177b318f4029661a7542eb9d6/Quit.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Image-Processing-with-OpenCV-Python-and-PyQt5 2 | Image Processing with OpenCV-Python and PyQt5 3 | Descriptions: A method to perform some operations on an image, in order to get an enhanced image or to extract some useful information from it. It is a type of signal processing in which input is an image and output may be image or characteristics/features associated with that image. 4 | Tech stack: Python programming languages, Qt Designer 5 | -------------------------------------------------------------------------------- /SaveAs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyhoang1905/Image-Processing-with-OpenCV-Python-and-PyQt5/b22fcaeb8ad63fa177b318f4029661a7542eb9d6/SaveAs.png -------------------------------------------------------------------------------- /Soc.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyhoang1905/Image-Processing-with-OpenCV-Python-and-PyQt5/b22fcaeb8ad63fa177b318f4029661a7542eb9d6/Soc.jpg -------------------------------------------------------------------------------- /demo.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | MainWindow 4 | 5 | 6 | 7 | 0 8 | 0 9 | 1359 10 | 686 11 | 12 | 13 | 14 | MainWindow 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 30 25 | 20 26 | 491 27 | 521 28 | 29 | 30 | 31 | QFrame::Panel 32 | 33 | 34 | QFrame::Plain 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 570 44 | 20 45 | 491 46 | 521 47 | 48 | 49 | 50 | QFrame::Panel 51 | 52 | 53 | QFrame::Plain 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 1190 63 | 10 64 | 81 65 | 51 66 | 67 | 68 | 69 | 70 | 8 71 | 72 | 73 | 74 | 360 75 | 76 | 77 | 78 | 79 | 80 | 1120 81 | 30 82 | 71 83 | 21 84 | 85 | 86 | 87 | 88 | 14 89 | 90 | 91 | 92 | Rotation 93 | 94 | 95 | 96 | 97 | 98 | 1180 99 | 90 100 | 141 101 | 22 102 | 103 | 104 | 105 | 5 106 | 107 | 108 | 20 109 | 110 | 111 | 5 112 | 113 | 114 | 5 115 | 116 | 117 | Qt::Horizontal 118 | 119 | 120 | 121 | 122 | 123 | 1120 124 | 90 125 | 55 126 | 16 127 | 128 | 129 | 130 | 131 | 10 132 | 133 | 134 | 135 | Gamma 136 | 137 | 138 | 139 | 140 | 141 | 1080 142 | 10 143 | 20 144 | 631 145 | 146 | 147 | 148 | Qt::Vertical 149 | 150 | 151 | 152 | 153 | 154 | 1180 155 | 60 156 | 141 157 | 22 158 | 159 | 160 | 161 | 1 162 | 163 | 164 | 10 165 | 166 | 167 | 1 168 | 169 | 170 | 1 171 | 172 | 173 | Qt::Horizontal 174 | 175 | 176 | 177 | 178 | 179 | 1120 180 | 60 181 | 55 182 | 16 183 | 184 | 185 | 186 | 187 | 10 188 | 189 | 190 | 191 | Scaling 192 | 193 | 194 | 195 | 196 | 197 | 1120 198 | 120 199 | 55 200 | 16 201 | 202 | 203 | 204 | 205 | 10 206 | 207 | 208 | 209 | Gaussian 210 | 211 | 212 | 213 | 214 | 215 | 1180 216 | 120 217 | 141 218 | 22 219 | 220 | 221 | 222 | 0 223 | 224 | 225 | 4 226 | 227 | 228 | 10 229 | 230 | 231 | 0 232 | 233 | 234 | 0 235 | 236 | 237 | Qt::Horizontal 238 | 239 | 240 | 241 | 242 | 243 | 1120 244 | 170 245 | 201 246 | 22 247 | 248 | 249 | 250 | -5 251 | 252 | 253 | 5 254 | 255 | 256 | 0 257 | 258 | 259 | 0 260 | 261 | 262 | Qt::Horizontal 263 | 264 | 265 | 266 | 267 | 268 | 1120 269 | 150 270 | 91 271 | 16 272 | 273 | 274 | 275 | 276 | 10 277 | 278 | 279 | 280 | Dilate_Erosion 281 | 282 | 283 | 284 | 285 | 286 | 1130 287 | 200 288 | 31 289 | 21 290 | 291 | 292 | 293 | 294 | 12 295 | 296 | 297 | 298 | Log 299 | 300 | 301 | 302 | 303 | 304 | 1170 305 | 200 306 | 141 307 | 22 308 | 309 | 310 | 311 | 2 312 | 313 | 314 | 4 315 | 316 | 317 | 2 318 | 319 | 320 | 2 321 | 322 | 323 | Qt::Horizontal 324 | 325 | 326 | 327 | 328 | 329 | 1100 330 | 240 331 | 221 332 | 20 333 | 334 | 335 | 336 | Qt::Horizontal 337 | 338 | 339 | 340 | 341 | 342 | 1100 343 | 310 344 | 31 345 | 17 346 | 347 | 348 | 349 | Min 350 | 351 | 352 | 353 | 354 | 355 | 1100 356 | 360 357 | 31 358 | 17 359 | 360 | 361 | 362 | Max 363 | 364 | 365 | 366 | 367 | 368 | 1100 369 | 270 370 | 171 371 | 22 372 | 373 | 374 | 375 | false 376 | 377 | 378 | Canny Edge Detector 379 | 380 | 381 | true 382 | 383 | 384 | false 385 | 386 | 387 | 388 | 389 | 390 | 1140 391 | 310 392 | 160 393 | 29 394 | 395 | 396 | 397 | 200 398 | 399 | 400 | 100 401 | 402 | 403 | Qt::Horizontal 404 | 405 | 406 | 407 | 408 | 409 | 1140 410 | 360 411 | 160 412 | 29 413 | 414 | 415 | 416 | 400 417 | 418 | 419 | 200 420 | 421 | 422 | Qt::Horizontal 423 | 424 | 425 | 426 | 427 | 428 | 1170 429 | 460 430 | 91 431 | 41 432 | 433 | 434 | 435 | Qt::StrongFocus 436 | 437 | 438 | RESET 439 | 440 | 441 | 442 | 443 | 444 | 220 445 | 540 446 | 121 447 | 41 448 | 449 | 450 | 451 | 452 | 24 453 | 454 | 455 | 456 | Original 457 | 458 | 459 | 460 | 461 | 462 | 780 463 | 540 464 | 131 465 | 41 466 | 467 | 468 | 469 | 470 | 24 471 | 472 | 473 | 474 | Changed 475 | 476 | 477 | 478 | 479 | 480 | 481 | 0 482 | 0 483 | 1359 484 | 36 485 | 486 | 487 | 488 | 489 | File 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | View 501 | 502 | 503 | 504 | 505 | 506 | 507 | Chapter 2 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | Chapter 3 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | About US 526 | 527 | 528 | 529 | 530 | 531 | 532 | Image Restoration 533 | 534 | 535 | 536 | 537 | Image Restoration 1 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | Image Restoration 2 547 | 548 | 549 | 550 | 551 | 552 | Image Restoration 553 | 554 | 555 | 556 | Type Noise 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | Simple Edge Detection 576 | 577 | 578 | 579 | 580 | 581 | Smoothing 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | Filter 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | Cartooning of an Image 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | toolBar 621 | 622 | 623 | TopToolBarArea 624 | 625 | 626 | false 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | open.pngopen.png 640 | 641 | 642 | Open 643 | 644 | 645 | 646 | 647 | 648 | save.pngsave.png 649 | 650 | 651 | Save 652 | 653 | 654 | 655 | 656 | 657 | print.pngprint.png 658 | 659 | 660 | Print 661 | 662 | 663 | 664 | 665 | 666 | Quit.pngQuit.png 667 | 668 | 669 | Exit 670 | 671 | 672 | 673 | 674 | Graycsale 675 | 676 | 677 | 678 | 679 | Canny 680 | 681 | 682 | 683 | 684 | Negative 685 | 686 | 687 | 688 | 689 | Histogram Equal 690 | 691 | 692 | 693 | 694 | Log 695 | 696 | 697 | 698 | 699 | Gaussan 700 | 701 | 702 | 703 | 704 | High Boost 705 | 706 | 707 | 708 | 709 | Laplacian 710 | 711 | 712 | 713 | 714 | Median 715 | 716 | 717 | 718 | 719 | Unsharp 720 | 721 | 722 | 723 | 724 | Chương 5 725 | 726 | 727 | 728 | 729 | Ảnh Miền Tần Số 730 | 731 | 732 | 733 | 734 | Ideal LPF 735 | 736 | 737 | 738 | 739 | Butterworth LPF 740 | 741 | 742 | 743 | 744 | Gaussian LPF 745 | 746 | 747 | 748 | 749 | Ideal HPF 750 | 751 | 752 | 753 | 754 | Butterworth HPF 755 | 756 | 757 | 758 | 759 | Gaussian HPF 760 | 761 | 762 | 763 | 764 | dilate 765 | 766 | 767 | 768 | 769 | Erode 770 | 771 | 772 | 773 | 774 | Open 775 | 776 | 777 | 778 | 779 | Close 780 | 781 | 782 | 783 | 784 | Hit-miss 785 | 786 | 787 | 788 | 789 | Dilate 790 | 791 | 792 | 793 | 794 | Morboundary 795 | 796 | 797 | 798 | 799 | Gradient 800 | 801 | 802 | 803 | 804 | Convex 805 | 806 | 807 | 808 | 809 | Sobel X 810 | 811 | 812 | 813 | 814 | Sobel Y 815 | 816 | 817 | 818 | 819 | Sobel Laplacian 820 | 821 | 822 | 823 | 824 | Laplacian of Gaussian 825 | 826 | 827 | 828 | 829 | Hough 830 | 831 | 832 | 833 | 834 | Zoom in 835 | 836 | 837 | 838 | 839 | Rotation 840 | 841 | 842 | 843 | 844 | Shearing 845 | 846 | 847 | 848 | 849 | Gamma 850 | 851 | 852 | 853 | 854 | Zoom out 855 | 856 | 857 | 858 | 859 | About Qt 860 | 861 | 862 | 863 | 864 | Author 865 | 866 | 867 | 868 | 869 | Translation 870 | 871 | 872 | 873 | 874 | Gaussian 875 | 876 | 877 | 878 | 879 | Rayleigh 880 | 881 | 882 | 883 | 884 | Impluse 885 | 886 | 887 | 888 | 889 | Uniform 890 | 891 | 892 | 893 | 894 | Erlang 895 | 896 | 897 | 898 | 899 | Histogram PDF 900 | 901 | 902 | 903 | 904 | HoughLines 905 | 906 | 907 | 908 | 909 | HoughLines 910 | 911 | 912 | 913 | 914 | Standard Hough Transform 915 | 916 | 917 | 918 | 919 | Median Filtering 920 | 921 | 922 | 923 | 924 | Adaptive Wiener Filtering 925 | 926 | 927 | 928 | 929 | Adaptive Median Filtering 930 | 931 | 932 | 933 | 934 | Inverse Filter 935 | 936 | 937 | 938 | 939 | Blur 940 | 941 | 942 | 943 | 944 | Box Filter 945 | 946 | 947 | 948 | 949 | Median Filter 950 | 951 | 952 | 953 | 954 | Bilateral Filter 955 | 956 | 957 | 958 | 959 | Gaussian Filter 960 | 961 | 962 | 963 | 964 | Directional Filtering 965 | 966 | 967 | 968 | 969 | Median threshold 970 | 971 | 972 | 973 | 974 | Median threshold 975 | 976 | 977 | 978 | 979 | Directional Filtering 980 | 981 | 982 | 983 | 984 | Butterworth Filter 985 | 986 | 987 | 988 | 989 | Notch Filter 990 | 991 | 992 | 993 | 994 | Cartoon 995 | 996 | 997 | 998 | 999 | Directional Filtering 2 1000 | 1001 | 1002 | 1003 | 1004 | Directional Filtering 3 1005 | 1006 | 1007 | 1008 | 1009 | 1010 | 1011 | -------------------------------------------------------------------------------- /lanelines.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyhoang1905/Image-Processing-with-OpenCV-Python-and-PyQt5/b22fcaeb8ad63fa177b318f4029661a7542eb9d6/lanelines.png -------------------------------------------------------------------------------- /open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyhoang1905/Image-Processing-with-OpenCV-Python-and-PyQt5/b22fcaeb8ad63fa177b318f4029661a7542eb9d6/open.png -------------------------------------------------------------------------------- /print.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyhoang1905/Image-Processing-with-OpenCV-Python-and-PyQt5/b22fcaeb8ad63fa177b318f4029661a7542eb9d6/print.png -------------------------------------------------------------------------------- /python-icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyhoang1905/Image-Processing-with-OpenCV-Python-and-PyQt5/b22fcaeb8ad63fa177b318f4029661a7542eb9d6/python-icon.png -------------------------------------------------------------------------------- /save.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/huyhoang1905/Image-Processing-with-OpenCV-Python-and-PyQt5/b22fcaeb8ad63fa177b318f4029661a7542eb9d6/save.png --------------------------------------------------------------------------------