我们知道,进行边缘检测有两种方法:一阶导数的极值、二阶导数的过零点。
Robert算子是一种一阶微分算子,而且Robert算子是第一个边缘检测算子,提出者是Lawrence Roberts in 1963。
从这篇博客开始,会陆续介绍几种经典的边缘检测算子。先附上各种边缘检测算法的优缺点:
Roberts算子是一种斜向偏差分的梯度计算方法,梯度的大小代表边缘的强度,梯度的方向与边缘的走向垂直(正交)。
梯度算子定义为:
为了简化计算,一般梯度算子可以近似为:
由此,我们可得图像离散化(差分代替偏导)的对角线Roberts算子:
从图像处理的实际效果来看,计算简单,边缘定位较准,但对噪声极敏感。适用于边缘明显且噪声较少的图像分割。
#include
#include
#include
#include
void getRobert_oper(cv::Mat& getRobert_oper1, cv::Mat& getRobert_oper2){
//135°方向
getRobert_oper1 = (cv::Mat_(2, 2) << 1, 0, -1, 0);
//45°方向
getRobert_oper2 = (cv::Mat_(2, 2) << 0, 1, -1, 0);
//逆时针反转180°得到卷积核(这里反转之后与原来一样,为了严谨还是做这个操作)
cv::flip(getRobert_oper1, getRobert_oper1, -1);
cv::flip(getRobert_oper2, getRobert_oper2, -1);
}
void edge_Robert(cv::Mat& src, cv::Mat& dst1, cv::Mat& dst2, cv::Mat& dst,int ddepth, double delta = 0, int borderType = cv::BORDER_DEFAULT){
//获取Robert算子
cv::Mat getRobert_oper1;
cv::Mat getRobert_oper2;
getRobert_oper(getRobert_oper1, getRobert_oper2);
//卷积得到135°方向边缘
cv::filter2D(src, dst1, ddepth, getRobert_oper1, cv::Point(0, 0), delta, borderType);
//卷积得到45°方向边缘
cv::filter2D(src, dst2, ddepth, getRobert_oper2, cv::Point(1, 0), delta, borderType);
//边缘强度(近似)
cv::convertScaleAbs(dst1, dst1); //求绝对值并转为无符号8位图
cv::convertScaleAbs(dst2, dst2);
dst = dst1 + dst2;
}
int main(){
cv::Mat src = cv::imread("I:\\Learning-and-Practice\\2019Change\\Image process algorithm\\Img\\Fig1025(a)(building_original).tif");
if (src.empty()){
return -1;
}
if (src.channels() > 1) cv::cvtColor(src, src, CV_RGB2GRAY);
cv::Mat dst, dst1, dst2;
//注意:要采用CV_32F,因为有些地方卷积后为负数,若用8位无符号,则会导致这些地方为0
edge_Robert(src, dst1, dst2, dst, CV_32F);
imshow("src", src);
imshow("135°边缘", dst1);
imshow("45°边缘", dst2);
imshow("边缘强度", dst);
cv::waitKey(0);
return 0;
}
https://zhuanlan.zhihu.com/p/49447503
http://imgtec.eetrend.com/d6-imgtec/blog/2018-09/17673.html
https://blog.csdn.net/tigerda/article/details/61192943
https://blog.csdn.net/Augusdi/article/details/9028331