背景:机器视觉课堂编程作业之二
功能:实现边界检测、直线检测、圆检测
使用平台:python36 opencv34
注意事项:python36下的opencv34出现了一些函数的用法变动
总体效果还是很好的。
显示效果:
源代码:
1 #-*- coding:utf-8 -*- 2 #edited by Mufasa 3 4 import tkinter as tk 5 import tkinter.filedialog 6 from PIL import Image, ImageTk 7 import numpy as np 8 from tkinter import ttk 9 import time,threading 10 import matplotlib.pyplot as plt 11 from mpl_toolkits.mplot3d import Axes3D 12 from tkinter import messagebox 13 import cv2 14 import os 15 16 class main_: 17 # def ui_(): 18 19 def btn_begin(): 20 global root 21 btn_select = tk.Button(root,text=‘打开文件‘,width=15,command=assist.select).grid(row=0,column=0) 22 btn_about = tk.Button(root,text=‘关于程序‘,width=15,command=assist.about).grid(row=0,column=4) 23 def show_photo(): 24 global root 25 label = tk.Label(root) 26 def btn_then(): 27 global root 28 btn_about = tk.Button(root,text=‘显示灰度原图‘,width=15,command=assist.show_gray).grid(row=0,column=1) 29 btn_about = tk.Button(root,text=‘数据还原‘,width=15,command=assist.restart).grid(row=0,column=2) 30 btn_about = tk.Button(root,text=‘当前图像保存‘,width=15,command=assist.storage).grid(row=0,column=3) 31 32 btn_about = tk.Button(root,text=‘高斯滤波‘,width=15,command=filter.GaussianBlur).grid(row=1,column=0) 33 btn_about = tk.Button(root,text=‘均值滤波‘,width=15,command=filter.MeanBlur).grid(row=1,column=1) 34 btn_about = tk.Button(root,text=‘中值滤波‘,width=15,command=filter.medianBlur).grid(row=1,column=2) 35 btn_about = tk.Button(root,text=‘双边滤波‘,width=15,command=filter.bilateralFilter).grid(row=1,column=3) 36 btn_about = tk.Button(root,text=‘2d滤波器‘,width=15,command=filter.filter2D).grid(row=1,column=4) 37 38 btn_about = tk.Button(root,text=‘laplacian‘,width=15,command=algorithm.laplacian).grid(row=2,column=0) 39 btn_about = tk.Button(root,text=‘canny‘,width=15,command=algorithm.canny).grid(row=2,column=1) 40 btn_about = tk.Button(root,text=‘形态学‘,width=15,command=algorithm.morphology).grid(row=2,column=2) 41 btn_about = tk.Button(root,text=‘sobel算子‘,width=15,command=algorithm.sobel).grid(row=2,column=3) 42 btn_about = tk.Button(root,text=‘检测原理解释‘,width=15,command=assist.describe_edge).grid(row=2,column=4) 43 44 45 btn_about = tk.Button(root,text=‘梯度模型1‘,width=15,command=lambda:algorithm.gradient(n=0)).grid(row=3,column=0) 46 btn_about = tk.Button(root,text=‘梯度模型2‘,width=15,command=lambda:algorithm.gradient(n=1)).grid(row=3,column=1) 47 btn_about = tk.Button(root,text=‘梯度模型3‘,width=15,command=lambda:algorithm.gradient(n=2)).grid(row=3,column=2) 48 btn_about = tk.Button(root,text=‘梯度模型4‘,width=15,command=lambda:algorithm.gradient(n=3)).grid(row=3,column=3) 49 btn_about = tk.Button(root,text=‘梯度算法介绍‘,width=15,command=assist.describe_gradient).grid(row=3,column=4) 50 51 btn_about = tk.Button(root,text=‘霍夫曼直线‘,width=15,command=algorithm.HoughLines).grid(row=4,column=0) 52 btn_about = tk.Button(root,text=‘概率霍夫曼直线‘,width=15,command=algorithm.HoughLinesP).grid(row=4,column=1) 53 btn_about = tk.Button(root,text=‘霍夫曼圆检测‘,width=15,command=algorithm.HoughCircles).grid(row=4,column=2) 54 btn_about = tk.Button(root,text=‘直方图谱‘,width=15,command=assist._2D_out).grid(row=4,column=3) 55 btn_about = tk.Button(root,text=‘3D图谱显示‘,width=15,command=assist._3D_out).grid(row=4,column=4) 56 57 58 59 class assist: 60 def select(): 61 global data,path,im #data是图像的灰度值 62 path = tkinter.filedialog.askopenfilename(initialdir = ‘‘,filetypes=( ("Audio files", "*.jpg;*.bmp"),("All files", "*.*"))) 63 64 image = Image.open(path) 65 im = ImageTk.PhotoImage(image) 66 tk.Label(root, image = im).grid(row=5,column=0,columnspan=5) 67 68 data = cv2.imdecode(np.fromfile(path,dtype=np.uint8),-1) 69 if len(data.shape) >= 3: 70 data = cv2.cvtColor(data,cv2.COLOR_BGR2GRAY) 71 main_.btn_then() 72 73 def show_gray(): 74 global data 75 cv2.imshow(u"original", data) 76 cv2.waitKey() 77 cv2.destroyAllWindows() 78 79 def _3D_out(): 80 global data 81 fig = plt.figure() 82 ax = Axes3D(fig) 83 x = [i for i in range(len(data[0]))] 84 y = [j for j in range(len(data))] 85 86 X = np.mat(x) 87 Y = np.mat(y) 88 X, Y = np.meshgrid(X, Y) #变成二维矩阵 89 Z = np.mat(data) 90 ax.plot_surface(X, Y, Z, rstride=5, cstride=5, cmap=‘rainbow‘) 91 plt.show() 92 93 def _2D_out(): 94 global data 95 d_array = [0]*256 96 for i in data: 97 for j in i: 98 d_array[j] = d_array[j] + 1 99 plt.title(u"Ash rectangle",fontsize=24) 100 plt.xlabel("Ash values",fontsize=10) 101 plt.ylabel("Numbers",fontsize=10) 102 plt.plot(d_array,linewidth=1) 103 plt.show() 104 105 def restart(): 106 global data 107 data = cv2.imdecode(np.fromfile(path,dtype=np.uint8),-1) 108 if len(data.shape) >= 3: 109 data = cv2.cvtColor(data,cv2.COLOR_BGR2GRAY) 110 111 def about(): 112 tk.messagebox.showinfo(title=‘关于程序‘, message=( 113 ‘程序名称:边界检测\n程序平台:python3.6、opencv3.4\n编辑者:Mufasa\n编辑时间:2017.12.24\n\n主要功能:\n1)灰度直方图、3D图谱显示;\n2)高斯、均值、中值、双边、2d滤波器滤波;\n3)Laplacian、Canny、形态学方法、sobel方法;\n4)霍夫线变换、概率霍夫变换、霍夫圆变换;‘ 114 )) 115 116 def describe_edge(): 117 tk.messagebox.showinfo(title=‘算法简析‘, message=(‘Laplacian算法:计算灰度各个方向变化的二阶导数,将二阶导数的0值设置为边界\nCanny算法:去噪声、计算梯度幅值和方向、进行非极大值抑制\n形态学方法:将分别腐蚀和膨胀之后的图片进行相减处理\nsobel算子:应用sobel算子对灰度图像进行卷积处理‘)) 118 119 def describe_gradient(): 120 tk.messagebox.showinfo(title=‘梯度算法‘, message=(‘梯度算法:\n1)原理与sobel算子基本一致\n2)可以分为垂直水平和45度135度角的两种方向\n3)差值的取和方式分为算术和取最大值两种等多种形式‘)) 121 122 def storage(): 123 global data,path,name 124 p,f=os.path.split(path) 125 # print(p) 126 num = os.path.splitext(str(time.time()))[0] 127 # print(num) 128 # print(name) 129 # cv2.imwrite(p+‘\\‘+name+‘\\‘+num+‘.jpg‘, data) #python3版本下无法使用 130 cv2.imencode(‘.jpg‘, data)[1].tofile(p+‘//‘+name+"_"+num+‘.jpg‘) 131 132 133 class filter: 134 def GaussianBlur(): #高斯滤波 135 global data,name 136 data = cv2.GaussianBlur(data,(5,5),0) 137 cv2.imshow(u"GaussianBlur", data) 138 name = "GaussianBlur" 139 cv2.waitKey() 140 cv2.destroyAllWindows() 141 142 def MeanBlur(): #均值滤波 143 global data,name 144 data = cv2.blur(data,(3,5)) 145 cv2.imshow(u"MeanBlur", data) 146 name = "MeanBlur" 147 cv2.waitKey() 148 cv2.destroyAllWindows() 149 150 def filter2D(): #2D滤波器 151 global data,name 152 name = "filter2D" 153 kernel = np.ones((5,5),np.float32)/25 154 data = cv2.filter2D(data,-1,kernel) 155 cv2.imshow(u"filter2D", data) 156 cv2.waitKey() 157 cv2.destroyAllWindows() 158 159 def bilateralFilter(): #双边滤波 160 global data,name 161 name = "bilateralFilter" 162 data = cv2.bilateralFilter(data,9,75,75) 163 cv2.imshow(u"bilateralFilter", data) 164 cv2.waitKey() 165 cv2.destroyAllWindows() 166 167 def medianBlur(): #中值滤波 168 global data,name 169 name = "medianBlur" 170 171 data = cv2.medianBlur(data,5) 172 cv2.imshow(u"medianBlur", data) 173 cv2.waitKey() 174 cv2.destroyAllWindows() 175 176 class algorithm: 177 def laplacian(): 178 global data,name 179 name = "laplacian" 180 gray_lap = cv2.Laplacian(data,cv2.CV_16S,ksize = 3) 181 data = cv2.convertScaleAbs(gray_lap) 182 cv2.imshow(‘laplacian‘,data) 183 cv2.waitKey() 184 cv2.destroyAllWindows() 185 186 def canny(): 187 global data,name 188 name = "canny" 189 data = cv2.Canny(data, 50, 100) 190 cv2.imshow(‘canny‘,data) 191 cv2.waitKey() 192 cv2.destroyAllWindows() 193 194 def morphology(): #形态学边界检测,膨胀和腐蚀后的图片相减 195 global data,name 196 name = "morphology" 197 element = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3)) 198 dilate = cv2.dilate(data, element) # 扩大;膨胀;详述 199 erode = cv2.erode(data, element) # 腐蚀,侵蚀 200 data = cv2.absdiff(dilate,erode) 201 cv2.imshow(‘morphology‘,data) 202 cv2.waitKey() 203 cv2.destroyAllWindows() 204 205 def gradient(n): 206 if n == 0: 207 flag1,flag2 =0,0 208 elif n == 1: 209 flag1,flag2 =0,1 210 elif n == 2: 211 flag1,flag2 =1,0 212 elif n == 3: 213 flag1,flag2 =1,1 214 215 global data,name 216 name = "gradient" 217 218 w = data.shape[0] 219 h = data.shape[1] 220 size = (w,h) #(575, 768) 221 iSharp = np.zeros(size, dtype=‘uint8‘) 222 t = 3 223 for i in range(0,w-t): #高度减1! #这里需要注意 i——(0,768-1-1=766) 224 for j in range(0,h-t): #宽度也减1 j——(0,575-1-1=573) 225 if flag2 == 0: 226 x = abs(int(data[i,j+t])-int(data[i,j])) 227 y = abs(int(data[i+t,j])-int(data[i,j])) #index 575 is out of bounds for axis 0 with size 575 228 else: 229 x = abs(int(data[i+t,j+t])-int(data[i,j])) 230 y = abs(int(data[i+t,j])-int(data[i,j+t])) 231 232 if flag1 == 0: 233 iSharp[i,j] = max(x,y) 234 elif int(x)+int(y)>255: 235 iSharp[i,j] = 255 #内存溢出可能出现的地点 236 else: 237 iSharp[i,j] = x+y 238 data = iSharp 239 cv2.imshow(‘gradient‘,data) 240 cv2.waitKey() 241 cv2.destroyAllWindows() 242 243 def sobel(): 244 global data,name 245 name = "sobel" 246 247 x = cv2.Sobel(data,cv2.CV_16S,1,0) 248 y = cv2.Sobel(data,cv2.CV_16S,0,1) 249 absX = cv2.convertScaleAbs(x)# 转回uint8 250 absY = cv2.convertScaleAbs(y) 251 data = cv2.addWeighted(absX,1,absY,1,0) 252 cv2.imshow(‘sobel‘,data) 253 cv2.waitKey() 254 cv2.destroyAllWindows() 255 256 def HoughLines(): 257 global data,name 258 name = "HoughLines" 259 260 img = cv2.GaussianBlur(data,(3,3),0) #先进行高斯滤波,这里必须要先进行这一项 261 img = cv2.Canny(img, 50, 150, apertureSize = 3) #canny算子边界检测 262 lines = cv2.HoughLines(img,1,np.pi/180,100) #这里对最后一个参数使用了经验型的值 263 result = data.copy() 264 for i in lines: 265 for j in i: 266 rho = j[0] #第一个元素是距离rho 267 theta= j[1] #第二个元素是角度theta 268 if (theta < (np.pi/4. )) or (theta > (3.*np.pi/4.0)): #垂直直线 269 pt1 = (int(rho/np.cos(theta)),0) 270 #该直线与最后一行的焦点 271 pt2 = (int((rho-result.shape[0]*np.sin(theta))/np.cos(theta)),result.shape[0]) 272 #绘制一条白线 273 cv2.line( result, pt1, pt2, (255)) 274 else: #水平直线 275 # 该直线与第一列的交点 276 pt1 = (0,int(rho/np.sin(theta))) 277 #该直线与最后一列的交点 278 pt2 = (result.shape[1], int((rho-result.shape[1]*np.cos(theta))/np.sin(theta))) 279 #绘制一条直线 280 cv2.line(result, pt1, pt2, (255), 1) 281 data = result 282 cv2.imshow(‘HoughLines‘,data) 283 cv2.waitKey() 284 cv2.destroyAllWindows() 285 286 def HoughLinesP(): 287 global data,name 288 name = "HoughLinesP" 289 290 edges = cv2.Canny(data, 50, 150, apertureSize = 3) 291 minLineLength = 60 292 maxLineGap = 10 293 lines = cv2.HoughLinesP(edges,1,np.pi/180,80,minLineLength,maxLineGap) 294 for i in lines: 295 for x1,y1,x2,y2 in i: 296 cv2.line(data,(x1,y1),(x2,y2),(255),2) 297 cv2.imshow(‘HoughLinesP‘,data) 298 cv2.waitKey() 299 cv2.destroyAllWindows() 300 301 def HoughCircles(): 302 global data,name 303 name = "HoughCircles" 304 305 edge = cv2.medianBlur(data, 5) 306 circles = cv2.HoughCircles(edge, cv2.HOUGH_GRADIENT, 1, 120, param1=100, param2 = 30, minRadius = 0, maxRadius = 0) 307 circles = np.uint16(np.around(circles)) 308 for i in circles[0,:,:]: 309 cv2.circle(data, (i[0], i[1]), i[2],(255),1) 310 cv2.circle(data, (i[0], i[1]), 1, (255), 1) 311 cv2.imshow("HoughCircles", data) 312 cv2.waitKey() 313 cv2.destroyAllWindows() 314 315 global data,path,root,name 316 name = ‘original‘ 317 318 root = tk.Tk() 319 main_.btn_begin() 320 root.mainloop()
源程序及exe可执行程序链接
链接:https://pan.baidu.com/s/1cptezW 密码:iukp