OpenCV之边缘检测(附python代码)

边缘检测的目的:标识出数字图像中亮度变化明显的点。

边缘检测可以按照原理被分为两类,第一类是基于查找的一类(通过寻找图像一阶导数中的最大最小值来检测边界)第二类是基于零穿越的一类(寻找图像二阶导数的零点)。经常有人将锐化和边缘检测弄混,找到有差异的相邻像素是边缘检测,增加有差异的像素的对比度是图像锐化。

一阶导数为基础的边缘检测有sobel算子,prewitt算子,robert算子

二阶导数为基础的边缘检测有LOG算子;

下面先介绍robel算子,robel算子是用卷积的方法以差分的形式近似计算梯度。算子公式如下:

dx=\begin{bmatrix} -1& 0\\ 0 & 1 \end{bmatrix}     dy=\begin{bmatrix} 0 &-1 \\1 & 0 \end{bmatrix}

对于\begin{bmatrix} P1 &P2 &P3 \\ P4& P5 &P6 \\ P7&P8 &P9 \end{bmatrix}中的P5来说,要求其x方向上的梯度秩序与dx卷积即可,即g_{x}=p9-p5同理可得g_{y}=P8-P6

具体处理的过程是:1.对图像灰度化处理2.使用filter2D函数对图像求梯度,3.将x方向上的梯度和y方向上的梯度求绝对值(convertscaleAbs函数)后将两个方向上的绝对值按照加权值进行相加(addweighted函数)4.最后显示图像。

prewitt算子和robel算子原理差不多,但又区别的是卷积核不同。prewitt算子的卷积核是:

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}

sobel算子是利用像素上下左右邻域的灰度加权算法,根据在边缘点处到达极值这一原理进行边缘检测。其大致步骤为1.提取x方向的边缘,x方向上的边缘检测算子为\begin{bmatrix} -1 &0 &1 \\ -2&0 &2 \\ -1&0 &1 \end{bmatrix}

2.提取y方向上的边缘,y方向上的边缘检测算子为\begin{bmatrix} -1 &-2 &-1 \\ 0&0 &0 \\ 1 &2 & 1 \end{bmatrix}

3.综合两个方向的边缘信息(求两个方向上像素的绝对值平方和)。

LOG算子 也就是高斯拉普拉斯函数(laplace of gaussian function)

log算子边缘检测的过程如下:1.首先对图像做高斯滤波2.求其拉普拉斯二阶导,即图像与laplacian of the gaussian function进行滤波运算3.最后通过检测滤波的零交叉可以获得图像的边缘。

常用的5*5版本的高斯拉普拉斯算子(其实就是差分系数)如图所示。

\begin{bmatrix} -2 &-4 &-4 &-4 &-2 \\ -4 &0 &8 &0 &-4 \\ -4& 8 &24 &8 &-4 \\ -4& 0 &8 &0 &-4 \\ -2 &-4 &-4 &-4 &-2 \end{bmatrix}

import cv2 as cv
import sys
import numpy as np
np.set_printoptions(threshold=sys.maxsize)

import matplotlib.pyplot as plt
doc=open('out.txt','w')
#读取图像
img=cv.imread("C:/Users/wangyiyuan/Desktop/20200201172603_hocyy.jpg")

rgb_img=cv.cvtColor(img,cv.COLOR_BGR2RGB)
#灰度化图像
grayImage=cv.cvtColor(img,cv.COLOR_BGR2GRAY)


##################################################robert算子
print("原图像矩阵")

#######robert算子
kernelx=np.array([[-1,0],[0,1]], dtype=int)
kernely=np.array([[0,-1],[1,0]],dtype=int)


x=cv.filter2D(grayImage,cv.CV_16S,kernelx)
y=cv.filter2D(grayImage,cv.CV_16S,kernely)
print(x,file=doc)


#转unit8,图像融合
absX=cv.convertScaleAbs(x)
absY=cv.convertScaleAbs(y)
Roberts=cv.addWeighted(absX,0.5,absY,0.5,0)
#显示图形
titles=['src','robert operator']
image=[rgb_img,Roberts]

for i in range(2):
    plt.subplot(1,2,i+1),plt.imshow(image[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

##############################################################prewitt算子
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=cv.filter2D(grayImage,cv.CV_16S,kernelx)
y=cv.filter2D(grayImage,cv.CV_16S,kernely)
print(x,file=doc)


#转unit8,图像融合
absX=cv.convertScaleAbs(x)
absY=cv.convertScaleAbs(y)
Roberts=cv.addWeighted(absX,0.5,absY,0.5,0)
#显示图形
titles=['src','prewitt operator']
image=[rgb_img,Roberts]

for i in range(2):
    plt.subplot(1,2,i+1),plt.imshow(image[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()


######################################################################log算子

gaussian=cv.GaussianBlur(grayImage,(3,3),0)
dst=cv.Laplacian(gaussian,cv.CV_16S,ksize=3)
log=cv.convertScaleAbs(dst)
plt.rcParams['font.sans-serif']=['SimHei']
titles=['原始图像','LOG算子']
image=[rgb_img,log]

for i in range(2):
    plt.subplot(1,2,i+1),plt.imshow(image[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

##############################################################sobel算子
x=cv.Sobel(grayImage,cv.CV_16S,1,0)
y=cv.Sobel(grayImage,cv.CV_16S,0,1)
absX=cv.convertScaleAbs(x)
absY=cv.convertScaleAbs(y)
sobel=cv.addWeighted(absX,0.5,absY,0.5,0)
plt.rcParams['font.sans-serif']=['SimHei']
titles=['原始图像','sobel算子']
image=[rgb_img,sobel]

for i in range(2):
    plt.subplot(1,2,i+1),plt.imshow(image[i],'gray')
    plt.title(titles[i])
    plt.xticks([]),plt.yticks([])
plt.show()

结果图如下

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值