在进行图像识别时,常需要检测图像的边缘信息。图像的边缘指的是灰度值急剧变化的地方,一般是背景和前景物体的交界处。由于边缘处的灰度值急剧变化特性,可以利用离散数列的差分(相当于连续函数的导数)来识别边缘。目前常用的边缘检测算法大多数是通过梯度方向导数求卷积的方法,常用的卷积算子有Roberts算子,Prewitt,Sobel算子,Scharr算子等。
1. Roberts算子和Prewitt算子
1.1 Roberts算子
Roberts边缘检测算法是图像,分别与下面两个卷积核(锚点为1所在位置)进行卷积运算。第一个为135度方向像素值差分,第二个为45度方向像素值差分,可以发现卷积后,图像内部由于相近像素值会变为0,成为黑色背景,而边缘处由于像素值相差大,相减的差分值作为新的像素值。因此能够将图像边缘处的像素值识别出来,得到图像的轮廓
通过上述两个卷积会得到145度和45度的卷积结果,将两者合并得到最后的输出结果。有如下四种合并方式:
a. 取两个矩阵对应位置绝对值的和
b. 取两个矩阵对应位置平方和的开方
c. 取两个矩阵对应位置绝对值的最大值
d. 插值法
取平方和的开方效果最好,但同时也是最耗时的操作。
下面通过convolve2d()函数实现robert边缘检测算法的代码和效果如下:(可以发现45度和135度得到的是该角度上的边缘信息,而两者综合后的边缘更加清晰和完整)
#coding:utf-8 import cv2 as cv from scipy import signal import numpy as np def robert(img,boundary="symm",fillvalue=0): H1,W1 = img.shape[:2] r1 = np.array([[1,0],[0,-1]],np.float32) r2 = np.array([[0,1],[-1,0]],np.float32) H2,W2= 2,2 #锚点位置 kr1,kc1=0,0 con_r1 = signal.convolve2d(img,r1,mode="full",boundary=boundary,fillvalue=fillvalue) #截取出same卷积 con_r1 = con_r1[H2-kr1-1:H1+H2-kr1-1,W2-kc1-1:W1+W2-kc1-1] kr2,kc2=0,1 con_r2 = signal.convolve2d(img,r2,mode="full",boundary=boundary,fillvalue=fillvalue) con_r2 = con_r2[H2-kr2-1:H1+H2-kr2-1,W2-kc2-1:W1+W2-kc2-1] return (con_r1,con_r2) if __name__=="__main__": img = cv.imread(r"C:\Users\Administrator\Desktop\Messi.jpg",0) con_r1,con_r2 = robert(img) con_r1 =np.abs(con_r1) edge_135 = con_r1.astype(np.uint8) con_r2 =np.abs(con_r2) edge_45 = con_r2.astype(np.uint8) edge = np.sqrt(np.power(con_r1,2.0)+np.power(con_r2,2.0)) edge = np.round(edge) edge[edge>255]=255 edge = edge.astype(np.uint8) cv.imshow("img",img) cv.imshow("edge_135",edge_135) cv.imshow("edge_45 ",edge_45 ) cv.imshow("edge",edge) cv.waitKey(0) cv.destroyAllWindows()