Roberts算子
1963年,Roberts算子,又称罗伯茨算子,是一种最简单的算子,是一种利用局部差分算子寻找边缘的算子。他采用对角线方向相邻两象素之差近似梯度幅值检测边缘。检测垂直边缘的效果好于斜向边缘,定位精度高,对噪声敏感,无法抑制噪声的影响。
Roberts算子的模板分为水平方向和垂直方向,如下式所示,从其模板可以看出,Roberts算子能较好的增强正负45度的图像边缘。
voidquick_opencv::roberts_Demo(Mat&img) { // Roberts算子边缘检测cvtColor(img,img,COLOR_BGR2GRAY); Matgrad; grad.create(img.size(), CV_8UC1); for (inti=1; i<img.rows-1; i++) { for (intj=1; j<img.cols-1; j++) { grad.at<uchar>(i, j) =saturate_cast<uchar>(fabs(img.at<uchar>(i, j) -img.at<uchar>(i-1, j-1)) +fabs(img.at<uchar>(i, j-1) -img.at<uchar>(i-1, j))); } } imshow("Roberts算子", grad);
Prewitt算子
1970年,Prewitt算子来自J.M.S. Prewitt "Object Enhancement and Extraction" in "Picture processing and Psychopictorics", Academic Press
Prewitt算子是一种图像边缘检测的微分算子,其原理是利用特定区域内像素灰度值产生的差分实现边缘检测。由于Prewitt算子采用 33 模板对区域内的像素值进行计算,而Robert算子的模板为 22,故Prewitt算子的边缘检测结果在水平方向和垂直方向均比Robert算子更加明显。Prewitt算子适合用来识别噪声较多、灰度渐变的图像,其计算公式如下所示:
voidgetPrewitt_oper(Mat&getPrewitt_horizontal, Mat&getPrewitt_vertical, Mat&getPrewitt_Diagonal1, Mat&getPrewitt_Diagonal2) { //水平方向getPrewitt_horizontal= (Mat_<float>(3, 3) <<-1, -1, -1, 0, 0, 0, 1, 1, 1); //垂直方向getPrewitt_vertical= (Mat_<float>(3, 3) <<-1, 0, 1, -1, 0, 1, -1, 0, 1); //对角135°getPrewitt_Diagonal1= (Mat_<float>(3, 3) <<0, 1, 1, -1, 0, 1, -1, -1, 0); //对角45°getPrewitt_Diagonal2= (Mat_<float>(3, 3) <<-1, -1, 0, -1, 0, 1, 0, 1, 1); //逆时针反转180°得到卷积核flip(getPrewitt_horizontal, getPrewitt_horizontal, -1); flip(getPrewitt_vertical, getPrewitt_vertical, -1); flip(getPrewitt_Diagonal1, getPrewitt_Diagonal1, -1); flip(getPrewitt_Diagonal2, getPrewitt_Diagonal2, -1); } voidedge_Prewitt(Mat&src, Mat&dst1, Mat&dst2, Mat&dst3, Mat&dst4, Mat&dst, intddepth, doubledelta=0, intborderType=BORDER_DEFAULT) { //获取Prewitt算子MatgetPrewitt_horizontal; MatgetPrewitt_vertical; MatgetPrewitt_Diagonal1; MatgetPrewitt_Diagonal2; getPrewitt_oper(getPrewitt_horizontal, getPrewitt_vertical, getPrewitt_Diagonal1, getPrewitt_Diagonal2); //卷积得到水平方向边缘filter2D(src, dst1, ddepth, getPrewitt_horizontal, Point(-1, -1), delta, borderType); //卷积得到4垂直方向边缘filter2D(src, dst2, ddepth, getPrewitt_vertical, Point(-1, -1), delta, borderType); //卷积得到45°方向边缘filter2D(src, dst3, ddepth, getPrewitt_Diagonal1, Point(-1, -1), delta, borderType); //卷积得到135°方向边缘filter2D(src, dst4, ddepth, getPrewitt_Diagonal2, Point(-1, -1), delta, borderType); //边缘强度(近似)convertScaleAbs(dst1, dst1); //求绝对值并转为无符号8位图convertScaleAbs(dst2, dst2); convertScaleAbs(dst3, dst3); //求绝对值并转为无符号8位图convertScaleAbs(dst4, dst4); dst=dst1+dst2; } voidquick_opencv::prewitt_Demo(Mat&img) { Matdst, dst1, dst2, dst3, dst4; cvtColor(img, img, COLOR_BGR2GRAY); //注意:要采用CV_32F,因为有些地方卷积后为负数,若用8位无符号,则会导致这些地方为0edge_Prewitt(img, dst1, dst2, dst3, dst4, dst, CV_32F); namedWindow("水平边缘", WINDOW_NORMAL); imshow("水平边缘", dst1); namedWindow("垂直边缘", WINDOW_NORMAL); imshow("垂直边缘", dst2); namedWindow("45°边缘", WINDOW_NORMAL); imshow("45°边缘", dst3); namedWindow("135°边缘", WINDOW_NORMAL); imshow("135°边缘", dst4); namedWindow("边缘强度", WINDOW_NORMAL); imshow("边缘强度", dst); }