【C++】图像处理中的微分算子原理与实现(一)

简介: 一阶微分边缘算子:经典算子比如:Roberts(罗伯特)、Prewitt(普鲁伊特)、Sobel(索贝尔),Canny(坎尼)等。二阶微分边缘算子:Laplacian算子,LoG( Laplace of Gaussian function)边缘检测算子和DoG(Difference of Gaussian)高斯差分算子。

fe5a1c705f924bae992d7671ccac28ed.png

Roberts算子

1963年,Roberts算子,又称罗伯茨算子,是一种最简单的算子,是一种利用局部差分算子寻找边缘的算子。他采用对角线方向相邻两象素之差近似梯度幅值检测边缘。检测垂直边缘的效果好于斜向边缘,定位精度高,对噪声敏感,无法抑制噪声的影响。

Roberts算子的模板分为水平方向和垂直方向,如下式所示,从其模板可以看出,Roberts算子能较好的增强正负45度的图像边缘。

9d7a0b990576428fa8877b99048c5bf1.gif

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算子适合用来识别噪声较多、灰度渐变的图像,其计算公式如下所示:

02e8c151c79e4e93b3a5701347ffce3c.gif

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);
}
目录
相关文章
|
2月前
|
C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(二)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
2月前
|
编译器 C++ 开发者
【C++】深入解析C/C++内存管理:new与delete的使用及原理(三)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
2月前
|
存储 C语言 C++
【C++】深入解析C/C++内存管理:new与delete的使用及原理(一)
【C++】深入解析C/C++内存管理:new与delete的使用及原理
|
2月前
|
C++
C++番外篇——虚拟继承解决数据冗余和二义性的原理
C++番外篇——虚拟继承解决数据冗余和二义性的原理
42 1
|
6月前
|
存储 自然语言处理 安全
C++ STL标准库 《string原理与实战分析》
C++ STL标准库 《string原理与实战分析》
95 0
|
7月前
|
小程序 编译器 Linux
C++ 异常原理:以一个小程序为例
作者在调查某个 bug 时涉及到 C++ 异常,借此机会以本文把 C++ 异常机制梳理清楚供大家参考。
|
7月前
|
设计模式 算法 C++
【C++】STL之迭代器介绍、原理、失效
【C++】STL之迭代器介绍、原理、失效
137 2
|
6月前
|
大数据 C++ 索引
C++ STL标准库 《vector向量原理与实战分析》
C++ STL标准库 《vector向量原理与实战分析》
58 0
|
6月前
|
C++ 容器
C++ STL标准库 《queue单向队列原理与实战分析》
C++ STL标准库 《queue单向队列原理与实战分析》
49 0
|
7月前
|
编译器 C++ 容器
C++模板的原理及使用
C++模板的原理及使用