本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的、不同方法的处理,以达到对图像进行去噪、锐化等一系列的操作。同时,希望观看本专栏的小伙伴可以理解到OpenCv进行图像处理的强大哦,如有转载,请注明出处(原文链接和作者署名),感谢各位小伙伴啦!

前文参考:
《OpenCv视觉之眼》Python图像处理一 :Opencv-python的简介及Python环境搭建
《OpenCv视觉之眼》Python图像处理二 :Opencv图像读取、显示、保存基本函数原型及使用
《OpenCv视觉之眼》Python图像处理三 :Opencv图像属性、ROI区域获取及通道处理
《OpenCv视觉之眼》Python图像处理四 :Opencv图像灰度处理的四种方法及原理
《OpenCv视觉之眼》Python图像处理五 :Opencv图像去噪处理之均值滤波、方框滤波、中值滤波和高斯滤波
《OpenCv视觉之眼》Python图像处理六 :Opencv图像傅里叶变换和傅里叶逆变换原理及实现
《OpenCv视觉之眼》Python图像处理七 :Opencv图像处理之高通滤波和低通滤波原理及构造
《OpenCv视觉之眼》Python图像处理八 :Opencv图像处理之图像阈值化处理原理及函数
《OpenCv视觉之眼》Python图像处理九 :Opencv图像形态学处理之图像腐蚀与膨胀原理及方法
《OpenCv视觉之眼》Python图像处理十 :Opencv图像形态学处理之开运算、闭运算和梯度运算原理及方法
《OpenCv视觉之眼》Python图像处理十一 :Opencv图像形态学处理之顶帽运算与黑帽运算
《OpenCv视觉之眼》Python图像处理十二 :Opencv图像轮廓提取之基于一阶导数的Roberts算法、Prewitt算法及Sobel算法
《OpenCv视觉之眼》Python图像处理十三 :Opencv图像轮廓提取之基于二阶导数的Laplacian算法和LOG算法

上次博客,我们介绍了基于二阶导数的轮廓提取算法Laplacian算法和LOG算法,包括各自的优点个缺点,并且自行构造了对应算法的功能函数,但在现实的图像处理中,这两张算法如果能够用到,那么用得较多的就是LOG算法,因此掌握LOG二阶导算法原理就可。

本次博客,林君学长将介绍在进行图像处理中用得最多也是效果较好的两种算法Scharr算法和Canny算法。Scharr算法是配合Sobel算法运算而存在的,可以理解为Sobel算法的升级版本,也就是说,如果你决定用Sobel算法,那请一定用Scharr算法代替你的想法;而Canny算法则是一个多级边缘检测算法,是用的最多的,是一种被广泛应用于边缘检测的标准算法。

本次博客讲解完,我们的图像处理的基本处理步骤就讲解完成,该系列接下来就将进入到对图像处理的项目实战之中去了,小伙伴们要准备好呀,前面还没有了解完全的请参考林君学长前面的博客抓紧学习哦!

Python图像处理十四 :Opencv图像轮廓提取之Scharr算法和Canny算法

  • 一、Scharr算法
    • 1、Scharr算法原理
    • 2、Scharr算法功能函数构造
    • 3、OpenCV中Scharr算法库函数使用
  • 二、Canny算法
    • 1、Canny算法原理
    • 2、Canny算法功能函数构造
    • 3、OpenCV中Canny算法库函数使用

一、Scharr算法

1、Scharr算法原理

1)、Scharr算法简介
Scharr算子又称为Scharr滤波器,也是计算x或y方向上的图像差分,在OpenCV中主要是配合Sobel算子的运算而存在的;scharr算子实际上是sobel算子的优化,scharr算子在处理边缘时比sobel精度高一些。两种算子唯一的区别就是他们的卷积核不同,他们无论在计算时间还是复杂度都是一样的。

由于Sobel算子在计算相对较小的核的时候,其近似计算导数的精度比较低,比如一个33的Sobel算子,当梯度角度接近水平或垂直方向时,其不精确性就越发明显。Scharr算子同Sobel算子的速度一样快,但是准确率更高,尤其是计算较小核的情景,所以利用33滤波器实现图像边缘提取更推荐使用Scharr算子。
2)、Scharr算法算法优缺点

  • 优点:Scharr算子同Sobel算子的速度一样快,但是准确率更高,尤其是计算较小核的情景、对灰度渐变和噪声较多的图像处理效果较好
  • 缺点:检测精度相比于Sobel算法有所提高,但不如Canny算法精度高

3)、Scharr算法计算原理
Scharr算法通过在3x3邻域内对x方向梯度和y方向梯度模板进行梯度差分求解得到结果,模板如下:
d x = [ − 3 0 3 − 10 0 10 − 3 0 3 ] , d y = [ − 3 − 10 − 3 0 0 0 3 10 3 ] dx=\begin{bmatrix} -3 & 0 & 3 \\ -10 & 0 & 10 \\-3 & 0 & 3 \end{bmatrix} , dy=\begin{bmatrix} -3 & -10 & -3 \\ 0 & 0 & 0 \\3 & 10 & 3 \end{bmatrix} dx=⎣⎡​−3−10−3​000​3103​⎦⎤​,dy=⎣⎡​−303​−10010​−303​⎦⎤​
通过对以上对于模板方向求解梯度差分,公式如下:
d x = ( 3 f [ i − 1 , j − 1 ] + 10 f [ i − 1 , j ] + 3 f [ i − 1 , j + 1 ] ) − ( 3 f [ i + 1 , j − 1 ] + 10 f [ i + 1 , j ] + 3 f [ i + 1 , j + 1 ] ) d y = ( 3 f [ i − 1 , j + 1 ] + 10 f [ i , j + 1 ] + 3 f [ i + 1 , j + 1 ] ) − ( 3 f [ i − 1 , j − 1 ] + 10 f [ i , j − 1 ] + 3 f [ i + 1 , j − 1 ] ) d x 、 d y 分 别 表 示 图 像 水 平 方 向 和 竖 直 方 向 的 计 算 出 的 像 素 值 图 像 轮 廓 S [ i , j ] = d x 2 + d y 2 d_x=(3f[i-1,j-1]+10f[i-1,j]+3f[i-1,j+1])-(3f[i+1,j-1]+10f[i+1,j]+3f[i+1,j+1])\\\\ d_y=(3f[i-1,j+1]+10f[i,j+1]+3f[i+1,j+1])-(3f[i-1,j-1]+10f[i,j-1]+3f[i+1,j-1])\\\\ d_x、d_y分别表示图像水平方向和竖直方向的计算出的像素值\\\\ 图像轮廓S[i,j]=\sqrt{d_x^2+d_y^2} dx​=(3f[i−1,j−1]+10f[i−1,j]+3f[i−1,j+1])−(3f[i+1,j−1]+10f[i+1,j]+3f[i+1,j+1])dy​=(3f[i−1,j+1]+10f[i,j+1]+3f[i+1,j+1])−(3f[i−1,j−1]+10f[i,j−1]+3f[i+1,j−1])dx​、dy​分别表示图像水平方向和竖直方向的计算出的像素值图像轮廓S[i,j]=dx2​+dy2​ ​
那么通过以上的计算公式原理,我们就可以自行构造Scharr算法的功能函数啦,如下步骤

2、Scharr算法功能函数构造

1)、Scharr算法功能函数构造

'''
Scharr算法轮廓提取函数构造
'''
#通过原理,编写对应的Roberts图像轮廓提取算法
def Scharr(thresh1):#获取图像属性h,w=thresh1.shape[0:2]#定义空白图像,用于存放LOG算法提取出来的轮廓图Scharr=np.zeros((h,w),dtype=thresh1.dtype)#对阈值化图像进行遍历,进行Laplacian算法for i in range(1,h-1):for j in range(1,w-1):#得到模板卷积第一个位置dx=(3*int(thresh1[i-1,j-1])+10*int(thresh1[i-1,j])+3*int(thresh1[i-1,j+1]))-(3*int(thresh1[i+1,j-1])+10*int(thresh1[i+1,j])+3*int(thresh1[i+1,j+1]))dy=(3*int(thresh1[i-1,j+1])+10*int(thresh1[i,j+1])+3*int(thresh1[i+1,j+1]))-(3*int(thresh1[i-1,j-1])+10*int(thresh1[i,j-1])+3*int(thresh1[i+1,j-1]))Scharr[i,j]=np.sqrt(dx**2+dy**2)return Scharr

2)、读取图像并处理,然后调用Scharr算法进行轮廓提取,如下:

import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
'''
一般来说,对图像轮廓提取都会经过如下步骤,灰度-滤波去噪-阈值化处理-(形态学处理,前面如果达标,这步骤可以省略)-轮廓提取
'''
#读取图像
img=cv2.imread("my.jpg")
#图像灰度化
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#图像高斯滤波去噪
blur=cv2.GaussianBlur(gray,(7,7),1,1)#核尺寸通过对图像的调节自行定义
#图像阈值化处理
ret,thresh1=cv2.threshold(blur,127,255,cv2.THRESH_BINARY)  #二进制阈值化
#调用Scharr算法函数进行图像轮廓提取
result=Scharr(thresh1)
#对原图进行格式转换,方便matplotlib图像显示
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
result=cv2.cvtColor(result,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Scharr算法']  #标题
images = [img, result]   #图像对比显示
for i in range(2):plt.subplot(1,2,i+1),plt.imshow(images[i])  plt.title(titles[i])    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

3、OpenCV中Scharr算法库函数使用

OpenCV官方给出了明确的Scharr算法的库函数,如下介绍
1)、函数原型:result=cv2.Scharr(img, ddepth, dx,dy)

  • img:需要轮廓提取的图像
  • ddepth:目标图深度
  • dx:dx方向上的差分阶数,取值1或 0
  • dy:y方向上的差分阶数,取值1或0

2)、Scharr算法库函数使用方法如下:

'''
Scharr轮廓提取算法-OpenCV库函数的使用方法
'''
import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
'''
一般来说,对图像轮廓提取都会经过如下步骤,灰度-滤波去噪-阈值化处理-(形态学处理,前面如果达标,这步骤可以省略)-轮廓提取
'''
#读取图像
img=cv2.imread("my.jpg")
#图像灰度化
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#图像高斯滤波去噪
blur=cv2.GaussianBlur(gray,(7,7),1,1)#核尺寸通过对图像的调节自行定义
#图像阈值化处理
ret,thresh1=cv2.threshold(blur,127,255,cv2.THRESH_BINARY)  #二进制阈值化
#调用Scharr算法的OpenCV库函数进行图像轮廓提取
x = cv2.Scharr(thresh1, cv2.CV_32F, 1, 0) #X方向
y = cv2.Scharr(thresh1, cv2.CV_32F, 0, 1) #Y方向
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Scharr = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
#对原图进行格式转换,方便matplotlib图像显示
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
Scharr=cv2.cvtColor(Scharr,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Scharr算法']  #标题
images = [img, Scharr]   #图像对比显示
for i in range(2):plt.subplot(1,2,i+1), plt.imshow(images[i])  plt.title(titles[i])    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像


二、Canny算法

1、Canny算法原理

1)、Canny算法简介
John F.Canny于1986年发明了一个多级边缘检测算法——Canny边缘检测算法,并创立了边缘检测计算理论(Computational theory of edge detection),该理论有效地解释了这项技术的工作理论。边缘检测通常是在保留原有图像属性的情况下,对图像数据规模进行缩减,提取图像边缘轮廓的处理方式。
Canny算法是一种被广泛应用于边缘检测的标准算法,其目标是找到一个最优的边缘检测解或找寻一幅图像中灰度强度变化最强的位置。最优边缘检测主要通过低错误率、高定位性和最小响应三个标准进行评价。
2)、Canny算法优缺点

  • 优点:不容易受噪声干扰,能够检测到真正的弱边缘;使用两种不同的阈值分别检测强边缘和弱边缘,并且当弱边缘和强边缘相连时,才将弱边缘包含在输出图像中;尽可能多地标识出图像中的实际边缘;标识出的边缘要与实际图像中的实际边缘尽可能接近。
  • 缺点:图像中的边缘只能标识一次,并且可能存在的图像噪声不应该标识为边缘。

3)、Canny算法构造原理
(1)、使用高斯平滑(如公式所示)去除噪声
K ( 5 , 5 ) = 1 / 273 [ 1 4 7 4 1 4 16 26 16 4 7 26 41 26 7 4 16 26 16 4 1 4 7 4 1 ] K(5,5)=1/273\begin{bmatrix} 1 & 4 & 7&4&1 \\ 4 & 16 & 26&16&4 \\7 & 26 & 41&26&7 \\4 & 16 & 26&16&4\\1 & 4 & 7&4&1\end{bmatrix} K(5,5)=1/273⎣⎢⎢⎢⎢⎡​14741​41626164​72641267​41626164​14741​⎦⎥⎥⎥⎥⎤​

(2)、按照Sobel滤波器步骤计算梯度幅值和方向,寻找图像的强度梯度。先将卷积模板分别作用x和y方向,再计算梯度幅值和方向,其公式如下所示。梯度方向一般取0度、45度、90度和135度四个方向
d x = [ 1 0 − 1 2 0 − 2 1 0 − 1 ] , d y = [ − 1 − 2 − 1 0 0 0 1 2 1 ] 图 像 轮 廓 边 缘 强 度 : S [ i , j ] = d x 2 + d y 2 边 缘 角 度 : t a n = a r c t a n ( d y / d x ) dx=\begin{bmatrix} 1 & 0 & -1 \\ 2 & 0 & -2 \\1 & 0 & -1 \end{bmatrix} , dy=\begin{bmatrix} -1 & -2 & -1 \\ 0 & 0 & 0 \\1 & 2 & 1 \end{bmatrix} \\\\ 图像轮廓边缘强度:S[i,j]=\sqrt{d_x^2+d_y^2}\\\\ 边缘角度:tan=arctan(dy/dx) dx=⎣⎡​121​000​−1−2−1​⎦⎤​,dy=⎣⎡​−101​−202​−101​⎦⎤​图像轮廓边缘强度:S[i,j]=dx2​+dy2​ ​边缘角度:tan=arctan(dy/dx)

(3)、通过非极大值抑制(Non-maximum Suppression)过滤掉非边缘像素,将模糊的边界变得清晰。该过程保留了每个像素点上梯度强度的极大值,过滤掉其他的值

  • 将其梯度方向近似为以下值中的一个,包括0、45、90、135、即表示x方向,y方向和正负对角线方向。

  • 比较该像素点和其梯度正负方向的像素点的梯度强度,如果该像素点梯度强度最大则保留,否则抑制(删除,即置为0)

    非极大值抑制算法:0°时取(x,y)、(x+1,y)、(x-1,y) 中的最大值与(x,y)比较,如(x,y)大,则保留像素值,如(x,y)小,则设置为0,其它角度类似


(4)、利用双阈值方法来确定潜在的边界。经过非极大抑制后图像中仍然有很多噪声点,此时需要通过双阈值技术处理,即设定一个阈值上界和阈值下界。图像中的像素点如果大于阈值上界则认为必然是边界(称为强边界,strong edge),小于阈值下界则认为必然不是边界,两者之间的则认为是候选项(称为弱边界,weak edge)

  • 如果梯度幅值S[i,j]大于高阈值的话,令S[i,j]=255
  • 如果梯度幅值S[i,j]小于低阈值的话,令S[i,j]=0


(5)、利用滞后技术来跟踪边界。若某一像素位置和强边界相连的弱边界认为是边界,其他的弱边界则被删除

  • 如果梯度幅值S[i,j]在高阈值和低阈值之间,并且周围8邻域内有比高阈值高的像素点存在,令S[i,j]=255,没有则令S[i,j]=0

那么对于Canny算法的功能函数构造也分为以上5个步骤,依次步骤进行处理,最后得到Canny算法边缘提取函数,如下步骤构造

2、Canny算法功能函数构造

1)、使用高斯平滑(如公式所示)去除噪声

 #获取图像属性h,w=gray.shape[0:2]# 定义存放高斯滤波处理后的图像gauss = np.zeros((h, w), dtype=gray.dtype)#定义高斯核卷积模板a=np.array([[1,4,7,4,1],[4,16,26,16,4],[7,26,41,26,7],[4,16,26,16,4],[1,4,7,4,1]])kernel=a*(1/273)'''使用高斯平滑(如公式所示)去除噪声'''#对图像遍历进行高斯滤波处理for i in range(2, h - 2):for j in range(2, w - 2):sum= np.sum(gray[i-2:i+2+1,j-2:j+2+1]*kernel)gauss[i, j]=sum

上面代码并没有进行黑边处理,正常情况下是需要处理的,如果小伙伴需要对图像进行黑边处理,请参考该系列博客教程前面讲解高斯滤波去噪的博客章节学习!
2)、按照Sobel滤波器步骤计算梯度幅值和方向

 '''按照Sobel滤波器步骤计算梯度幅值和方向,寻找图像的强度梯度'''Sobel=np.zeros((h,w),dtype=gray.dtype)#对阈值化图像进行遍历,进行Sobel梯度求解for i in range(h-1):for j in range(w-1):dx=(int(gauss[i-1,j-1])+2*int(gauss[i-1,j])+int(gauss[i-1,j+1]))-(int(gauss[i+1,j-1])+2*int(gauss[i+1,j])+int(gauss[i+1,j+1]))dy=(int(gauss[i-1,j+1])+2*int(gauss[i,j+1])+int(gauss[i+1,j+1]))-(int(gauss[i-1,j-1])+2*int(gauss[i,j-1])+int(gauss[i+1,j-1]))Sobel[i,j]=np.sqrt(dx**2+dy**2)

3)、通过非极大值抑制(Non-maximum Suppression)过滤掉非边缘像素,将模糊的边界变得清晰

 '''通过非极大值抑制(Non-maximum Suppression)过滤掉非边缘像素'''Suppression=np.zeros((h,w),dtype=gray.dtype)#对阈值化图像进行遍历,进行非极大值抑制for i in range(h-1):for j in range(w-1):dx=(int(gauss[i-1,j-1])+2*int(gauss[i-1,j])+int(gauss[i-1,j+1]))-(int(gauss[i+1,j-1])+2*int(gauss[i+1,j])+int(gauss[i+1,j+1]))dy=(int(gauss[i-1,j+1])+2*int(gauss[i,j+1])+int(gauss[i+1,j+1]))-(int(gauss[i-1,j-1])+2*int(gauss[i,j-1])+int(gauss[i+1,j-1]))#确保分母不是0dx = np.maximum(dx, 1e-10)seta=np.arctan(dy/dx)'''确定梯度角度'''if seta>-0.4142 and seta<0.4142:angle=0elif seta>0.4142 and seta<2.4142:angle=45elif abs(seta)>2.4142:angle=90elif seta>-2.4142 and seta<-0.4142:angle=135'''根据梯度角度方向,求得对应的非极大值抑制'''if angle==0:if max(Sobel[i,j],Sobel[i,j-1],Sobel[i,j+1])==Sobel[i,j]:#比较x方向梯度3个值中的最大值,如果Sobel[i,j]最大则保留,否则设置为0Suppression[i,j]=Sobel[i,j]else:Suppression[i,j]=0elif angle==45:if max(Sobel[i,j],Sobel[i-1,j+1],Sobel[i+1,j-1])==Sobel[i,j]:#比较正对角线方向梯度3个值中的最大值,如果Sobel[i,j]最大则保留,否则设置为0Suppression[i,j]=Sobel[i,j]else:Suppression[i,j]=0elif angle==90:if max(Sobel[i,j],Sobel[i-1,j],Sobel[i+1,j])==Sobel[i,j]:#比较y方向梯度3个值中的最大值,如果Sobel[i,j]最大则保留,否则设置为0Suppression[i,j]=Sobel[i,j]else:Suppression[i,j]=0elif angle==135:if max(Sobel[i,j],Sobel[i-1,j-1],Sobel[i+1,j+1])==Sobel[i,j]:#比较反对角线方向梯度3个值中的最大值,如果Sobel[i,j]最大则保留,否则设置为0Suppression[i,j]=Sobel[i,j]else:Suppression[i,j]=0

4)、利用双阈值方法来确定潜在的边界并利用滞后技术来跟踪边界

 '''利用双阈值方法来确定潜在的边界'''doubleThreshold=np.zeros((h,w),dtype=gray.dtype)#对阈值化图像进行遍历,进行双阈值处理for i in range(h):for j in range(w):if Suppression[i,j]>=maxT:#大于上阈值,则设置为255doubleThreshold[i,j]=255elif Suppression[i,j]<=minT:#小于下阈值,则设置为0doubleThreshold[i,j]=0else:'''利用滞后技术来跟踪边界。若某一像素位置和强边界相连的弱边界认为是边界,其他的弱边界则被删除'''#周围8邻域内有比该像素值大的像素,则设置为255,否则设置为0if max(Suppression[i-1,j-1],Suppression[i-1,j],Suppression[i-1,j+1],Suppression[i,j-1],Suppression[i,j+1],Suppression[i+1,j-1],Suppression[i+1,j+1])>=Suppression[i,j]:doubleThreshold[i,j]=255else:doubleThreshold[i,j]=0

5)、Canny算法功能函数构造完整代码

'''
Canny算法轮廓提取算法构造
'''
def Canny(gray,minT,maxT):#获取图像属性h,w=gray.shape[0:2]#定义空白图像,用于存放LOG算法提取出来的轮廓图Canny=np.zeros((h,w),dtype=gray.dtype)# 定义存放高斯滤波处理后的图像gauss = np.zeros((h, w), dtype=gray.dtype)#定义高斯核卷积模板a=np.array([[1,4,7,4,1],[4,16,26,16,4],[7,26,41,26,7],[4,16,26,16,4],[1,4,7,4,1]])kernel=a*(1/273)'''使用高斯平滑(如公式所示)去除噪声'''#对图像遍历进行高斯滤波处理for i in range(2, h - 2):for j in range(2, w - 2):sum= np.sum(gray[i-2:i+2+1,j-2:j+2+1]*kernel)gauss[i, j]=sum'''按照Sobel滤波器步骤计算梯度幅值和方向,寻找图像的强度梯度'''Sobel=np.zeros((h,w),dtype=gray.dtype)#对阈值化图像进行遍历,进行Sobel求解梯度值for i in range(h-1):for j in range(w-1):dx=(int(gauss[i-1,j-1])+2*int(gauss[i-1,j])+int(gauss[i-1,j+1]))-(int(gauss[i+1,j-1])+2*int(gauss[i+1,j])+int(gauss[i+1,j+1]))dy=(int(gauss[i-1,j+1])+2*int(gauss[i,j+1])+int(gauss[i+1,j+1]))-(int(gauss[i-1,j-1])+2*int(gauss[i,j-1])+int(gauss[i+1,j-1]))Sobel[i,j]=np.sqrt(dx**2+dy**2)'''通过非极大值抑制(Non-maximum Suppression)过滤掉非边缘像素'''Suppression=np.zeros((h,w),dtype=gray.dtype)#对阈值化图像进行遍历,进行非极大值抑制for i in range(h-1):for j in range(w-1):dx=(int(gauss[i-1,j-1])+2*int(gauss[i-1,j])+int(gauss[i-1,j+1]))-(int(gauss[i+1,j-1])+2*int(gauss[i+1,j])+int(gauss[i+1,j+1]))dy=(int(gauss[i-1,j+1])+2*int(gauss[i,j+1])+int(gauss[i+1,j+1]))-(int(gauss[i-1,j-1])+2*int(gauss[i,j-1])+int(gauss[i+1,j-1]))#确保分母不是0dx = np.maximum(dx, 1e-10)seta=np.arctan(dy/dx)'''确定梯度角度'''if seta>-0.4142 and seta<0.4142:angle=0elif seta>0.4142 and seta<2.4142:angle=45elif abs(seta)>2.4142:angle=90elif seta>-2.4142 and seta<-0.4142:angle=135'''根据梯度角度方向,求得对应的非极大值抑制'''if angle==0:if max(Sobel[i,j],Sobel[i,j-1],Sobel[i,j+1])==Sobel[i,j]:#比较x方向梯度3个值中的最大值,如果Sobel[i,j]最大则保留,否则设置为0Suppression[i,j]=Sobel[i,j]else:Suppression[i,j]=0elif angle==45:if max(Sobel[i,j],Sobel[i-1,j+1],Sobel[i+1,j-1])==Sobel[i,j]:#比较正对角线方向梯度3个值中的最大值,如果Sobel[i,j]最大则保留,否则设置为0Suppression[i,j]=Sobel[i,j]else:Suppression[i,j]=0elif angle==90:if max(Sobel[i,j],Sobel[i-1,j],Sobel[i+1,j])==Sobel[i,j]:#比较y方向梯度3个值中的最大值,如果Sobel[i,j]最大则保留,否则设置为0Suppression[i,j]=Sobel[i,j]else:Suppression[i,j]=0elif angle==135:if max(Sobel[i,j],Sobel[i-1,j-1],Sobel[i+1,j+1])==Sobel[i,j]:#比较反对角线方向梯度3个值中的最大值,如果Sobel[i,j]最大则保留,否则设置为0Suppression[i,j]=Sobel[i,j]else:Suppression[i,j]=0'''利用双阈值方法来确定潜在的边界'''doubleThreshold=np.zeros((h,w),dtype=gray.dtype)#对阈值化图像进行遍历,进行双阈值处理for i in range(h):for j in range(w):if Suppression[i,j]>=maxT:#大于上阈值,则设置为255doubleThreshold[i,j]=255elif Suppression[i,j]<=minT:#小于下阈值,则设置为0doubleThreshold[i,j]=0else:'''利用滞后技术来跟踪边界。若某一像素位置和强边界相连的弱边界认为是边界,其他的弱边界则被删除'''#周围8邻域内有比该像素值大的像素,则设置为255,否则设置为0if max(Suppression[i-1,j-1],Suppression[i-1,j],Suppression[i-1,j+1],Suppression[i,j-1],Suppression[i,j+1],Suppression[i+1,j-1],Suppression[i+1,j+1])>=Suppression[i,j]:doubleThreshold[i,j]=255else:doubleThreshold[i,j]=0return doubleThreshold

6)、读取图像,调用Canny算法函数进行边缘提取并显示处理结果

import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
#读取图像
img=cv2.imread("my.jpg")
#图像灰度化
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#调用Canny算法函数
Canny= Canny(gray,50,150) #这里不需要阈值化处理,因为Canny算法自带阈值化处理
#对原图进行格式转换,方便matplotlib图像显示
img1=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
Canny=cv2.cvtColor(Canny,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Canny算法']  #标题
images = [img1, Canny]   #图像对比显示
for i in range(2):plt.subplot(1,2,i+1), plt.imshow(images[i])  plt.title(titles[i])    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像

3、OpenCV中Canny算法库函数使用

在OpenCV中,Canny()库函数原型如下介绍
1)、函数原型:Canny = cv2.Canny(img, threshold1, threshold2,apertureSize)

  • img:需要轮廓图提取的图像
  • threshold1:第一个滞后性阈值
  • threshold2:第二个滞后性阈值
  • apertureSize:Sobel算法的孔径大小,其默认值为3

2)、Canny()库函数使用如下:

'''
Canny算法轮廓提取算法-OpenCV库函数的使用方法
'''
import cv2
import numpy as np
#np.set_printoptions(threshold=np.inf)  #打印数组中的全部内容
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei'] #显示中文
'''
一般来说,对图像轮廓提取都会经过如下步骤,灰度-滤波去噪-阈值化处理-(形态学处理,前面如果达标,这步骤可以省略)-轮廓提取
'''
#读取图像
img=cv2.imread("my.jpg")
#图像灰度化
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#图像高斯滤波去噪
blur=cv2.GaussianBlur(gray,(7,7),1,1)#核尺寸通过对图像的调节自行定义
Canny = cv2.Canny(blur, 50, 150) #这里不需要阈值化处理,因为Canny算法自带阈值化处理
#对原图进行格式转换,方便matplotlib图像显示
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
Canny=cv2.cvtColor(Canny,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Canny算法-OpenCV']  #标题
images = [img, Canny]   #图像对比显示
for i in range(2):plt.subplot(1,2,i+1), plt.imshow(images[i])  plt.title(titles[i])    plt.axis('off')#关闭坐标轴  设置为on则表示开启坐标轴
plt.show()#显示图像


从上面可以看出,Canny算法提取出的物体轮廓的效果是非常好的不仅明显,而且提取的边缘线比较细,这就是Canny算法被广泛应用于图像轮廓提取的原因,这是被作为边缘检测的标准算法的原因!

以上就是本次博客的全部内容,图像处理的基本步骤到这里也就完结了,接下来该系列的博客主要讲解通过前面对图像处理的基本步骤,进行项目实战、包括图像中某物体的检测、图像美化处理、硬币检测、人脸检测、直线检测、圆脸检测等等,本次博客内容到此结束,遇到问题的小伙伴记得留言评论,学长看到会为大家进行解答的,这个学长不太冷!

善待自己,不被别人左右,也不去左右别人,自信优雅。如果做一粒尘埃,就用飞舞诠释生命的内涵;如果是一滴雨,就倾尽温柔滋润大地。人生多磨难,要为自己鼓掌,别让犹豫阻滞了脚步,别让忧伤苍白了心灵。

陈一月的又一天编程岁月^ _ ^

《OpenCv视觉之眼》Python图像处理十四 :Opencv图像轮廓提取之Scharr算法和Canny算法相关推荐

  1. 《OpenCv视觉之眼》Python图像处理十九:Opencv图像处理实战四之通过OpenCV进行人脸口罩模型训练并进行口罩检测

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  2. 《OpenCv视觉之眼》Python图像处理十六:Opencv图像处理实战一之图像中的硬币检测

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  3. 《OpenCv视觉之眼》Python图像处理十二 :Opencv图像轮廓提取之基于一阶导数的Roberts算法、Prewitt算法及Sobel算法

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  4. [Python图像处理] 十四.基于OpenCV和像素处理的图像灰度化处理

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  5. [Python图像处理] 十.形态学之图像顶帽运算和黑帽运算

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  6. python 函数修饰器 父类_手把手教你学python第十四讲(函数装饰器,super用法和时间处理)...

    文中有些字在图中是因为每篇文章最多100张图片,我把有的小图片和文字一起截图了,文中所有的引用都会标出原文网址,除此以外都是作者原创. 有时候会在文章最前或者最后补充一些知识或者把前面说的有问题的地方 ...

  7. 《OpenCv视觉之眼》Python图像处理二十三:OpenCV图像处理最终章之基于PyQt5的图像处理界面设计及功能实现

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  8. 《OpenCv视觉之眼》Python图像处理二十一:Opencv图像处理之图像线性变换和非线性变换的方法及原理

    本专栏主要介绍如果通过OpenCv-Python进行图像处理,通过原理理解OpenCv-Python的函数处理原型,在具体情况中,针对不同的图像进行不同等级的.不同方法的处理,以达到对图像进行去噪.锐 ...

  9. python灰度图片格式_[Python图像处理] 十五.图像的灰度线性变换

    [Python图像处理] 十五.图像的灰度线性变换 发布时间:2019-03-28 00:08, 浏览次数:619 , 标签: Python 该系列文章是讲解Python OpenCV图像处理知识,前 ...

最新文章

  1. 端产品多版本共存服务器端兼容的问题
  2. html5在li中添加按钮,如何在html5blank_nav()中的ul和li中添加类?
  3. 积木赛尔号机器人_《赛尔号大电影7》定档2019年暑期 十年陪伴升级归来
  4. 程序员修神之路--redis做分布式锁可能不那么简单
  5. 一文讲透Dubbo负载均衡之最小活跃数算法
  6. iOS 九宫格手势密码
  7. Python多线程编程中daemon属性的作用
  8. TrustBase团队完成subscript语言的Web3基金会Grant资助计划项目交付
  9. 使用 esxtop 识别存储性能问题
  10. BZOJ.1312.[Neerc2006]Hard Life(分数规划 最大权闭合子图)
  11. Ubuntu IP系统配置文件使用命令设置地址
  12. 雨果奖首设游戏奖项,Hades拿下科幻界的诺贝尔奖
  13. 大数据分析及工具应用总结
  14. 基于Matlab的IMM雷达多目标跟踪
  15. hbuilderx运行支付宝小程序
  16. 【Tcl学习笔记】第1章 Tcl和Tk概览-hello world!
  17. 面试官:RecyclerView布局动画原理了解吗?
  18. 【论文笔记】《基于深度学习的中文命名实体识别研究》阅读笔记
  19. 软件测试用例 单元测试,软件单元测试的测试用例编写方法
  20. 解决servlet请求转发、响应重定向无法实现页面跳转问题

热门文章

  1. java list定义和初始化_在 Java 中初始化 List 的五种方法
  2. 338页网易Java面试真题解析火爆全网,讲的明明白白!
  3. nonlinear systems 学习笔记
  4. 阿里云code上添加ssh key
  5. SELECT 语句 (七部分)
  6. 计算机网络应用基础实验指导,计算机及网络应用基础实验指导书.PDF
  7. 【C语言】求绝对值abs
  8. 乘用车变速器GB/T 28046.3测试多少钱?GB/T 28046.3振动测试
  9. R语言xcms处理质谱数据
  10. 中关村颠覆性技术创新项目资助政策及申报条件重点介绍,补贴500万