3种python3的canny边缘检测之静态,可调节和自适应
先看高级版的python3的canny的自适应边缘检测:
car的效果图
内容:
1 canny的边缘检测的介绍。
2 三种方法的canny的边缘检测,由浅入深地介绍:固定值的静态,可自调节的,自适应的。
说明:
1 环境:python3.8、opencv4.5.3和matplotlib3.4.3。
2 图片:来自今日头条正版免费图库。
3 实现自适应阈值的canny边缘检测的参考代码和文章:#基于python2实现自适应阈值的canny https://github.com/sadimanna/canny #本文基于python3,复现一种自适应的阈值分割方法。 https://blog.csdn.net/lyxleft/article/details/91558726?spm=1001.2014.3001.5501
上述的代码,本机均有报错,故对代码进行修改,注释和运行。
初级canny:
1 介绍:opencv中给出了canny边缘检测的接口,直接调用:ret = cv2.canny(img,t1,t2)
即可得到边缘检测的结果ret,其中,t1,t2是需要人为设置的阈值。
2 python的opencv的一行代码即可实现边缘检测。
3 Canny函数及使用:函数:Canny edges = cv2.Canny(image, threshold1, threashold2) 参数: image : 原始图像 threshold1 : 阈值1 (minVal) threshold2 : 阈值2 (maxVal) 返回值:edges : 边缘图像
4 Canny边缘检测流程:
去噪 --> 梯度 --> 非极大值抑制 --> 滞后阈值Canny边缘检测算法其实非常复杂,包括4个步骤: 1 去噪:用高斯滤波器对图像进行去噪 2 梯度:计算梯度 3 NMS:在边缘上使用非极大值抑制(NMS) 4 滞后阈值: 在检测到的边缘上使用双阈值去除假阳性 分析所有的边缘及其之间的连接,以保留真正的边缘去除不明显的边缘
5 代码:import cv2 img = cv2.imread("/home/xgj/Desktop/edge_detection/snake.jpeg", cv2.IMREAD_GRAYSCALE) cv2.imshow("snake", img) ret1 = cv2.Canny(img, 100, 200) #人工设置固定值 cv2.imshow("result1", ret1) ret2 = cv2.Canny(img, 20, 60) #人工设置固定值 cv2.imshow("result2", ret2) cv2.waitKey() cv2.destroyAllWindows()
6 操作和过程:
7 原图:
8 疑问:
ret = cv2.canny(img,t1,t2),其中,t1,t2是需要人为设置的阈值,一般人怎么知道具体数值是多少,才是最佳的呀?所以,这是它的缺点。
中级canny:
1 中级canny,就是可调节的阈值,找到最佳的canny边缘检测效果。
2 采用cv2.createTrackbar来调节阈值。
3 代码:import cv2 import numpy as np img= cv2.imread("/home/xgj/Desktop/edge_detection/3_self_canny/girl.jpeg") cv2.namedWindow("Canny edge detect") #设置窗口,cv2.WINDOW_NORMAL表示窗口大小可自动调节 cv2.namedWindow("Original Image") def nothing(x): pass # 创建两个滑动条,分别控制minVal(最小阈值)、maxVal(最大阈值). # minVal:滑动条名称; "Canny edge detect":窗口名; 60:滑动条默认滑动位置; 300:最大值 ; nothing:回调函数 cv2.createTrackbar("minVal","Canny edge detect",60,300,nothing) cv2.createTrackbar("maxVal","Canny edge detect",100,400,nothing) while(1): #获得滑动条所在的位置 #cv2.getTrackbarPos(滑动条名称,窗口名); minVal = cv2.getTrackbarPos("minVal","Canny edge detect") maxVal = cv2.getTrackbarPos("maxVal","Canny edge detect") #Canny边缘检测 #cv2.Canny函数参数解析: # img:原图像名 # minVal:最小梯度 # maxVal:最大梯度 # 5 :5*5大小的高斯滤波器(卷积核),用来消除噪声影响 # L2gradient :求图像梯度,从而进行去除非边界上的点(非极大值抑制) edgeImage = cv2.Canny(img,minVal,maxVal,5,L2gradient=True) #显示图片 cv2.imshow("Original Image",img) #原图 cv2.imshow("Canny edge detect",edgeImage) # Canny检测后的图 k = cv2.waitKey(1) if k ==ord("q")& 0xFF: # 按 q 退出 break cv2.destroyAllWindows()#销毁窗口
4 操作和效果:
5 原图:
高级canny:
1 自适应canny的算法:
ret = cv2.canny(img,t1,t2)
即算法在运行过程中能够自适应地找到较佳的分割阈值t1,t2。
2 文件结构:
3 main.py代码: # 主程序:main.py # 第1步:模块导入 import numpy as np import cv2, time, math from matplotlib import pyplot as plt from scipy.signal import convolve2d as conv2 #两个自定义模块(库)导入 from bilateralfilt import bilatfilt from dog import deroGauss # 第2步:函数定义 # 2-1 获取边缘函数:用高斯滤波器对图像进行去噪 def get_edges(I,sd): dim = I.shape Idog2d = np.zeros((nang,dim[0],dim[1])) for i in range(nang): dog2d = deroGauss(5,sd,angles[i]) Idog2dtemp = abs(conv2(I,dog2d,mode="same",boundary="fill")) Idog2dtemp[Idog2dtemp<0]=0 Idog2d[i,:,:] = Idog2dtemp return Idog2d # 2-2 计算梯度 def calc_sigt(I,threshval): M,N = I.shape ulim = np.uint8(np.max(I)) N1 = np.count_nonzero(I>threshval) N2 = np.count_nonzero(I<=threshval) w1 = np.float64(N1)/(M*N) w2 = np.float64(N2)/(M*N) try: u1 = sum(i*np.count_nonzero(np.multiply(I>i-0.5,I<=i+0.5))/N1 for i in range(threshval+1,ulim)) u2 = sum(i*np.count_nonzero(np.multiply(I>i-0.5,I<=i+0.5))/N2 for i in range(threshval+1)) uT = u1*w1+u2*w2 sigt = w1*w2*(u1-u2)**2 except: return 0 return sigt # 2-3 非极大值抑制(NMS) def nonmaxsup(I,gradang): dim = I.shape Inms = np.zeros(dim) xshift = int(np.round(math.cos(gradang*np.pi/180))) yshift = int(np.round(math.sin(gradang*np.pi/180))) Ipad = np.pad(I,(1,),"constant",constant_values = (0,0)) for r in range(1,dim[0]+1): for c in range(1,dim[1]+1): maggrad = [Ipad[r-xshift,c-yshift],Ipad[r,c],Ipad[r+xshift,c+yshift]] if Ipad[r,c] == np.max(maggrad): Inms[r-1,c-1] = Ipad[r,c] return Inms # 2-4-1 阈值 def threshold(I,uth): lth = uth/2.5 Ith = np.zeros(I.shape) Ith[I>=uth] = 255 Ith[I=lth, I0: Ipad[i,j] = 255 else: Ipad[i,j] = 0 Ih = Ipad[1:r+1,1:c+1] return Ih # 2-4-3 获取最佳阈值 def get_threshold(I): max_sigt = 0 opt_t = 0 ulim = np.uint8(np.max(I)) print(ulim," ") for t in range(ulim+1): sigt = calc_sigt(I,t) if sigt > max_sigt: max_sigt = sigt opt_t = t print ("optimal high threshold: ",opt_t," ") return opt_t # 第3步:图片读取 # 读取原图 img = cv2.imread("/home/xgj/Desktop/edge_detection/3_self_canny/car.jpeg") # 判断原图大小,如果大于多少,就调节图片大小 # 否则不调节 while img.shape[0] > 1100 or img.shape[1] > 1100: img = cv2.resize(img,None, fx=0.5,fy=0.5,interpolation = cv2.INTER_AREA) # 转换为gray灰度图 gimg = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) dim = img.shape #获取图片大小 # 第4步:开始图像的canny的自适应操作 #Bilateral filtering=双边滤波 print("总共有2步:有一定的耗时,与图片大小有关 ") print("第1步: ") print ("Bilateral filtering... ") # 双边滤波:达到保边去噪 gimg = bilatfilt(gimg,5,3,10) print ("after bilat: ",np.max(gimg)," ") #获取时间计时 stime = time.time() angles = [0,45,90,135] nang = len(angles) #Gradient of Image=图片的梯度 print ("Calculating Gradient... ") img_edges = get_edges(gimg,2) print ("after gradient: ",np.max(img_edges)," ") #Non-max suppression:在边缘上使用非极大值抑制(NMS) print ("Suppressing Non-maximas... ") for n in range(nang): img_edges[n,:,:] = nonmaxsup(img_edges[n,:,:],angles[n]) print ("after nms: ", np.max(img_edges)," ") print ("请关掉matplotlib的图形窗口,进行下一步自适应… ") img_edge = np.max(img_edges,axis=0) lim = np.uint8(np.max(img_edge)) plt.imshow(img_edge) plt.show() print("第2步 函数调用: ") # 计算阈值 print ("Calculating Threshold... ") th = get_threshold(gimg) the = get_threshold(img_edge) # 获取阈值 print (" Thresholding... ") img_edge = threshold(img_edge, the*0.25) # 在边缘上使用非极大值抑制,滞后效应,获取自适应阈值 print ("Applying Hysteresis... ") img_edge = nonmaxsup(hysteresis(img_edge),90) # 第5步:canny调用获取的自适应阈值 # 获取自适应的阈值采用canny进行边缘检测 img_canny = cv2.Canny(np.uint8(gimg),th/3,th) cv2.imshow("Uncanny",img_edge) cv2.imshow("Canny",img_canny) print( "Time taken :: ", str(time.time()-stime)+" seconds... ") print("结束!!") cv2.waitKey(0)
4 dog.py代码:import numpy as np import math def deroGauss(w=5,s=1,angle=0): wlim = (w-1)/2 y,x = np.meshgrid(np.arange(-wlim,wlim+1),np.arange(-wlim,wlim+1)) G = np.exp(-np.sum((np.square(x),np.square(y)),axis=0)/(2*np.float64(s)**2)) G = G/np.sum(G) dGdx = -np.multiply(x,G)/np.float64(s)**2 dGdy = -np.multiply(y,G)/np.float64(s)**2 angle = angle*math.pi/180 dog = math.cos(angle)*dGdx + math.sin(angle)*dGdy return dog
5 bilateralfilt.py代码:import numpy as np # 双边滤波 def bilatfilt(I,w,sd,sr): dim = I.shape Iout= np.zeros(dim) wlim = (w-1)//2 y,x = np.meshgrid(np.arange(-wlim,wlim+1),np.arange(-wlim,wlim+1)) g = np.exp(-np.sum((np.square(x),np.square(y)),axis=0)/(2*(np.float64(sd)**2))) Ipad = np.pad(I,(wlim,),"edge") for r in range(wlim,dim[0]+wlim): for c in range(wlim,dim[1]+wlim): Ix = Ipad[r-wlim:r+wlim+1,c-wlim:c+wlim+1] s = np.exp(-np.square(Ix-Ipad[r,c])/(2*(np.float64(sr)**2))) k = np.multiply(g,s) Iout[r-wlim,c-wlim] = np.sum(np.multiply(k,Ix))/np.sum(k) return Iout
6 原图:
7 效果图:本文第一个gif图,此处省略。
小结:
1 本文由浅入深,总结的很好,适合收藏。
2 对于理解python的opencv的canny的边缘检测,很有帮助。
3 本文高级版canny自适应的算法参考2篇文章,虽然我进行代码的删除,注释,修改,优化等操作,故我不标注原创,对原作者表达敬意。
4 自己总结和整理,分享出来,希望对大家有帮助。
APP开屏广告不能按下葫芦浮起瓢来源中工网工人日报原标题APP开屏广告不能按下葫芦浮起瓢海凝据12月19日北京日报报道,时下,不少APP开屏广告的触发开关由点击变成了摇一摇将手机放进口袋,或者走动小跑坐地铁时遇到
微信这次真的赢麻了重点回顾1。这些手机可能要永远消失了2。今天下载这App的网友,全都黑屏死机了3。这玩意要是量产,出门再也不用带手机机友们都知道,现在在使用App或者服务之前,都需要同意一份用户协
雷军这是要干啥?退出多家小米关联公司发生了什么?雷军被夺权了吗?还是又要创新的事业?众多企业家里,我最喜欢的企业家就是雷军了。真是个有趣又接地气的人。人生经历也堪称传奇,简直就是我重生穿越小说最想要成为的人的原型啊。
大神闭关7天整理!137页Python学习笔记,全面总结看这一篇就够了今天给大家分享一份大神整理的Python学习笔记,137页超全汇总,将一个核心知识点统筹在一个章节里面,更具条理性和提炼性,方便大家吃透Python难点,很适合新手入门。数字类型P
危机之下,联想的回应联想事件已经过去很长时间了,而司马南先生的视频我也看了十四期,联想那边除了柳传志的一段有关联想保卫战的动员语音,12月10日又发出了一篇内网声明,我大致看了看,就是自己证明自己的一
社区电商,风向变了作者易牟原创深眸财经(chutou0325)近日,人民日报一则专文引起了大家的注意。该文章以精准化产销,数字化便民让新鲜农产品搭上互联网快车为题,释放出了明显的支持信号,给了整个行
奇瑞新能源在尾灯的造型方面,小巧灵感来源于小巧的小型SUV,让人不得不再担心小蚂蚁的外观设计。而蚂蚁在外观和安全配置上做了很多升级,其中最大的不同就是在内饰方面,奇瑞EQ1基本延续了奇瑞最新
1。8亿!东芝冰箱11月销售成绩最新出炉,怎一个厉害了得?就在刚刚过去的11月份,东芝冰箱全渠道销售1。8亿,单月销售再创新高!这一销售成绩在当下无疑是亮眼的值得行业学习的。我们都知道,东芝冰箱来自日本,有着悠长的发展历史和深厚的消费者基
电脑故障诊断与维修主板短路或接地通19V电压,电压降到1V,说明大短路,一般都是下拉电阻电容芯片击穿,摸那个器件发烫,就更换哪个器件。比如电脑插电待机电流为19V0。1A或0。2A(此时CPU没有启
千米快修小米MIXFold2渲染7000mAh8英寸大屏最近,折叠屏可谓是机器圈的一个热词。首先是OPPO发布了极为便携的OPPOFindN,然后预热了华为首款垂直折叠屏华为P50Pocket。这些手机不断突破折叠屏的定义和门槛,让大家
知乎多次出现禁止发布传输的信息被约谈!曾被责令自查自纠12月20日,南都记者获悉,近日,国家互联网信息办公室指导北京市互联网信息办公室依法约谈知乎网负责人,针对知乎网多次出现法律法规禁止发布或者传输的信息等问题,依据网络安全法,责令其