├── README.md ├── mainWindow.py └── mainWindowLayout.py /README.md: -------------------------------------------------------------------------------- 1 | ## 软件界面 2 | ![imgprocessing.png](https://github.com/marshalwolf/img-folder/blob/master/imgprocessing.png) 3 | ## 运行环境 4 | * python 3.6+ 5 | * opencv 3.4+ 6 | * pyqt5 7 | ## 使用说明 8 | * 配置好环境,直接运行mainWindow.py即可。 9 | ## License 10 | [MIT](https://opensource.org/licenses/MIT) 11 | -------------------------------------------------------------------------------- /mainWindow.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | import sys 5 | import os 6 | from PyQt5.QtGui import * 7 | from PyQt5.QtCore import * 8 | from PyQt5.QtWidgets import * 9 | from PyQt5 import QtCore, QtGui, QtWidgets 10 | 11 | from mainWindowLayout import MainLayout 12 | 13 | import cv2 14 | import numpy as np 15 | from scipy import ndimage 16 | from matplotlib import pyplot as plt 17 | 18 | class MainWindow(QMainWindow, MainLayout): 19 | imagePaths = [] 20 | originImages=[] 21 | imageList = [] #二维的图像列表 22 | hideLayoutTag=-1 23 | 24 | def __init__(self,parent=None): 25 | super(MainWindow, self).__init__(parent) 26 | self.setupUi(self) 27 | self.signalSlots() 28 | 29 | 30 | #button与具体方法关联 31 | def signalSlots(self): 32 | #文件按钮相关方法 33 | #打开 34 | self.openAct.triggered.connect(lambda : importImage(self)) 35 | #保存 36 | self.saveAct.triggered.connect(lambda : importImage(self)) 37 | #退出 38 | self.exitAct.triggered.connect(self.close) 39 | 40 | #编辑按钮相关方法 41 | #放大 42 | self.largeAct.triggered.connect(lambda : largeImage(self)) 43 | #缩小 44 | self.smallAct.triggered.connect(lambda : smallImage(self)) 45 | #灰度 46 | self.grayAct.triggered.connect(lambda : grayImage(self)) 47 | #亮度 48 | self.brightAct.triggered.connect(lambda : brightImage(self)) 49 | #旋转 50 | self.rotateAct.triggered.connect(lambda : rotateImage(self)) 51 | #截图 52 | self.screenshotAct.triggered.connect(lambda : screenshotImage(self)) 53 | 54 | #变换按钮相关方法 55 | #傅里叶变换 56 | self.change1Act.triggered.connect(lambda : change1Image(self)) 57 | #离散余弦变换 58 | self.change2Act.triggered.connect(lambda : change2Image(self)) 59 | #Radon变换 60 | self.change3Act.triggered.connect(lambda : change3Image(self)) 61 | 62 | #噪声按钮相关方法 63 | #高斯噪声 64 | self.noise1Act.triggered.connect(lambda : noise1Image(self)) 65 | #椒盐噪声 66 | self.noise2Act.triggered.connect(lambda : noise2Image(self)) 67 | #斑点噪声 68 | self.noise3Act.triggered.connect(lambda : importImage(self)) 69 | #泊松噪声 70 | self.noise4Act.triggered.connect(lambda : importImage(self)) 71 | 72 | #滤波按钮相关方法 73 | #高通滤波 74 | self.smoothing1Act.triggered.connect(lambda : smoothing1Image(self)) 75 | #低通滤波 76 | self.smoothing2Act.triggered.connect(lambda : smoothing2Image(self)) 77 | #平滑滤波 78 | self.smoothing3Act.triggered.connect(lambda : smoothing3Image(self)) 79 | #锐化滤波 80 | self.smoothing4Act.triggered.connect(lambda : smoothing4Image(self)) 81 | 82 | #直方图统计按钮相关方法 83 | #R直方图 84 | self.hist1Act.triggered.connect(lambda : hist1Image(self)) 85 | #G直方图 86 | self.hist2Act.triggered.connect(lambda : importImage(self)) 87 | #B直方图 88 | self.hist3Act.triggered.connect(lambda : importImage(self)) 89 | 90 | #图像增强按钮相关方法 91 | #伪彩色增强 92 | self.enhance1Act.triggered.connect(lambda : enhance1Image(self)) 93 | #真彩色增强 94 | self.enhance2Act.triggered.connect(lambda : enhance2Image(self)) 95 | #直方图均衡 96 | self.enhance3Act.triggered.connect(lambda : histNormalized(self)) 97 | #NTSC颜色模型 98 | self.enhance4Act.triggered.connect(lambda : enhance4Image(self)) 99 | #YCbCr颜色模型 100 | self.enhance5Act.triggered.connect(lambda : enhance5Image(self)) 101 | #HSV颜色模型 102 | self.enhance6Act.triggered.connect(lambda : enhance6Image(self)) 103 | 104 | #阈值分割方法 105 | self.threButton.clicked.connect(lambda : threImage(self)) 106 | #形态学处理方法 107 | self.morphologyProcessButton.clicked.connect(lambda : morphologyProcessImage(self)) 108 | #特征提取方法 109 | self.featureButton.clicked.connect(lambda : featureImage(self)) 110 | #图像分类与识别方法 111 | self.imgButton.clicked.connect(lambda : layoutChange(self)) 112 | #底部 113 | #上一张 114 | self.preButton.clicked.connect(lambda : preImage(self)) 115 | #下一张 116 | self.nextButton.clicked.connect(lambda : nextImage(self)) 117 | #退出 118 | self.exitButton.clicked.connect(self.close) 119 | 120 | #编辑按钮相关方法 121 | #放大 122 | def largeImage(window): 123 | imageList=[] 124 | for img in window.originImages: 125 | imgs=[] 126 | img_info=img[0].shape 127 | image_height=img_info[0] 128 | image_weight=img_info[1] 129 | dstHeight=int(2*image_height) 130 | dstWeight=int(2*image_weight) 131 | result=cv2.resize(img[0],(dstHeight,dstWeight)) 132 | imgs.extend([img[0],result]) 133 | imageList.append(imgs) 134 | resizeFromList(window, imageList) 135 | showImage(window,['原图','放大后']) 136 | #缩小 137 | def smallImage(window): 138 | imageList=[] 139 | for img in window.originImages: 140 | imgs=[] 141 | img_info=img[0].shape 142 | image_height=img_info[0] 143 | image_weight=img_info[1] 144 | dstHeight=int(0.5*image_height) 145 | dstWeight=int(0.5*image_weight) 146 | result=cv2.resize(img[0],(dstHeight,dstWeight)) 147 | imgs.extend([img[0],result]) 148 | imageList.append(imgs) 149 | resizeFromList(window, imageList) 150 | showImage(window,['原图','缩小后']) 151 | #灰度 152 | def grayImage(window): 153 | imageList=[] 154 | for img in window.originImages: 155 | imgs=[] 156 | result = cv2.cvtColor(img[0], cv2.COLOR_BGR2RGB) 157 | imgs.extend([img[0],result]) 158 | imageList.append(imgs) 159 | resizeFromList(window, imageList) 160 | showImage(window,['原图','灰度处理后']) 161 | #亮度 162 | def brightImage(window): 163 | imageList=[] 164 | for img in window.originImages: 165 | imgs=[] 166 | rows, cols, chunnel = img[0].shape 167 | blank = np.zeros([rows, cols, chunnel], img[0].dtype) 168 | result = cv2.addWeighted(img[0], 1.3, blank, 1-1.3, 3) 169 | imgs.extend([img[0],result]) 170 | imageList.append(imgs) 171 | resizeFromList(window, imageList) 172 | showImage(window,['原图','调整亮度后']) 173 | #旋转 174 | def rotateImage(window): 175 | imageList=[] 176 | for img in window.originImages: 177 | imgs=[] 178 | img_info=img[0].shape 179 | image_height=img_info[0] 180 | image_weight=img_info[1] 181 | mat_rotate=cv2.getRotationMatrix2D((image_height*0.5,image_weight*0.5),90,1) #center angle 3scale 182 | result=cv2.warpAffine(img[0],mat_rotate,(image_height,image_weight)) 183 | imgs.extend([img[0],result]) 184 | imageList.append(imgs) 185 | resizeFromList(window, imageList) 186 | showImage(window,['原图','旋转后']) 187 | #截图 188 | def screenshotImage(window): 189 | imageList=[] 190 | for img in window.originImages: 191 | imgs=[] 192 | result = img[0][70:170, 440:540] 193 | imgs.extend([img[0],result]) 194 | imageList.append(imgs) 195 | resizeFromList(window, imageList) 196 | showImage(window,['原图','截图后']) 197 | 198 | #变换按钮相关方法 199 | #傅里叶变换 200 | def change1Image(window): 201 | imageList=[] 202 | for img in window.originImages: 203 | imgs=[] 204 | b,g,r=cv2.split(img[0]) 205 | b_freImg,b_recImg=oneChannelDft(b) 206 | g_freImg, g_recImg = oneChannelDft(g) 207 | r_freImg, r_recImg = oneChannelDft(r) 208 | freImg=cv2.merge([b_freImg,g_freImg,r_freImg]) 209 | imgs.extend([img[0],freImg]) 210 | imageList.append(imgs) 211 | resizeFromList(window, imageList) 212 | showImage(window,['原图','傅里叶变换后']) 213 | def oneChannelDft(img): 214 | width, height = img.shape 215 | nwidth = cv2.getOptimalDFTSize(width) 216 | nheigth = cv2.getOptimalDFTSize(height) 217 | nimg = np.zeros((nwidth, nheigth)) 218 | nimg[:width, :height] = img 219 | dft = cv2.dft(np.float32(nimg), flags=cv2.DFT_COMPLEX_OUTPUT) 220 | ndft = dft[:width, :height] 221 | ndshift = np.fft.fftshift(ndft) 222 | magnitude = np.log(cv2.magnitude(ndshift[:, :, 0], ndshift[:, :, 1])) 223 | result = (magnitude - magnitude.min()) / (magnitude.max() - magnitude.min()) * 255 224 | frequencyImg = result.astype('uint8') 225 | ilmg = cv2.idft(dft) 226 | ilmg = cv2.magnitude(ilmg[:, :, 0], ilmg[:, :, 1])[:width, :height] 227 | ilmg = np.floor((ilmg - ilmg.min()) / (ilmg.max() - ilmg.min()) * 255) 228 | recoveredImg = ilmg.astype('uint8') 229 | return frequencyImg,recoveredImg 230 | 231 | #离散余弦变换 232 | def change2Image(window): 233 | imageList=[] 234 | for img in window.originImages: 235 | imgs=[] 236 | img1 = cv2.cvtColor(img[0], cv2.COLOR_BGR2RGB) 237 | img_dct = cv2.dct(img1) #进行离散余弦变换 238 | imgs.extend([img[0],img_dct]) 239 | imageList.append(imgs) 240 | resizeFromList(window, imageList) 241 | showImage(window,['原图','离散余弦变换后']) 242 | #Radon变换 243 | def change3Image(window): 244 | imageList=[] 245 | for img in window.originImages: 246 | imgs=[] 247 | img_dct = cv2.dct(img[0]) 248 | result = np.log(abs(img_dct)) 249 | imgs.extend([img[0],result]) 250 | imageList.append(imgs) 251 | resizeFromList(window, imageList) 252 | showImage(window,['原图','Radon变换后']) 253 | 254 | #噪声按钮相关方法 255 | #高斯噪声 256 | #定义添加高斯噪声的函数 257 | def addGaussianNoise(image,percetage): 258 | G_Noiseimg = image 259 | G_NoiseNum=int(percetage*image.shape[0]*image.shape[1]) 260 | for i in range(G_NoiseNum): 261 | temp_x = np.random.randint(20,40) 262 | temp_y = np.random.randint(20,40) 263 | G_Noiseimg[temp_x][temp_y] = 255 264 | return G_Noiseimg 265 | def noise1Image(window): 266 | imageList=[] 267 | for img in window.originImages: 268 | imgs=[] 269 | grayImage = cv2.cvtColor(img[0], cv2.COLOR_BGR2RGB) #灰度变换 270 | result = addGaussianNoise(grayImage,0.01) #添加10%的高斯噪声 271 | imgs.extend([img[0],result]) 272 | imageList.append(imgs) 273 | resizeFromList(window, imageList) 274 | showImage(window,['原图','高斯噪声后']) 275 | #椒盐噪声 276 | #定义添加椒盐噪声的函数 277 | def saltpepper(img,n): 278 | m=int((img.shape[0]*img.shape[1])*n) 279 | for a in range(m): 280 | i=int(np.random.random()*img.shape[1]) 281 | j=int(np.random.random()*img.shape[0]) 282 | if img.ndim==2: 283 | img[j,i]=255 284 | elif img.ndim==3: 285 | img[j,i,0]=255 286 | img[j,i,1]=255 287 | img[j,i,2]=255 288 | for b in range(m): 289 | i=int(np.random.random()*img.shape[1]) 290 | j=int(np.random.random()*img.shape[0]) 291 | if img.ndim==2: 292 | img[j,i]=0 293 | elif img.ndim==3: 294 | img[j,i,0]=0 295 | img[j,i,1]=0 296 | img[j,i,2]=0 297 | return img 298 | def noise2Image(window): 299 | imageList=[] 300 | for img in window.originImages: 301 | imgs=[] 302 | grayImage = cv2.cvtColor(img[0], cv2.COLOR_BGR2RGB) #灰度变换 303 | result = saltpepper(grayImage,0.02) 304 | imgs.extend([img[0],result]) 305 | imageList.append(imgs) 306 | resizeFromList(window, imageList) 307 | showImage(window,['原图','椒盐噪声后']) 308 | 309 | #滤波按钮相关方法 310 | #高通滤波 311 | def smoothing1Image(window): 312 | imageList=[] 313 | for img in window.originImages: 314 | imgs=[] 315 | x=cv2.Sobel(img[0],cv2.CV_16S,1,0) 316 | y=cv2.Sobel(img[0],cv2.CV_16S,0,1) 317 | absx=cv2.convertScaleAbs(x) 318 | absy=cv2.convertScaleAbs(y) 319 | result = cv2.addWeighted(absx,0.5,absy,0.5,0) 320 | imgs.extend([img[0],result]) 321 | imageList.append(imgs) 322 | resizeFromList(window, imageList) 323 | showImage(window,['原图','高通滤波后']) 324 | #低通滤波 325 | def smoothing2Image(window): 326 | imageList=[] 327 | for img in window.originImages: 328 | imgs=[] 329 | result = cv2.medianBlur(img[0],5) 330 | imgs.extend([img[0],result]) 331 | imageList.append(imgs) 332 | resizeFromList(window, imageList) 333 | showImage(window,['原图','低通滤波后']) 334 | #平滑滤波 335 | def smoothing3Image(window): 336 | imageList=[] 337 | for img in window.originImages: 338 | imgs=[] 339 | result = cv2.blur(img[0], (5, 5)) 340 | imgs.extend([img[0],result]) 341 | imageList.append(imgs) 342 | resizeFromList(window, imageList) 343 | showImage(window,['原图','平滑滤波后']) 344 | #锐化滤波 345 | def smoothing4Image(window): 346 | imageList=[] 347 | for img in window.originImages: 348 | imgs=[] 349 | result = cv2.bilateralFilter(img[0],9,75,75) 350 | imgs.extend([img[0],result]) 351 | imageList.append(imgs) 352 | resizeFromList(window, imageList) 353 | showImage(window,['原图','锐化滤波后']) 354 | 355 | #直方图统计按钮相关方法 356 | #R直方图 357 | def hist1Image(window): 358 | imageList=[] 359 | for img in window.originImages: 360 | imgs=[] 361 | color = ('b','g','r') 362 | for i,col in enumerate(color): 363 | histr = cv2.calcHist([img[0]],[i],None,[256],[0,256]) 364 | plt.plot(histr,color = col) 365 | plt.xlim([0,256]) 366 | plt.savefig("hist1.jpg") 367 | 368 | result = cv2.imread("hist1.jpg") 369 | imgs.extend([img[0],result]) 370 | imageList.append(imgs) 371 | resizeFromList(window, imageList) 372 | showImage(window,['原图','R直方图后']) 373 | 374 | #图像增强按钮相关方法 375 | #伪彩色增强 376 | def enhance1Image(window): 377 | imageList=[] 378 | 379 | for img in window.originImages: 380 | imgs=[] 381 | grayImage = cv2.cvtColor(img[0], cv2.COLOR_BGR2RGB) #灰度变换 382 | result = cv2.applyColorMap(grayImage, cv2.COLORMAP_JET) 383 | imgs.extend([img[0],result]) 384 | imageList.append(imgs) 385 | 386 | resizeFromList(window, imageList) 387 | showImage(window,['原图','伪彩色增强后']) 388 | #真彩色增强 389 | def enhance2Image(window): 390 | imageList=[] 391 | 392 | for img in window.originImages: 393 | imgs=[] 394 | grayImage = cv2.cvtColor(img[0], cv2.COLOR_BGR2RGB) #灰度变换 395 | result = cv2.applyColorMap(grayImage, cv2.COLORMAP_JET) 396 | imgs.extend([img[0],result]) 397 | imageList.append(imgs) 398 | 399 | resizeFromList(window, imageList) 400 | showImage(window,['原图','真彩色增强后']) 401 | #直方图均衡 402 | def histNormalized(window): 403 | imageList=[] 404 | 405 | for img in window.originImages: 406 | imgs=[] 407 | b, g, r = cv2.split(img[0]) 408 | b_equal = cv2.equalizeHist(b) 409 | g_equal = cv2.equalizeHist(g) 410 | r_equal = cv2.equalizeHist(r) 411 | result = cv2.merge([b_equal, g_equal, r_equal]) 412 | imgs.extend([img[0],result]) 413 | imageList.append(imgs) 414 | 415 | resizeFromList(window, imageList) 416 | showImage(window,['原图','直方图均衡化后']) 417 | 418 | #NTSC颜色模型 419 | def enhance4Image(window): 420 | imageList=[] 421 | 422 | for img in window.originImages: 423 | imgs=[] 424 | result = cv2.cvtColor(img[0], cv2.COLOR_BGR2RGB) 425 | imgs.extend([img[0],result]) 426 | imageList.append(imgs) 427 | 428 | resizeFromList(window, imageList) 429 | showImage(window,['原图','NTSC颜色模型后']) 430 | 431 | #YCbCr颜色模型 432 | def enhance5Image(window): 433 | imageList=[] 434 | 435 | for img in window.originImages: 436 | imgs=[] 437 | result = cv2.cvtColor(img[0], cv2.COLOR_BGR2YCR_CB) 438 | imgs.extend([img[0],result]) 439 | imageList.append(imgs) 440 | 441 | resizeFromList(window, imageList) 442 | showImage(window,['原图','YCbCr颜色模型后']) 443 | 444 | #HSV颜色模型 445 | def enhance6Image(window): 446 | imageList=[] 447 | 448 | for img in window.originImages: 449 | imgs=[] 450 | result = cv2.cvtColor(img[0],cv2.COLOR_BGR2HSV) 451 | imgs.extend([img[0],result]) 452 | imageList.append(imgs) 453 | 454 | resizeFromList(window, imageList) 455 | showImage(window,['原图','HSV颜色模型后']) 456 | 457 | #阈值分割方法 458 | def threImage(window): 459 | imageList=[] 460 | 461 | for img in window.originImages: 462 | imgs=[] 463 | grayImage = cv2.cvtColor(img[0], cv2.COLOR_BGR2RGB) #灰度变换 464 | result = cv2.threshold(grayImage, 127, 255, cv2.THRESH_BINARY) 465 | imgs.extend([img[0],result]) 466 | imageList.append(imgs) 467 | 468 | # resizeFromList(window, imageList) 469 | showImage(window,['原图','阈值分割后']) 470 | 471 | #形态学处理方法 472 | def morphologyProcessImage(window): 473 | imageList=[] 474 | 475 | for img in window.originImages: 476 | imgs=[] 477 | kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(3, 3)) 478 | result = cv2.erode(img[0],kernel) 479 | imgs.extend([img[0],result]) 480 | imageList.append(imgs) 481 | 482 | resizeFromList(window, imageList) 483 | showImage(window,['原图','形态学处理后']) 484 | 485 | #特征提取方法 486 | def featureImage(window): 487 | imageList=[] 488 | 489 | for img in window.originImages: 490 | imgs=[] 491 | img1 = img[0].copy() 492 | gray=cv2.cvtColor(img[0],cv2.COLOR_BGR2GRAY) 493 | gray=np.float32(gray) 494 | dst=cv2.cornerHarris(gray,2,3,0.04) 495 | img[0][dst>0.01*dst.max()]=[0,0,255] 496 | imgs.extend([img1,img[0]]) 497 | imageList.append(imgs) 498 | 499 | resizeFromList(window, imageList) 500 | showImage(window,['原图','特征提取后']) 501 | 502 | 503 | #打开图像 504 | def importImage(window): 505 | fname, _ = QFileDialog.getOpenFileName(window, 'Open file', '.', 'Image Files(*.jpg *.bmp *.png *.jpeg *.rgb *.tif)') 506 | if fname!='': 507 | window.importImageEdit.setText(fname) 508 | window.imagePaths = [] 509 | window.originImages = [] 510 | window.imageList = [] 511 | window.imagePaths.append(fname) 512 | if window.imagePaths!=[]: 513 | readIamge(window) 514 | resizeFromList(window, window.originImages) 515 | showImage(window) 516 | 517 | def readIamge(window): 518 | window.originImages=[] 519 | for path in window.imagePaths: 520 | imgs=[] 521 | # img=cv2.imread(path) 522 | img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), 1) 523 | # img=cv2.cvtColor(img,cv2.COLOR_RGB2BGR) 524 | imgs.append(img) 525 | window.originImages.append(imgs) 526 | 527 | #显示图像 528 | def showImage(window,headers=[]): 529 | window.showImageView.clear() 530 | window.showImageView.setColumnCount(len(window.imageList[0])) 531 | window.showImageView.setRowCount(len(window.imageList)) 532 | 533 | window.showImageView.setShowGrid(False) 534 | window.showImageView.setEditTriggers(QAbstractItemView.NoEditTriggers) 535 | window.showImageView.setHorizontalHeaderLabels(headers) 536 | for x in range(len(window.imageList[0])): 537 | for y in range(len(window.imageList)): 538 | imageView=QGraphicsView() 539 | imageView.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 540 | imageView.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) 541 | 542 | img=window.imageList[y][x] 543 | img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 544 | width=img.shape[1] 545 | height=img.shape[0] 546 | 547 | window.showImageView.setColumnWidth(x, width) 548 | window.showImageView.setRowHeight(y, height) 549 | 550 | frame = QImage(img, width, height, QImage.Format_RGB888) 551 | #调用QPixmap命令,建立一个图像存放框 552 | pix = QPixmap.fromImage(frame) 553 | item = QGraphicsPixmapItem(pix) 554 | scene = QGraphicsScene() # 创建场景 555 | scene.addItem(item) 556 | imageView.setScene(scene) 557 | window.showImageView.setCellWidget(y, x, imageView) 558 | 559 | def resizeFromList(window,imageList): 560 | width=600 561 | height=600 562 | window.imageList=[] 563 | for x_pos in range(len(imageList)): 564 | imgs=[] 565 | for img in imageList[x_pos]: 566 | 567 | # image=cv2.resize(img, (width, height)) 568 | image=cv2.resize(img, (width, height), interpolation=cv2.INTER_CUBIC) 569 | imgs.append(image) 570 | window.imageList.append(imgs) 571 | print(len(window.imageList),len(window.imageList[0])) 572 | 573 | if __name__=='__main__': 574 | 575 | app=QApplication(sys.argv) 576 | mw=MainWindow() 577 | mw.show() 578 | sys.exit(app.exec_()) 579 | -------------------------------------------------------------------------------- /mainWindowLayout.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | # -*- coding: utf-8 -*- 3 | 4 | from PyQt5.QtGui import * 5 | from PyQt5.QtCore import * 6 | from PyQt5.QtWidgets import * 7 | 8 | from PyQt5 import QtCore, QtGui, QtWidgets 9 | 10 | 11 | class MainLayout(object): 12 | 13 | def setupUi(self,window): 14 | window.resize(1000, 600) 15 | #窗口标题 16 | self.setWindowTitle('数字图像处理') 17 | 18 | self.centralWidget = QtWidgets.QWidget(window) 19 | 20 | #全局布局 21 | mainLayout=QVBoxLayout(self.centralWidget) 22 | self.label = QLabel() 23 | self.show() 24 | 25 | #顶部布局 26 | #顶部固定布局 27 | topLayout=QHBoxLayout() 28 | solidLayout=QHBoxLayout() 29 | self.importImageEdit=QLineEdit() 30 | self.importImageEdit.setFocusPolicy(Qt.NoFocus) 31 | solidLayout.addWidget(self.importImageEdit) 32 | #文件按钮 33 | self.importButton=QPushButton('文件') 34 | solidLayout.addWidget(self.importButton) 35 | filemenu = QMenu(self) 36 | self.openAct = QAction('打开',self) 37 | filemenu.addAction(self.openAct) 38 | self.saveAct = QAction('保存',self) 39 | filemenu.addAction(self.saveAct) 40 | self.exitAct = QAction('退出',self) 41 | filemenu.addAction(self.exitAct) 42 | self.importButton.setMenu(filemenu) 43 | #编辑按钮 44 | self.editButton=QPushButton('编辑') 45 | solidLayout.addWidget(self.editButton) 46 | editmenu = QMenu(self) 47 | self.largeAct = QAction('放大',self) 48 | editmenu.addAction(self.largeAct) 49 | self.smallAct = QAction('缩小',self) 50 | editmenu.addAction(self.smallAct) 51 | self.grayAct = QAction('灰度',self) 52 | editmenu.addAction(self.grayAct) 53 | self.brightAct = QAction('亮度',self) 54 | editmenu.addAction(self.brightAct) 55 | self.rotateAct = QAction('旋转',self) 56 | editmenu.addAction(self.rotateAct) 57 | self.screenshotAct = QAction('截图',self) 58 | editmenu.addAction(self.screenshotAct) 59 | self.editButton.setMenu(editmenu) 60 | #变换按钮 61 | self.changeButton=QPushButton('变换') 62 | solidLayout.addWidget(self.changeButton) 63 | changemenu = QMenu(self) 64 | self.change1Act = QAction('傅里叶变换',self) 65 | changemenu.addAction(self.change1Act) 66 | self.change2Act = QAction('离散余弦变换',self) 67 | changemenu.addAction(self.change2Act) 68 | self.change3Act = QAction('Radon变换',self) 69 | changemenu.addAction(self.change3Act) 70 | self.changeButton.setMenu(changemenu) 71 | #噪声按钮 72 | self.noiseButton=QPushButton('噪声') 73 | solidLayout.addWidget(self.noiseButton) 74 | noisemenu = QMenu(self) 75 | self.noise1Act = QAction('高斯噪声',self) 76 | noisemenu.addAction(self.noise1Act) 77 | self.noise2Act = QAction('椒盐噪声',self) 78 | noisemenu.addAction(self.noise2Act) 79 | self.noise3Act = QAction('斑点噪声',self) 80 | noisemenu.addAction(self.noise3Act) 81 | self.noise4Act = QAction('泊松噪声',self) 82 | noisemenu.addAction(self.noise4Act) 83 | self.noiseButton.setMenu(noisemenu) 84 | #滤波按钮 85 | self.smoothingButton=QPushButton('滤波') 86 | solidLayout.addWidget(self.smoothingButton) 87 | smoothingmenu = QMenu(self) 88 | self.smoothing1Act = QAction('高通滤波',self) 89 | smoothingmenu.addAction(self.smoothing1Act) 90 | self.smoothing2Act = QAction('低通滤波',self) 91 | smoothingmenu.addAction(self.smoothing2Act) 92 | self.smoothing3Act = QAction('平滑滤波',self) 93 | smoothingmenu.addAction(self.smoothing3Act) 94 | self.smoothing4Act = QAction('锐化滤波',self) 95 | smoothingmenu.addAction(self.smoothing4Act) 96 | self.smoothingButton.setMenu(smoothingmenu) 97 | #直方图统计按钮 98 | self.histButton=QPushButton('直方图统计') 99 | solidLayout.addWidget(self.histButton) 100 | histmenu = QMenu(self) 101 | self.hist1Act = QAction('R直方图',self) 102 | histmenu.addAction(self.hist1Act) 103 | self.hist2Act = QAction('G直方图',self) 104 | histmenu.addAction(self.hist2Act) 105 | self.hist3Act = QAction('B直方图',self) 106 | histmenu.addAction(self.hist3Act) 107 | self.histButton.setMenu(histmenu) 108 | #图像增强按钮 109 | self.enhanceButton=QPushButton('图像增强') 110 | solidLayout.addWidget(self.enhanceButton) 111 | enhancemenu = QMenu(self) 112 | self.enhance1Act = QAction('伪彩色增强',self) 113 | enhancemenu.addAction(self.enhance1Act) 114 | self.enhance2Act = QAction('真彩色增强',self) 115 | enhancemenu.addAction(self.enhance2Act) 116 | self.enhance3Act = QAction('直方图均衡',self) 117 | enhancemenu.addAction(self.enhance3Act) 118 | self.enhance4Act = QAction('NTSC颜色模型',self) 119 | enhancemenu.addAction(self.enhance4Act) 120 | self.enhance5Act = QAction('YCbCr颜色模型',self) 121 | enhancemenu.addAction(self.enhance5Act) 122 | self.enhance6Act = QAction('HSV颜色模型',self) 123 | enhancemenu.addAction(self.enhance6Act) 124 | self.enhanceButton.setMenu(enhancemenu) 125 | #阈值分割按钮 126 | self.threButton=QPushButton('阈值分割') 127 | solidLayout.addWidget(self.threButton) 128 | #形态学处理按钮 129 | self.morphologyProcessButton=QPushButton('形态学处理') 130 | solidLayout.addWidget(self.morphologyProcessButton) 131 | #特征提取按钮 132 | self.featureButton=QPushButton('特征提取') 133 | solidLayout.addWidget(self.featureButton) 134 | #图像分类与识别按钮 135 | self.imgButton=QPushButton('图像分类与识别') 136 | solidLayout.addWidget(self.imgButton) 137 | solidLayout.addStretch(1) 138 | topLayout.addLayout(solidLayout) 139 | 140 | #顶部隐藏布局 141 | self.hideLayout=QHBoxLayout() 142 | topLayout.addLayout(self.hideLayout) 143 | mainLayout.addLayout(topLayout) 144 | 145 | #中间布局 146 | midLayout=QHBoxLayout() 147 | self.showImageView=QTableWidget() 148 | midLayout.addWidget(self.showImageView) 149 | mainLayout.addLayout(midLayout) 150 | 151 | #底部布局 152 | bottomLayout=QHBoxLayout() 153 | self.preButton=QPushButton('上一张') 154 | bottomLayout.addWidget(self.preButton) 155 | self.nextButton=QPushButton('下一张') 156 | bottomLayout.addWidget(self.nextButton) 157 | bottomLayout.addStretch(4) 158 | self.exitButton=QPushButton('退出') 159 | bottomLayout.addWidget(self.exitButton) 160 | mainLayout.addLayout(bottomLayout) 161 | 162 | #设置stretch 163 | mainLayout.setStretchFactor(topLayout,1) 164 | mainLayout.setStretchFactor(midLayout,6) 165 | mainLayout.setStretchFactor(bottomLayout,1) 166 | 167 | window.setCentralWidget(self.centralWidget) 168 | 169 | 170 | 171 | --------------------------------------------------------------------------------