
OpenCV 图像梯度计算(学习笔记)
Sobel算子简介
Sobel算子是一个图像边缘检测的算法。
其基本原理是通过计算像素点梯度值来确定图像中的边缘信息。
什么情况下会产生梯度?
举例:在一个白心圆黑心背景图中,纯白或纯黑部分都不会产生,只有的边缘部分将会产生梯度的情况。
定义Sobel算子模板
Sobel算子模板是一个3*3
的矩阵卷积核。
将3*3
的模板矩阵与图像中的某个像素点对应位置进行对齐。
如下图所示:
当我们要求出模板矩阵与该像素点周围8个像素点的加权平均值,水平x
方向为:
含义:当目标(P5点)左右两列差别特别大的时候,目标点的值会很大,说明该点为边界。
求y
方向的权值公式如下:
Sobel算子的梯度问题
1.目标像素点求得的值小于0或者大于255怎么办?
通常Opencv默认的是是截断操作,即小于0就按0算,大于255按255算。
2.截断操作合适吗?
不合适,因为呈现的程度不一样。举例:-200或-1它都是按照0来算
3.应该如何操作?
对于小于0的值取出绝对值,大于255的可按255算(因为255是最大的值了)
总梯度计算
示例代码
import cv2 #opencv读取的格式是BGR
import numpy as np
import matplotlib.pyplot as plt#Matplotlib是RGB
%matplotlib inline
展示原图。
img = cv2.imread('pie.png',cv2.IMREAD_GRAYSCALE)
cv2.imshow("img",img)
cv2.waitKey()
cv2.destroyAllWindows()
可通过cv2.Sobel
来进行计算,举例:dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
参数如下:ddepth
:图像的深度dx
和dy
分别表示水平和竖直方向ksize
是Sobel算子的大小
def cv_show(img,name):
cv2.imshow(name,img)
cv2.waitKey()
cv2.destroyAllWindows()
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
cv_show(sobelx,'sobelx')
白到黑是正数,黑到白就是负数了,所有的负数会被截断成0,所以要取绝对值。
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
# 进行取绝对值操作
sobelx = cv2.convertScaleAbs(sobelx)
cv_show(sobelx,'sobelx')
再求y
的Sobel算子。
分别计算x和y,再求和.
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')
不建议直接计算.
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show(sobelxy,'sobelxy')
再举个例子。
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
cv_show(img,'img')
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
cv_show(sobelxy,'sobelxy')
但是如果直接计算就会效果不佳。
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelxy=cv2.Sobel(img,cv2.CV_64F,1,1,ksize=3)
sobelxy = cv2.convertScaleAbs(sobelxy)
cv_show(sobelxy,'sobelxy')
Scharr算子
与Sobel算子一样的原理,只是数值比它大一些,对于细节刻画得更明显一些。
laplacian算子
这个很不一样,不会进行梯度。
Laplacian是利用二阶导数来检测边缘,因为图像是二维的,我们需要在两个方向上求导,如下式所示:
计算P5的梯度公式如下:
\large P5{_n}ew=(P2+P4+P6+P8)-4*P5
代码实验对比
通过进行Sobel、Scharr和laplacian的代码如下所示:
#不同算子的差异
img = cv2.imread('lena.jpg',cv2.IMREAD_GRAYSCALE)
sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobely = cv2.Sobel(img,cv2.CV_64F,0,1,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx,0.5,sobely,0.5,0)
scharrx = cv2.Scharr(img,cv2.CV_64F,1,0)
scharry = cv2.Scharr(img,cv2.CV_64F,0,1)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx,0.5,scharry,0.5,0)
laplacian = cv2.Laplacian(img,cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)
res = np.hstack((sobelxy,scharrxy,laplacian))
cv_show(res,'res')
欢迎加群讨论技术,1群:677373950(满了,可以加,但通过不了),2群:656732739

