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

本专栏主要介绍如果通过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图像形态学处理之顶帽运算与黑帽运算

上次博客,我们介绍了图像形态学处理的最后一个章节,图像形态学黑帽与顶帽运算,到这里,图像形态学处理我们就暂告一个段落,而对于形态学的黑帽与顶帽运算,大家作为一个科普了解一下,因为针对一般图像而言,我们不会用到。

本次博客,我们将进行图像处理的下一个阶段的学习——图像轮廓提取;对于图像轮廓提取,是图像处理中的一个重要阶段,而对于图像轮廓提取也有很多的算法,本次博客主要讲解图像轮廓提取的Roberts算法、Prewitt算法、以及常用的Sobel算法,分析各种算法的优势和缺点,通过原理,自己编写对应的函数实现对该种算法的功能函数编写,一起来看吧!

图像轮廓提取(边缘提取)技术可以消除图像中的噪声,提取图像信息中用来表征图像的一些变量,为图像识别提供基础。通常使用灰度差分法对图像的边缘、轮廓进行处理,将其凸显。本次博客分别采用Robert算子、Prewitt算子和Sobel算子进行图像锐化边缘处理,了解原理是关键哦!

一、Roberts算法

1、Roberts算法原理

1)、Roberts算法简介
Roberts算法又称为交叉微分算法,它是基于交叉差分的梯度算法,通过局部差分计算检测边缘线条。常用来处理具有陡峭的低噪声图像,当图像边缘接近于正45度或负45度时,该算法处理效果更理想。
Roberts算子的模板分为水平方向和垂直方向,如下所示:
d x = [ − 1 0 0 1 ] , d y = [ 0 − 1 1 0 ] dx=\begin{bmatrix} -1 & 0 \\ 0 & 1 \\ \end{bmatrix} , dy=\begin{bmatrix} 0 & -1 \\ 1 & 0 \\ \end{bmatrix} dx=[1001],dy=[0110]
从其模板可以看出,Roberts算子能较好的增强正负45度的图像边缘。

2)、Roberts算法优缺点

  • 优点:Roberts算子能较好的增强正负45度的图像边缘
  • 缺点:对边缘的定位不太准确,提取的边缘线条较粗。

3)、Roberts算法计算原理
d x = f ( i + 1 , j + 1 ) − f ( i , j ) d y = f ( i , j + 1 ) − f ( i + 1 , j ) S = d x 2 + d y 2 d_x=f(i+1,j+1)-f(i,j)\\\\ d_y=f(i,j+1)-f(i+1,j)\\\\ S=\sqrt{d_x^2+d_y^2} dx=f(i+1,j+1)f(i,j)dy=f(i,j+1)f(i+1,j)S=dx2+dy2
以上计算原理就是我们自己构造Roberts算法原理功能函数的基础,通过以上计算原理,那么如何将计算公式与图像结合呢?如下所示:
d x = i m g [ i + 1 , j + 1 ] − i m g [ i , j ] d y = i m g [ i , j + 1 ] − i m g [ i + 1 , j ] d x 、 d y 分 别 表 示 图 像 水 平 方 向 和 竖 直 方 向 的 计 算 出 的 像 素 值 图 像 轮 廓 S [ i , j ] = d x 2 + d y 2 d_x=img[i+1,j+1]-img[i,j]\\\\ d_y=img[i,j+1]-img[i+1,j]\\\\ d_x、d_y分别表示图像水平方向和竖直方向的计算出的像素值\\\\ 图像轮廓S[i,j]=\sqrt{d_x^2+d_y^2} dx=img[i+1,j+1]img[i,j]dy=img[i,j+1]img[i+1,j]dxdyS[i,j]=dx2+dy2
在对公式转换为图像处理的公式之后,我们就可以构造Roberts算法的功能函数了

2、Roberts算法构造

1)、Roberts算法功能构造

'''
Roberts轮廓提取算法
'''
#通过原理,编写对应的Roberts图像轮廓提取算法
def Roberts(thresh1):
    #获取图像属性
    h,w=thresh1.shape[0:2]
    #定义空白图像,用于存放Roberts算法提取出来的轮廓图
    Roberts=np.zeros((h,w),dtype=thresh1.dtype)
    #对阈值化图像进行遍历,进行Roberts算法
    for i in range(h-1):
        for j in range(w-1):
            dx=int(thresh1[i+1,j+1])-int(thresh1[i,j])#水平方向计算公式
            dy=int(thresh1[i,j+1])-int(thresh1[i+1,j])#竖直方向计算公式
            Roberts[i,j]=np.sqrt(dx**2+dy**2)#水平方向与竖直方向结合和最终像素
    return Roberts

以上就是对Roberts算法函数的编写,通过传递阈值化后的图像进行轮廓提取,为什么要阈值化,因为这是图像轮廓提取的一般步骤

一般来说,对图像轮廓提取都会经过如下步骤,灰度-滤波去噪-阈值化处理-(形态学处理,前面如果达标,这步骤可以省略)-轮廓提取

2)、读取图像进行对于处理,然后调用Roberts算法功能函数进行轮廓提取

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)  #二进制阈值化
#调用Roberts算法函数进行图像轮廓提取
result=Roberts(thresh1)
#对原图进行格式转换,方便matplotlib图像显示
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
result=cv2.cvtColor(result,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Roberts算法']  #标题
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()#显示图像

在这里插入图片描述

从上面可以看出,Roberts算法提取出来的轮廓图像轮廓边缘的线条是比较粗的,但大致轮廓却完美提取出来,但对于细节处理,由于边缘线较粗,会遮盖细节处,这个通过后面几种算法的对比可以看出来的!

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

在OpenCV官方的库中,也提供了Roberts算法库函数,调用OpenCV的filter2D()函数实现边缘提取。该函数主要是利用内核实现对图像的卷积运算,然后通过addWeighted()函数来进行x方向与y方向上的结合
1)、filter2D()函数原型:result=cv2.filter2D(thresh1, cv2.CV_16S, kernel)

  • thresh1:需要进行轮廓提取的图像
  • cv2.CV_16S:目标图深度
  • kernelx:卷积核,一个单通道浮点型矩阵

2)、addWeighted()函数原型:result=cv2.addWeighted(absX,alphax,absY, alphay,num)

  • absX:方向的处理结果
  • alphax:X方向上的权重
  • absY:Y方向的处理结果
  • alphay:Y方向上的权重
  • num:X与Y方向上求和后添加的偏移量,不能设置太大,否则容易溢出(总和超过255就算溢出)

3)、Roberts算法库函数的使用方法

'''
Roberts轮廓提取算法-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)  #二进制阈值化
#调用Roberts算法的OpenCV库函数进行图像轮廓提取
kernelx = np.array([[-1,0],[0,1]], dtype=int)
kernely = np.array([[0,-1],[1,0]], dtype=int)
x = cv2.filter2D(thresh1, cv2.CV_16S, kernelx)
y = cv2.filter2D(thresh1, cv2.CV_16S, kernely)
#转uint8 
absX = cv2.convertScaleAbs(x)      
absY = cv2.convertScaleAbs(y)    
Roberts = cv2.addWeighted(absX,0.5,absY,0.5,0)
#对原图进行格式转换,方便matplotlib图像显示
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
Roberts=cv2.cvtColor(Roberts,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Roberts算法']  #标题
images = [img, Roberts]   #图像对比显示
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()#显示图像

在这里插入图片描述

二、Prewitt算法

1、Prewitt算法原理

1)、Prewitt算法简介
Prewitt算子是一种一阶微分算子的边缘检测,利用像素点上下、左右邻点的灰度差,在边缘处达到极值检测边缘,去掉部分伪边缘,对噪声具有平滑作用 。其原理是在图像空间利用两个方向模板与图像进行邻域卷积来完成的,这两个方向模板一个检测水平边缘,一个检测垂直边缘。Prewitt算法适合用来识别噪声较多、灰度渐变的图像;水平和竖直方向上的卷积模板如下所示:
d x = [ 1 0 − 1 1 0 − 1 1 0 − 1 ] , d y = [ − 1 − 1 − 1 0 0 0 1 1 1 ] dx=\begin{bmatrix} 1 & 0 & -1 \\ 1 & 0 & -1 \\1 & 0 & -1 \end{bmatrix} , dy=\begin{bmatrix} -1 & -1 & -1 \\ 0 & 0 & 0 \\1 & 1 & 1 \end{bmatrix} dx=111000111,dy=101101101
2)、Prewitt算法优缺点

  • 优点:Prewitt算子的边缘检测结果在水平方向和垂直方向均比Robert算子更加明显
  • 缺点:凡灰度新值大于或等于阈值的像素点都是边缘点。即选择适当的阈值T,若P(i,j)≥T,则(i,j)为边缘点,P(i,j)为边缘图像。这种判定是欠合理的,会造成边缘点的误判,因为许多噪声点的灰度值也很大,而且对于幅值较小的边缘点,其边缘反而丢失了。

3)、Prewitt算法计算原理
d x = ( f [ i − 1 , j − 1 ] + f [ i − 1 , j ] + f [ i − 1 , j + 1 ] ) − ( f [ i + 1 , j − 1 ] + f [ i + 1 , j ] + f [ i + 1 , j + 1 ] ) d y = ( [ ( i − 1 , j + 1 ] + f [ i , j + 1 ] + f [ i + 1 , j + 1 ] ) − ( f [ i − 1 , j − 1 ] + f [ i , j − 1 ] + f [ i + 1 , j − 1 ] ) d x 、 d y 分 别 表 示 图 像 水 平 方 向 和 竖 直 方 向 的 计 算 出 的 像 素 值 图 像 轮 廓 S [ i , j ] = d x 2 + d y 2 d_x=(f[i-1,j-1]+f[i-1,j]+f[i-1,j+1])-(f[i+1,j-1]+f[i+1,j]+f[i+1,j+1])\\\\ d_y=([(i-1,j+1]+f[i,j+1]+f[i+1,j+1])-(f[i-1,j-1]+f[i,j-1]+f[i+1,j-1])\\\\ d_x、d_y分别表示图像水平方向和竖直方向的计算出的像素值\\\\ 图像轮廓S[i,j]=\sqrt{d_x^2+d_y^2} dx=(f[i1,j1]+f[i1,j]+f[i1j+1])(f[i+1,j1]+f[i+1j]+f[i+1j+1])dy=([(i1,j+1]+f[i,j+1]+f[i+1j+1])(f[i1,j1]+f[i,j1]+f[i+1j1])dxdyS[i,j]=dx2+dy2
通过以上的计算公式,我们就可以进行Prewitt算法功能函数的构造了,继续往下看吧!

2、Prewitt算法构造

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

'''
Prewitt轮廓提取算法
'''
#通过原理,编写对应的Roberts图像轮廓提取算法
def Prewitt(thresh1):
    #获取图像属性
    h,w=thresh1.shape[0:2]
    #定义空白图像,用于存放Prewitt算法提取出来的轮廓图
    Prewitt=np.zeros((h,w),dtype=thresh1.dtype)
    #对阈值化图像进行遍历,进行Roberts算法
    for i in range(h-1):
        for j in range(w-1):
            dx=(int(thresh1[i-1,j-1])+int(thresh1[i-1,j])+int(thresh1[i-1,j+1]))-(int(thresh1[i+1,j-1])+int(thresh1[i+1,j])+int(thresh1[i+1,j+1]))
            dy=(int(thresh1[i-1,j+1])+int(thresh1[i,j+1])+int(thresh1[i+1,j+1]))-(int(thresh1[i-1,j-1])+int(thresh1[i,j-1])+int(thresh1[i+1,j-1]))
            Prewitt[i,j]=np.sqrt(dx**2+dy**2)
    return Prewitt

2)、读取图像处理,然后调用Prewitt功能函数进行轮廓提取

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)  #二进制阈值化
#调用Prewitt算法函数进行图像轮廓提取
result=Prewitt(thresh1)
#对原图进行格式转换,方便matplotlib图像显示
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
result=cv2.cvtColor(result,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Prewitt算法']  #标题
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()#显示图像

在这里插入图片描述

通过这里可以看出,在对同一张图像进过相同处理之后,通过Prewitt算法提取的图像比通过Roberts算法算法提取的图像更加明显,但也将更多噪声误判为边缘点,这对图像轮廓提取是有一定影响的,这也是Prewitt算法的缺点

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

同样的,OpenCV官方同样对Prewitt算法有对于的库函数,与Roberts算法算法的库函数一样,只是传递的卷积核不一样,有变化;通过Numpy定义模板,再调用OpenCV的filter2D()函数实现对图像的卷积运算,最终通过convertScaleAbs()和addWeighted()函数实现边缘提取,函数原型参考Roberts算法介绍的函数原型,是一样的!
1)、Prewitt算发库函数使用方法

'''
Prewitt轮廓提取算法-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)  #二进制阈值化
#调用Prewitt算法的OpenCV库函数进行图像轮廓提取
kernelx = np.array([[1,1,1],[0,0,0],[-1,-1,-1]],dtype=int)
kernely = np.array([[-1,0,1],[-1,0,1],[-1,0,1]],dtype=int)
x = cv2.filter2D(thresh1, cv2.CV_16S, kernelx)
y = cv2.filter2D(thresh1, cv2.CV_16S, kernely)
#转uint8 
absX = cv2.convertScaleAbs(x)      
absY = cv2.convertScaleAbs(y)    
Prewitt= cv2.addWeighted(absX,0.5,absY,0.5,0)
#对原图进行格式转换,方便matplotlib图像显示
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
Prewitt=cv2.cvtColor(Prewitt,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Prewitt算法']  #标题
images = [img, Prewitt]   #图像对比显示
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()#显示图像

在这里插入图片描述

三、Sobel算法

1、Sobel算法原理

1)、Sobel算法简介
Sobel算法(索贝尔算子)是一种用于边缘检测的离散微分算子,它结合了高斯平滑和微分求导。该算子用于计算图像明暗程度近似值,根据图像边缘旁边明暗程度把该区域内超过某个数的特定点记为边缘。Sobel算子在Prewitt算子的基础上增加了权重的概念,认为相邻点的距离远近对当前像素点的影响是不同的,距离越近的像素点对应当前像素的影响越大,从而实现图像锐化并突出边缘轮廓。当对精度要求不是很高时,Sobel算子是一种较为常用的边缘检测方法,其卷积模板如下所示:
d x = [ 1 0 − 1 2 0 − 2 1 0 − 1 ] , d y = [ − 1 − 2 − 1 0 0 0 1 2 1 ] 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} dx=121000121,dy=101202101
2)、Sobel算法优缺点

  • 优点:Sobel算子的边缘定位更准确,会具有更多的抗噪性,不但产生较好的检测效果,而且对噪声具有平滑抑制作用;方法简单、处理速度快,并且所得的边缘光滑、连续
  • 缺点:得到的边缘较粗,且可能出现伪边缘

3)、Sobel算法计算原理
d x = ( f [ i − 1 , j − 1 ] + 2 f [ i − 1 , j ] + f [ i − 1 , j + 1 ] ) − ( f [ i + 1 , j − 1 ] + 2 f [ i + 1 , j ] + f [ i + 1 , j + 1 ] ) d y = ( f [ i − 1 , j + 1 ] + 2 f [ i , j + 1 ] + f [ i + 1 , j + 1 ] ) − ( f [ i − 1 , j − 1 ] + 2 f [ i , j − 1 ] + f [ i + 1 , j − 1 ] ) d x 、 d y 分 别 表 示 图 像 水 平 方 向 和 竖 直 方 向 的 计 算 出 的 像 素 值 图 像 轮 廓 S [ i , j ] = d x 2 + d y 2 d_x=(f[i-1,j-1]+2f[i-1,j]+f[i-1,j+1])-(f[i+1,j-1]+2f[i+1,j]+f[i+1,j+1])\\\\ d_y=(f[i-1,j+1]+2f[i,j+1]+f[i+1,j+1])-(f[i-1,j-1]+2f[i,j-1]+f[i+1,j-1])\\\\ d_x、d_y分别表示图像水平方向和竖直方向的计算出的像素值\\\\ 图像轮廓S[i,j]=\sqrt{d_x^2+d_y^2} dx=(f[i1,j1]+2f[i1,j]+f[i1j+1])(f[i+1,j1]+2f[i+1j]+f[i+1j+1])dy=(f[i1,j+1]+2f[i,j+1]+f[i+1j+1])(f[i1,j1]+2f[i,j1]+f[i+1j1])dxdyS[i,j]=dx2+dy2

2、Sobel算法构造

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

'''
Sobel轮廓提取算法
'''
#通过原理,编写对应的Roberts图像轮廓提取算法
def Sobel(thresh1):
    #获取图像属性
    h,w=thresh1.shape[0:2]
    #定义空白图像,用于存放Roberts算法提取出来的轮廓图
    Sobel=np.zeros((h,w),dtype=thresh1.dtype)
    #对阈值化图像进行遍历,进行Roberts算法
    for i in range(h-1):
        for j in range(w-1):
            dx=(int(thresh1[i-1,j-1])+2*int(thresh1[i-1,j])+int(thresh1[i-1,j+1]))-(int(thresh1[i+1,j-1])+2*int(thresh1[i+1,j])+int(thresh1[i+1,j+1]))
            dy=(int(thresh1[i-1,j+1])+2*int(thresh1[i,j+1])+int(thresh1[i+1,j+1]))-(int(thresh1[i-1,j-1])+2*int(thresh1[i,j-1])+int(thresh1[i+1,j-1]))
            Sobel[i,j]=np.sqrt(dx**2+dy**2)
    return Sobel

2)、读取图像并处理,调用Sobel算法进行图像轮廓提取

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)  #二进制阈值化
#调用Sobel算法函数进行图像轮廓提取
result=Sobel(thresh1)
#对原图进行格式转换,方便matplotlib图像显示
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
result=cv2.cvtColor(result,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Sobel算法']  #标题
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()#显示图像

在这里插入图片描述
Sobel算子根据像素点上下、左右邻点灰度加权差,在边缘处达到极值这一现象检测边缘。对噪声具有平滑作用,提供较为精确的边缘方向信息。因为Sobel算子结合了高斯平滑和微分求导(分化),因此结果会具有更多的抗噪性,当对精度要求不是很高时,Sobel算子是一种较为常用的边缘检测方法。

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

OpenCV中提供了专门的Soble算法的库函数,如下介绍
1)、函数原型:result=cv2.Sobel(img, ddepth, dx,dy,ksize)

  • img:需要轮廓提取的图像
  • ddepth:目标图像深度
  • dx:x方向上的差分阶数,取值1或 0
  • dy:y方向上的差分阶数,取值1或0
  • ksize:Sobel算子的大小,其值必须是正数和奇数

在进行Sobel算子处理之后,还需要调用convertScaleAbs()函数计算绝对值
2)、convertScaleAbs()函数原型:x=cv2.convertScaleAbs(x)

  • x:x或者y方向上的Sobel算法值

3)、OpenCV中Sobel算法库函数使用

'''
Sobel轮廓提取算法-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)  #二进制阈值化
#调用Sobel算法的OpenCV库函数进行图像轮廓提取
x = cv2.Sobel(thresh1, cv2.CV_16S, 1, 0) #对x求一阶导
y = cv2.Sobel(thresh1, cv2.CV_16S, 0, 1) #对y求一阶导
absX = cv2.convertScaleAbs(x)  #对x取绝对值,并将图像转换为8位图   
absY = cv2.convertScaleAbs(y)   #对y取绝对值,并将图像转换为8位图
Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
#对原图进行格式转换,方便matplotlib图像显示
img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#对结果图进行格式转换,方便matplotlib图像显示
Sobel=cv2.cvtColor(Sobel,cv2.COLOR_BGR2RGB)
#图像显示
titles = ['原图', 'Sobel算法']  #标题
images = [img, Sobel]   #图像对比显示
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()#显示图像

在这里插入图片描述
可以看出,Sobel算法的边缘定位更准确,相比于之前的Roberts算法和Prewitt算法,Sobel算法对边缘更加明显,抗噪能力强!

边缘检测算法主要是基于图像强度的一阶和二阶导数,但导数通常对噪声很敏感,因此需要采用滤波器来过滤噪声,并调用图像增强或阈值化算法进行处理,最后再进行边缘检测。

以上就是本次博客的全部内容,遇到问题的小伙伴记得留言评论,学长看到会为大家进行解答的,这个学长不太冷!

十二星座的光芒从不停歇,它们穿梭过你的生命,你永远在它们的共同辉映下,原本你以为你属于其中之一,其实这一生,你都在缓缓经历着所有星辰的痕迹,有深有浅,却不偏不倚。只是它们出现在你生命的不同阶段而已——十二星座的爱情

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

编辑推荐  Sedgewick之巨著,与高德纳TAOCP一脉相承  几十年多次修订,经久不衰的畅销书  涵盖所有程序员必须掌握的50种算法 内容简介    《算法(第4版)》全面讲述算法和数据结构的必备知识,具有以下几大特色。    1、 算法领域的经典参考书:Sedgewick畅销著作的*版,反映了经过几十年演化而成的算法核心知识体系    2、内容全面:全面论述排序、搜索、图处理和字符串处理的算法和数据结构,涵盖每位程序员应知应会的50种算法    3、全新修订的代码:全新的Java实现代码,采用模块化的编程风格,所有代码均可供读者使用    4、与实际应用相结合:在重要的科学、工程和商业应用环境下探讨算法,给出了算法的实际代码,而非同类著作常用的伪代码   5、富于智力趣味性:简明扼要的内容,用丰富的视觉元素展示的示例,精心设计的代码,详尽的历史和科学背景知识,各种难度的练习,这一切都将使读者手不释卷    6、科学的方法:用合适的数学模型精确地讨论算法性能,这些模型是在真实环境中得到验证的   7、与网络相结合:配套网站algs4.cs.princeton.edu提供了本书内容的摘要及相关的代码、测试数据、编程练习、教学课件等资源 作者简介    Robert Sedgewick,斯坦福大学博士,导师为Donald E.Knuth,从1985年开始一直担任普林斯顿大学计算机科学系教授,曾任该系主任,也是AdobeSystems公司董事会成员,曾在Xerox PARC、国防分析研究所(Institute for DefenseAnalyses)和法国国家信息与自动化研究所(INRIA)从事研究工作。他的研究方向包括解析组合学、数据结构和算法的分析与设计、程序可视化等。    KevinWayne,康奈尔大学博士,普林斯顿大学计算机科学系高级讲师,研究方向包括算法的设计、分析和实现,特别是图和离散优化。 目  录 第1章  基础 1.1 基础编程模型 1.1.1 Java程序的基本结构 1.1.2 原始数据类型与表达式 1.1.3  语句 1.1.4  简便记法 1.1.5  数组 1.1.6  静态方法 1.1.7  API 1.1.8  字符串 1.1.9  输入输出 1.1.10  二分查找 1.1.11  展望 1.2  数据抽象 1.2.1  使用抽象数据类型 1.2.2  抽象数据类型举例 1.2.3  抽象数据类型的实现 1.2.4  更多抽象数据类型的实现 1.2.5  数据类型的设计 1.3  背包、队列和栈 1.3.1  API 1.3.2  集合类数据类型的实现 1.3.3  链表 1.3.4  综述 1.4  算法分析 1.4.1  科学方法 1.4.2  观察 1.4.3  数学模型 1.4.4  增长数量级的分类 1.4.5  设计更快的算法 1.4.6  倍率实验 1.4.7  注意事项 1.4.8  处理对于输入的依赖 1.4.9  内存 1.4.10  展望 1.5  案例研究:union-find算法 1.5.1  动态连通性 1.5.2  实现 1.5.3  展望 第2章  排序 2.1  初级排序算法 2.1.1  游戏规则 2.1.2  选择排序 2.1.3  插入排序 2.1.4  排序算法的可视化 2.1.5  比较两种排序算法 2.1.6  希尔排序 2.2  归并排序 2.2.1  原地归并的抽象方法 2.2.2  自顶向下的归并排序 2.2.3  自底向上的归并排序 2.2.4  排序算法的复杂度 2.3  快速排序 2.3.1  基本算法 2.3.2  性能特点 2.3.3  算法改进 2.4  优先队列 2.4.1  API 2.4.2  初级实现 2.4.3  堆的定义 2.4.4  堆的算法 2.4.5  堆排序 2.5  应用 2.5.1  将各种数据排序 2.5.2  我应该使用哪种排序算法 2.5.3  问题的归约 2.5.4  排序应用一览 第3章 查找 3.1 符号表 3.1.1 API 3.1.2 有序符号表 3.1.3 用例举例 3.1.4 无序链表中的顺序查找 3.1.5 有序数组中的二分查找 3.1.6 对二分查找的分析 3.1.7 预览 3.2 二叉查找树 3.2.1 基本实现 3.2.2 分析 3.2.3 有序性相关的方法与删除操作 3.3 平衡查找树 3.3.1 2-3查找树 3.3.2 红黑二叉查找树 3.3.3 实现 3.3.4 删除操作 3.3.5 红黑树的性质 3.4 散列表 3.4.1 散列函数 3.4.2 基于拉链法的散列表 3.4.3 基于线性探测法的散列表 3.4.4 调整数组大小 3.4.5 内存使用 3.5 应用 3.5.1 我应该使用符号表的哪种实现 3.5.2 集合的API 3.5.3 字典类用例 3.5.4 索引类用例 3.5.5 稀疏向量 第4章  图 4.1  无向图 4.1.1  术语表 4.1.2  表示无向图的数据类型 4.1.3  深度优先搜索 4.1.4  寻找路径 4.1.5  广度优先搜索 4.1.6  连通分量 4.1.7  符号图 4.1.8  总结 4.2  有向图 4.2.1  术语 4.2.2  有向图的数据类型 4.2.3  有向图中的可达性 4.2.4  环和有向无环图 4.2.5  有向图中的强连通性 4.2.6  总结 4.3  最小生成树 4.3.1  原理 4.3.2  加权无向图的数据类型 4.3.3  最小生成树的API和测试用例 4.3.4  Prim算法 4.3.5  Prim算法的即时实现 4.3.6  Kruskal算法 4.3.7  展望 4.4  最短路径 4.4.1  最短路径的性质 4.4.2  加权有向图的数据结构 4.4.3  最短路径算法的理论基础 4.4.4  Dijkstra算法 4.4.5  无环加权有向图中的最短路径算法 4.4.6  一般加权有向图中的最短路径问题 4.4.7  展望 第5章  字符串 5.1  字符串排序 5.1.1  键索引计数法 5.1.2  低位优先的字符串排序 5.1.3  高位优先的字符串排序 5.1.4  三向字符串快速排序 5.1.5  字符串排序算法的选择 5.2  单词查找树 5.2.1  单词查找树 5.2.2  单词查找树的性质 5.2.3  三向单词查找树 5.2.4  三向单词查找树的性质 5.2.5  应该使用字符串符号表的哪种实现 5.3  子字符串查找 5.3.1  历史简介 5.3.2  暴力子字符串查找算法 5.3.3  Knuth-Morris-Pratt子字符串查找算法 5.3.4  Boyer-Moore字符串查找算法 5.3.5  Rabin-Karp指纹字符串查找算法 5.3.6  总结 5.4  正则表达式 5.4.1  使用正则表达式描述模式 5.4.2  缩略写法 5.4.3  正则表达式的实际应用 5.4.4  非确定有限状态自动机 5.4.5  模拟NFA的运行 5.4.6  构造与正则表达式对应的 5.5  数据压缩 5.5.1  游戏规则 5.5.2  读写二进制数据 5.5.3  局限 5.5.4  热身运动:基因组 5.5.5  游程编码 5.5.6  霍夫曼压缩 第6章  背景 索引
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陈一月的编程岁月

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值