先看高级版的python3的canny的自适应边缘检测: car的效果图 内容: 1canny的边缘检测的介绍。 2三种方法的canny的边缘检测,由浅入深地介绍:固定值的静态,可自调节的,自适应的。 说明: 1环境:python3。8、opencv4。5。3和matplotlib3。4。3。 2图片:来自今日头条正版免费图库。 3实现自适应阈值的canny边缘检测的参考代码和文章:基于python2实现自适应阈值的cannyhttps:github。comsadimannacanny本文基于python3,复现一种自适应的阈值分割方法。https:blog。csdn。netlyxleftarticledetails91558726?spm1001。2014。3001。5501 上述的代码,本机均有报错,故对代码进行修改,注释和运行。 初级canny: 1介绍:opencv中给出了canny边缘检测的接口,直接调用:retcv2。canny(img,t1,t2) 即可得到边缘检测的结果ret,其中,t1,t2是需要人为设置的阈值。 2python的opencv的一行代码即可实现边缘检测。 3Canny函数及使用:函数:Cannyedgescv2。Canny(image,threshold1,threashold2)参数:image:原始图像threshold1:阈值1(minVal)threshold2:阈值2(maxVal)返回值:edges:边缘图像 4Canny边缘检测流程: 去噪梯度非极大值抑制滞后阈值Canny边缘检测算法其实非常复杂,包括4个步骤:1去噪:用高斯滤波器对图像进行去噪2梯度:计算梯度3NMS:在边缘上使用非极大值抑制(NMS)4滞后阈值:在检测到的边缘上使用双阈值去除假阳性分析所有的边缘及其之间的连接,以保留真正的边缘去除不明显的边缘 5代码:importcv2imgcv2。imread(homexgjDesktopedgedetectionsnake。jpeg,cv2。IMREADGRAYSCALE)cv2。imshow(snake,img)ret1cv2。Canny(img,100,200)人工设置固定值cv2。imshow(result1,ret1)ret2cv2。Canny(img,20,60)人工设置固定值cv2。imshow(result2,ret2)cv2。waitKey()cv2。destroyAllWindows() 6操作和过程: 7原图: 8疑问: retcv2。canny(img,t1,t2),其中,t1,t2是需要人为设置的阈值,一般人怎么知道具体数值是多少,才是最佳的呀?所以,这是它的缺点。 中级canny: 1中级canny,就是可调节的阈值,找到最佳的canny边缘检测效果。 2采用cv2。createTrackbar来调节阈值。 3代码:importcv2importnumpyasnpimgcv2。imread(homexgjDesktopedgedetection3selfcannygirl。jpeg)cv2。namedWindow(Cannyedgedetect)设置窗口,cv2。WINDOWNORMAL表示窗口大小可自动调节cv2。namedWindow(OriginalImage)defnothing(x):pass创建两个滑动条,分别控制minVal(最小阈值)、maxVal(最大阈值)。minVal:滑动条名称;Cannyedgedetect:窗口名;60:滑动条默认滑动位置;300:最大值;nothing:回调函数cv2。createTrackbar(minVal,Cannyedgedetect,60,300,nothing)cv2。createTrackbar(maxVal,Cannyedgedetect,100,400,nothing)while(1):获得滑动条所在的位置cv2。getTrackbarPos(滑动条名称,窗口名);minValcv2。getTrackbarPos(minVal,Cannyedgedetect)maxValcv2。getTrackbarPos(maxVal,Cannyedgedetect)Canny边缘检测cv2。Canny函数参数解析:img:原图像名minVal:最小梯度maxVal:最大梯度5:55大小的高斯滤波器(卷积核),用来消除噪声影响L2gradient:求图像梯度,从而进行去除非边界上的点(非极大值抑制)edgeImagecv2。Canny(img,minVal,maxVal,5,L2gradientTrue)显示图片cv2。imshow(OriginalImage,img)原图cv2。imshow(Cannyedgedetect,edgeImage)Canny检测后的图kcv2。waitKey(1)ifkord(q)0xFF:按q退出breakcv2。destroyAllWindows()销毁窗口 4操作和效果: 5原图: 高级canny: 1自适应canny的算法: retcv2。canny(img,t1,t2) 即算法在运行过程中能够自适应地找到较佳的分割阈值t1,t2。 2文件结构: 3main。py代码:主程序:main。py第1步:模块导入importnumpyasnpimportcv2,time,mathfrommatplotlibimportpyplotaspltfromscipy。signalimportconvolve2dasconv2两个自定义模块(库)导入frombilateralfiltimportbilatfiltfromdogimportderoGauss第2步:函数定义21获取边缘函数:用高斯滤波器对图像进行去噪defgetedges(I,sd):dimI。shapeIdog2dnp。zeros((nang,dim〔0〕,dim〔1〕))foriinrange(nang):dog2dderoGauss(5,sd,angles〔i〕)Idog2dtempabs(conv2(I,dog2d,modesame,boundaryfill))Idog2dtemp〔Idog2dtemp0〕0Idog2d〔i,:,:〕Idog2dtempreturnIdog2d22计算梯度defcalcsigt(I,threshval):M,NI。shapeulimnp。uint8(np。max(I))N1np。countnonzero(Ithreshval)N2np。countnonzero(Ithreshval)w1np。float64(N1)(MN)w2np。float64(N2)(MN)try:u1sum(inp。countnonzero(np。multiply(Ii0。5,Ii0。5))N1foriinrange(threshval1,ulim))u2sum(inp。countnonzero(np。multiply(Ii0。5,Ii0。5))N2foriinrange(threshval1))uTu1w1u2w2sigtw1w2(u1u2)2except:return0returnsigt23非极大值抑制(NMS)defnonmaxsup(I,gradang):dimI。shapeInmsnp。zeros(dim)xshiftint(np。round(math。cos(gradangnp。pi180)))yshiftint(np。round(math。sin(gradangnp。pi180)))Ipadnp。pad(I,(1,),constant,constantvalues(0,0))forrinrange(1,dim〔0〕1):forcinrange(1,dim〔1〕1):maggrad〔Ipad〔rxshift,cyshift〕,Ipad〔r,c〕,Ipad〔rxshift,cyshift〕〕ifIpad〔r,c〕np。max(maggrad):Inms〔r1,c1〕Ipad〔r,c〕returnInms241阈值defthreshold(I,uth):lthuth2。5Ithnp。zeros(I。shape)Ith〔Iuth〕255Ith〔Ilth〕0Ith〔np。multiply(Ilth,Iuth)〕100returnIth242hysteresis滞后(效应)defhysteresis(I):r,cI。shapeIpadnp。pad(I,(1,),edge)c255np。countnonzero(Ipad255)imgchangeTrueforiinrange(1,r1):forjinrange(1,c1):ifIpad〔i,j〕100:ifnp。countnonzero(Ipad〔r1:r1,c1:c1〕255)0:Ipad〔i,j〕255else:Ipad〔i,j〕0IhIpad〔1:r1,1:c1〕returnIh243获取最佳阈值defgetthreshold(I):maxsigt0optt0ulimnp。uint8(np。max(I))print(ulim,)fortinrange(ulim1):sigtcalcsigt(I,t)ifsigtmaxsigt:maxsigtsigtoptttprint(optimalhighthreshold:,optt,)returnoptt第3步:图片读取读取原图imgcv2。imread(homexgjDesktopedgedetection3selfcannycar。jpeg)判断原图大小,如果大于多少,就调节图片大小否则不调节whileimg。shape〔0〕1100orimg。shape〔1〕1100:imgcv2。resize(img,None,fx0。5,fy0。5,interpolationcv2。INTERAREA)转换为gray灰度图gimgcv2。cvtColor(img,cv2。COLORBGR2GRAY)dimimg。shape获取图片大小第4步:开始图像的canny的自适应操作Bilateralfiltering双边滤波print(总共有2步:有一定的耗时,与图片大小有关)print(第1步:)print(Bilateralfiltering。。。)双边滤波:达到保边去噪gimgbilatfilt(gimg,5,3,10)print(afterbilat:,np。max(gimg),)获取时间计时stimetime。time()angles〔0,45,90,135〕nanglen(angles)GradientofImage图片的梯度print(CalculatingGradient。。。)imgedgesgetedges(gimg,2)print(aftergradient:,np。max(imgedges),)Nonmaxsuppression:在边缘上使用非极大值抑制(NMS)print(SuppressingNonmaximas。。。)forninrange(nang):imgedges〔n,:,:〕nonmaxsup(imgedges〔n,:,:〕,angles〔n〕)print(afternms:,np。max(imgedges),)print(请关掉matplotlib的图形窗口,进行下一步自适应)imgedgenp。max(imgedges,axis0)limnp。uint8(np。max(imgedge))plt。imshow(imgedge)plt。show()print(第2步函数调用:)计算阈值print(CalculatingThreshold。。。)thgetthreshold(gimg)thegetthreshold(imgedge)获取阈值print(Thresholding。。。)imgedgethreshold(imgedge,the0。25)在边缘上使用非极大值抑制,滞后效应,获取自适应阈值print(ApplyingHysteresis。。。)imgedgenonmaxsup(hysteresis(imgedge),90)第5步:canny调用获取的自适应阈值获取自适应的阈值采用canny进行边缘检测imgcannycv2。Canny(np。uint8(gimg),th3,th)cv2。imshow(Uncanny,imgedge)cv2。imshow(Canny,imgcanny)print(Timetaken::,str(time。time()stime)seconds。。。)print(结束!!)cv2。waitKey(0) 4dog。py代码:importnumpyasnpimportmathdefderoGauss(w5,s1,angle0):wlim(w1)2y,xnp。meshgrid(np。arange(wlim,wlim1),np。arange(wlim,wlim1))Gnp。exp(np。sum((np。square(x),np。square(y)),axis0)(2np。float64(s)2))GGnp。sum(G)dGdxnp。multiply(x,G)np。float64(s)2dGdynp。multiply(y,G)np。float64(s)2angleanglemath。pi180dogmath。cos(angle)dGdxmath。sin(angle)dGdyreturndog 5bilateralfilt。py代码:importnumpyasnp双边滤波defbilatfilt(I,w,sd,sr):dimI。shapeIoutnp。zeros(dim)wlim(w1)2y,xnp。meshgrid(np。arange(wlim,wlim1),np。arange(wlim,wlim1))gnp。exp(np。sum((np。square(x),np。square(y)),axis0)(2(np。float64(sd)2)))Ipadnp。pad(I,(wlim,),edge)forrinrange(wlim,dim〔0〕wlim):forcinrange(wlim,dim〔1〕wlim):IxIpad〔rwlim:rwlim1,cwlim:cwlim1〕snp。exp(np。square(IxIpad〔r,c〕)(2(np。float64(sr)2)))knp。multiply(g,s)Iout〔rwlim,cwlim〕np。sum(np。multiply(k,Ix))np。sum(k)returnIout 6原图: 7效果图:本文第一个gif图,此处省略。 小结: 1本文由浅入深,总结的很好,适合收藏。 2对于理解python的opencv的canny的边缘检测,很有帮助。 3本文高级版canny自适应的算法参考2篇文章,虽然我进行代码的删除,注释,修改,优化等操作,故我不标注原创,对原作者表达敬意。 4自己总结和整理,分享出来,希望对大家有帮助。