java 图像梯度检测_opencv学习笔记(六)---图像梯度

图像梯度的算法有很多方法:sabel算子,scharr算子,laplacian算子,sanny边缘检测(下个随笔)。。。

下面是我的一些理解:

sabel算子:

sobel算子主要用于获得数字图像的一阶梯度,常见的应用和物理意义是边缘检测。

函数:

Python: cv2.Sobel(src, ddepth, dx, dy[, dst[, ksize[, scale[, delta[, borderType]]]]]) → dst  (参数就不一一说了,常用的就那几个,其他默认即可)

Parameters:

src – Source image.

dst – Destination image of the same size and the same number of channels as src .

ddepth – Destination image depth.

xorder – Order of the derivative x.

yorder – Order of the derivative y.

ksize – Size of the extended Sobel kernel. It must be 1, 3, 5, or 7.

scale – Optional scale factor for the computed derivative values. By default, no scaling is applied. See getDerivKernels() for details.

delta – Optional delta value that is added to the results prior to storing them in dst .

borderType – Pixel extrapolation method. See borderInterpolate() for details.

原理

算子使用两个33的矩阵(图1)算子使用两个33的矩阵(图1)去和原始图片作卷积,分别得到横向G(x)和纵向G(y)的梯度值,如果梯度值大于某一个阈值,则认为该点为边缘点

Gx方向的相关模板:

d49f0ac16db47012b5761c9de550a9fd.png

Gy方向的相关模板:

892f4f6804c732a2e28bf7d8ef522367.png

具体计算如下:

图像的每一个像素的横向及纵向灰度值通过以下公式结合,来计算该点灰度的大小:

1670d45797afab2168b0b2c2c0101d08.png

通常,为了提高效率使用不开平方的近似值:

0cb6744eda1c0697b3762f5b3b4e154f.png

#sobels算子

img = cv.imread("E:/pictures/lena.jpg",cv.IMREAD_UNCHANGED)

sobelx= cv.Sobel(img,cv.CV_64F,1,0) #cv.CV_64F将像素值转换为double型,不然计算后为负值的像素会被截断为0

sobelx = cv.convertScaleAbs(sobelx) #转换为uint8类型(x方向)

sobely = cv.Sobel(img,cv.CV_64F,0,1)

sobely = cv.convertScaleAbs(sobely)

sobelxy11 = cv.Sobel(img,cv.CV_64F,1,1) #直接x,y方向一起计算(效果不好,应分开计算,再求权重和)

sobelxy11 = cv.convertScaleAbs(sobelxy11)

sobelxy = cv.addWeighted(sobelx,0.5,sobely,0.5,0) #图像权重和

cv.imshow("orginal",img) #dst = cv.addWidget(src1,alpha,src2,beta,gamma)

cv.imshow("sobelx",sobelx) #src1 图一 alpha->图一的权重 src2->图二 beta->图二的权重 gamma->修正值

cv.imshow("sobely",sobely) #dst = src1*alpha+src2*beta+gamma

cv.imshow("sobelxy",sobelxy)

cv.imshow("sobelxy11",sobelxy11)

cv.waitKey()

cv.destroyAllWindows()

188df802da2c16422f0bdfdf2f92f7fa.png

41da4105e0a69c500e278a76389aa21b.png

edd3b4861ccd4c07c0dc9c93904e95a8.png

4c485a247a69b69aa1b7f65128c47b22.png

aebfd8bcf1bdb1319e09382f53cbd4d9.png

用sobel函数同时对想x,y方向检测的效果并不好,一般不用。

scharr算子:

函数:

Python: cv2.Scharr(src, ddepth, dx, dy[, dst[, scale[, delta[, borderType]]]]) → dst

Parameters:

src – Source image.

dst – Destination image of the same size and the same number of channels as src .

ddepth – Destination image depth.

xorder – Order of the derivative x.

yorder – Order of the derivative y.

scale – Optional scale factor for the computed derivative values. By default, no scaling is applied. See getDerivKernels() for details.

delta – Optional delta value that is added to the results prior to storing them in dst .

borderType – Pixel extrapolation method. See borderInterpolate() for details.

scharr算子是对sabel算子的增强,可以看到上图中很多细小的边缘都没检测到,那么scharr算子就是解决这个问题的,它比sabel算子更精确,速度和复杂程度却一样,只是因为用的核不一样

b44be9fc7ba346f8f93db38bdf13063c.png

是scharr 的卷积核,他的原理和sabel算子一样。

#scharr算子 scharr算子是对sabel算子的增强 scharr算子等价于ksize=-1的sabel算子

img = cv.imread("E:/pictures/lena.jpg",cv.IMREAD_GRAYSCALE)

scharrx= cv.Scharr(img,cv.CV_64F,1,0) #scharrx算子要满足dx>=0&&dy>=0&&dx+dy=1

scharrx = cv.convertScaleAbs(scharrx)

scharry = cv.Scharr(img,cv.CV_64F,0,1)

scharry = cv.convertScaleAbs(scharry)

scharrxy = cv.addWeighted(scharrx,0.5,scharry,0.5,0)

#sabel算子和 scharr算子的比较

sobelx= cv.Sobel(img,cv.CV_64F,1,0)

sobelx = cv.convertScaleAbs(sobelx)

sobely = cv.Sobel(img,cv.CV_64F,0,1)

sobely = cv.convertScaleAbs(sobely)

sobelxy = cv.addWeighted(sobelx,0.5,sobely,0.5,0)

cv.imshow("orginal",img)

cv.imshow("sobelxy",sobelxy)

cv.imshow("scharrxy",scharrxy)

cv.waitKey()

cv.destroyAllWindows()

7ff5b98591ef491b6cf6e1ae33e520b8.png

67e129b7416f7769de95ee11d59d2839.png

1635571-20190324145619976-567761782.jpg

3ec20db6389e5991d221241b83120e03.png

laplacian算子:

Laplace算子和Sobel算子一样,属于空间锐化滤波操作,只不过是用的二阶微分,看官网的一些解释:

The function calculates the Laplacian of the source image by adding up the second x and y derivatives calculated using the Sobel operator:

0eee1421430237f8cac8c15b88732b0f.png

This is done when ksize > 1 . When ksize == 1 , the Laplacian is computed by filtering the image with the following

7b2c08f8076f1842fba3e04bfe893832.png aperture:

cdebff03a0476b51c69c5b1130ec2ecc.png

cv.Laplace(src, dst, ksize=3) → None

Parameters:

src – Source image.

dst – Destination image of the same size and the same number of channels as src .

ddepth – Desired depth of the destination image.

ksize – Aperture size used to compute the second-derivative filters. See getDerivKernels() for details. The size must be positive and odd.

scale – Optional scale factor for the computed Laplacian values. By default, no scaling is applied. See getDerivKernels() for details.

delta – Optional delta value that is added to the results prior to storing them in dst .

borderType – Pixel extrapolation method. See borderInterpolate() for details.

#拉普拉斯算子

img = cv.imread("E:/pictures/erode1.jpg",cv.IMREAD_GRAYSCALE)

r = cv.Laplacian(img,cv.CV_64F)

r = cv.convertScaleAbs(r) #关键代码就这两行,拉普拉斯算子不用再求x,y的权重和,因为这个函数都计算好了

cv.imshow("orginal",img)

cv.imshow("laplacian",r)

cv.waitKey()

cv.destroyAllWindows()

ffa73e19757bf4e9fe014f327428c42d.png

768aeca0f08e475f77621f48b20f2ab9.png

Canny边缘检测:

Python: cv2.Canny(image, threshold1, threshold2[, edges[, apertureSize[, L2gradient]]]) → edges

threshold1和threshold2是两个阈值,越小检测效果越好

import cv2 as cv

import numpy as np

img = cv.imread("E:/pictures/lena.jpg")

result1 = cv.Canny(img,50,100)

result2 = cv.Canny(img,100,200)

cv.imshow("orginal",img)

cv.imshow("result1",result1)

cv.imshow("result2",result2)

cv.waitKey()

cv.destroyAllWindows()

395dd41f3aaf3993c8abbd1cff619e34.png

241ccb5d245344c2d5e84256f45fc608.png

8f8c87e9c23266d4c586c0634ff38ff4.png

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值