Roberts算子即交叉微分算子,是基于交叉差分的梯度算子。此算法通过局部差分来计算检测图像的边缘线条,对噪声敏感。
Roberts交叉微分算子分别为主对角线和副对角线方向的算子,有两个2*2的滤波算子组成:
对于图像而言,如果im表示图像像素矩阵,则可以如下计算(i,j)点处的特征值:
|im(i,j)-im(i+1,j+1)|+|im(i+1,j)-im(i,j+1)|
完整代码如下:
import cv2
import numpy as np
def cv_show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
im=cv2.imread('C:/Users/bwy/Desktop/lena.bmp',cv2.IMREAD_GRAYSCALE)
cv_show('im',im)
m,n=im.shape
eIm=np.zeros([m,n])
for i in range(m-1):
for j in range(n-1):
eIm[i,j]=abs(im[i,j]-im[i+1,j+1])+abs(im[i+1,j]-im[i,j+1])
eim=eIm.astype(np.uint8)
res=np.hstack((im,eim))
cv_show('res',res)
结果如图所示:
Sobel算子结合了高斯模糊和一阶微分并计算图像明暗程度的近似值,通过比较图像边缘的明暗程度把该区域内超过阈值的特定像素点记为边缘点。Sobel算子具有一定的平滑作用,对噪声不敏感。
手写代码如下:
def sobel(image):
filterX=np.array([[-1,0,1],[-2,0,2],[-1,0,1]])
filterY=np.array([[-1,-2,-1],[0,0,0],[1,1,2,]])
w,h=im.shape
edgeim=np.zeros((w,h))
theta=np.zeros((w,h))
half_mF=np.floor(mF/2)
half_mF1=half_mF.astype(int)
for i in range(m-1):
for j in range(n-1):
localImage=data[i:i+mF,j:j+nF]
edgeImX=abs(sum(sum(localImage*filterX)))
edgeImY=abs(sum(sum(localImage*filterY)))
edgeim[i,j]=max( edgeImX,edgeImY)
edgeim=edgeim.astype(np.uint8)
if edgeImX == 0:
theta[i, j] = np.pi / 2
else:
theta[i, j] = np.arctan(edgeImY/ edgeImX)
return edgeim,theta
测试:
a,b=sobel(im)
r=np.hstack((im,a))
cv_show('r',r)
结果如图所示:
To begin with,我们看函数:
Dst=cv2.Sobel(im,ddepth,dx,dy,ksize)
参数解释:
Ddepth代表:图像的深度(一般为-1表示输入深度和输出深度一样)
dx,dy代表:水平方向和竖直方向(谁为1代表在哪个方向)
ksize是Sobel算子的大小
Next
对应项相乘在求和=p3+2*p6+p9-p1-2p4-p7(这这里我们会发现在x方向是右减左,那我们运行一下程序看结果如何。
Img=cv2.imread('C:/Users/bwy/Desktop/2.png',cv2.IMREAD_GRAYSCALE)
sobelx=cv2.Sobel(Img,cv2.CV_64F,1,0,ksize=3)
cv_show('sobelx',sobelx)
解释说明一下cv2.CV_64F:在我们进行计算的时候会出现正数和负数都存在,opencv会自动拦截将负数变成零,因此我们需要强制换成负数形式,这就是它的含义。
结果如图所示:
左图是操作过的图,右图是原图。
看到这个左图像,想大家都会有疑问,咦???右边的呢咋没了呢?是因为我们前面说了,在计算的时候是右减左,大家看原图,当把这个圆2从中间分开,左半部分在进行计算的时候 ,是不是白减黑因此它是大于零的,而右半部分黑减白是小于零的,就没了,因此我们需要取绝对值。我们在实现以下代码。
sobelx1=cv2.Sobel(Img,cv2.CV_64F,1,0,ksize=3)
sobelx1=cv2.convertScaleAbs(sobelx1)
cv_show('sobelx1',sobelx1)
结果如图所示:
上下是点点因此我们再看一下Sobel因子,我就不写计算过程了,在y方向上是下减上 。看一下代码吧:
sobely=cv2.Sobel(Img,cv2.CV_64F,0,1,ksize=3)
sobely=cv2.convertScaleAbs(sobely)
cv_show('sobely',sobely)
结果如图所示:
Finished,分别计算x,y之后再求和:
sobelxy=cv2.addWeighted(sobelx1,0.5,sobely,0.5,0)
结果如图所示:
和上面的很像,但它的数更大,效果就会更详细,后面看区别很容易看出来。 而Laplacian算子是一种具有旋转不变性的各向同性的二阶微分算子。我们观察这个算子是四周减去中间,由于它对噪音很敏感所以很少单独用。
#不同算子的差异
im=cv2.imread('C:/Users/bwy/Desktop/lena.bmp',cv2.IMREAD_GRAYSCALE)
sobelxx=cv2.Sobel(im,cv2.CV_64F,1,0,ksize=3)
sobelyy=cv2.Sobel(im,cv2.CV_64F,0,1,ksize=3)
sobelyy=cv2.convertScaleAbs(sobelyy)
sobelxx=cv2.convertScaleAbs(sobelxx)
sobelxxyy=cv2.addWeighted(sobelxx,0.5,sobelyy,0.5,0)
scharrx=cv2.Scharr(im,cv2.CV_64F,1,0)
scharry=cv2.Scharr(im,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(im,cv2.CV_64F)
laplacian=cv2.convertScaleAbs(laplacian)
RR=np.hstack((im,sobelxxyy,scharrxy,laplacian))
cv_show("RR",RR)
结果如图所示: