Opencv2.4学习::形态学滤波-角点检测

形态学滤波-角点检测


就是利用形态学处理中的腐蚀和膨胀操作进行的角点检测、边缘检测。


基本步骤

第一步:十字型核-------->【对原图:膨胀操作】

效果:原图在水平和垂直方向会扩展,而45度.135度方向没有得到扩展

目的:目的是使得在下一步的腐蚀操作中,保证腐蚀后的边缘与原图一致,而只有角点被腐蚀掉

第二步:菱形核-------->【对第一步的结果:腐蚀操作】

效果:使得第一步的结果在水平和垂直方向被腐蚀,而在45度.135度等方向也有一定腐蚀效果,使用菱形而不用十字进行腐蚀是为了斜方向得到腐蚀

第一步+第二部的最终结果:原图的边缘不发生变化,仅有角点被腐蚀

上图来源:https://blog.csdn.net/z827997640/article/details/80536547

个人认为,角点检测到这里就应该结束了,最后一步直接用原图与第二步的结果相减,就可以得出角点了

这里给出测试代码:

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void main()
{
	Mat srcImg = imread("F:\\opencv_re_learn\\contour1.jpg");
	if (!srcImg.data){
		cout << "failed to read" << endl;
		system("pause");
		return;
	}
	Mat srcGray;
	cvtColor(srcImg, srcGray, CV_RGB2GRAY);
	Mat thresh;
	thresh = srcGray.clone();
	threshold(srcGray, thresh, 176, 255, CV_THRESH_BINARY_INV);
	imshow("thresh", thresh);
	//定义核
	Mat CrossMat(5, 5, CV_8U, Scalar(0));
	Mat diamondMat(5, 5, CV_8U, Scalar(1));
	Mat squareMat(5, 5, CV_8U, Scalar(1));
	Mat X(5, 5, CV_8U, Scalar(0));
	//十字形核
	for (int i = 0; i < 5; i++){
		CrossMat.at<uchar>(2, i) = 1;
		CrossMat.at<uchar>(i, 2) = 1;
	}
	//菱形形状核
	diamondMat.at<uchar>(0, 0) = 0;
	diamondMat.at<uchar>(0, 1) = 0;
	diamondMat.at<uchar>(1, 0) = 0;
	diamondMat.at<uchar>(4, 4) = 0;
	diamondMat.at<uchar>(3, 4) = 0;
	diamondMat.at<uchar>(4, 3) = 0;
	diamondMat.at<uchar>(4, 0) = 0;
	diamondMat.at<uchar>(4, 1) = 0;
	diamondMat.at<uchar>(3, 0) = 0;
	diamondMat.at<uchar>(0, 4) = 0;
	diamondMat.at<uchar>(0, 3) = 0;
	diamondMat.at<uchar>(1, 4) = 0;
	//X形状核
	for (int i = 0; i < 5; i++){
		X.at<uchar>(i, i) = 1;
		X.at<uchar>(4 - i, i) = 1;
	}
	//第一步:十字型核,【膨胀操作】
	//原图在水平和垂直方向会扩展,而45度.135度方向没有得到扩展
	//目的是使得在下一步的腐蚀操作中,保证腐蚀后的边缘与原图一致,
	//而只有角点被腐蚀掉
	Mat result;
	dilate(thresh, result, CrossMat);
	imshow("1:Cross", result);
	//第二步:菱形核,【腐蚀操作】
	//效果:使得第一步的结果在水平和垂直方向被腐蚀,而在45度.135度等方向也,
	//有一定腐蚀效果,使用菱形而不用十字进行腐蚀是为了斜方向得到腐蚀
	//第一第二步操作后的结果是:原图的边缘不发生变化,仅有角点被腐蚀
	erode(result, result, diamondMat);
	imshow("2:diamond", result);
	
	//计算差值
	absdiff(thresh, result, result);
	threshold(result, result, 30, 255, THRESH_BINARY);
	//绘制
	for (int i = 0; i < result.rows; i++){
		//获取行指针
		const uchar* data = result.ptr<uchar>(i);
		for (int j = 0; j < result.cols; j++){
			//如果是角点,则绘制圆圈
			if (data[j]){
				circle(srcImg, Point(j, i), 8,
					Scalar(0, 0, 255));
			}
		}
	}
	imshow("src", srcImg);
	imshow("result", result);
	waitKey(0);


}

测试结果: 


实际上,算法给出还有第三第四步

第三步: X型核-------->【对原图:膨胀操作】

效果:使得原图在水平和垂直,45度,135度等倾斜方向都有扩展

 

第四步:正方形核---------->【对第三步结果:腐蚀操作】

效果:又腐蚀掉一次

第三第四部操作后的结果是:原图角点不发生变化,而水平和垂直方向的边缘似乎被腐蚀掉

 

最后一步:将第二步与第四步的结果相减,获得角点


以上四步的全部代码如下:

#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
#include<iostream>
using namespace std;
using namespace cv;
void main()
{
	Mat srcImg = imread("F:\\opencv_re_learn\\contour1.jpg");
	if (!srcImg.data){
		cout << "failed to read" << endl;
		system("pause");
		return;
	}
	Mat srcGray;
	cvtColor(srcImg, srcGray, CV_RGB2GRAY);
	Mat thresh;
	thresh = srcGray.clone();
	threshold(srcGray, thresh, 176, 255, CV_THRESH_BINARY_INV);
	imshow("thresh", thresh);
	//定义核
	Mat CrossMat(5, 5, CV_8U, Scalar(0));
	Mat diamondMat(5, 5, CV_8U, Scalar(1));
	Mat squareMat(5, 5, CV_8U, Scalar(1));
	Mat X(5, 5, CV_8U, Scalar(0));
	//十字形核
	for (int i = 0; i < 5; i++){
		CrossMat.at<uchar>(2, i) = 1;
		CrossMat.at<uchar>(i, 2) = 1;
	}
	//菱形形状核
	diamondMat.at<uchar>(0, 0) = 0;
	diamondMat.at<uchar>(0, 1) = 0;
	diamondMat.at<uchar>(1, 0) = 0;
	diamondMat.at<uchar>(4, 4) = 0;
	diamondMat.at<uchar>(3, 4) = 0;
	diamondMat.at<uchar>(4, 3) = 0;
	diamondMat.at<uchar>(4, 0) = 0;
	diamondMat.at<uchar>(4, 1) = 0;
	diamondMat.at<uchar>(3, 0) = 0;
	diamondMat.at<uchar>(0, 4) = 0;
	diamondMat.at<uchar>(0, 3) = 0;
	diamondMat.at<uchar>(1, 4) = 0;
	//X形状核
	for (int i = 0; i < 5; i++){
		X.at<uchar>(i, i) = 1;
		X.at<uchar>(4 - i, i) = 1;
	}
	//第一步:十字型核,【膨胀操作】
	//原图在水平和垂直方向会扩展,而45度.135度方向没有得到扩展
	//目的是使得在下一步的腐蚀操作中,保证腐蚀后的边缘与原图一致,
	//而只有角点被腐蚀掉
	Mat result;
	dilate(thresh, result, CrossMat);
	imshow("1:Cross", result);
	//第二步:菱形核,【腐蚀操作】
	//效果:使得第一步的结果在水平和垂直方向被腐蚀,而在45度.135度等方向也,
	//有一定腐蚀效果,使用菱形而不用十字进行腐蚀是为了斜方向得到腐蚀
	//第一第二步操作后的结果是:原图的边缘不发生变化,仅有角点被腐蚀
	erode(result, result, diamondMat);
	imshow("2:diamond", result);
	//第三步:X型核对原图膨胀
	//效果:使得原图在水平和垂直,45度,135度等倾斜方向都有扩展
	Mat result2;
	dilate(thresh, result2, X);
	imshow("X", result2);
	//第四步:正方形核,【腐蚀操作】
	//效果:又腐蚀掉一次,第三第四部操作后的结果是,原图角点不发生变化,
	//而水平和垂直方向的边缘似乎被腐蚀掉
	erode(result2, result2, squareMat);
	imshow("squ", result2);
	//计算差值
	absdiff(result2, result, result);
	threshold(result, result, 30, 255, THRESH_BINARY);
	//绘制
	for (int i = 0; i < result.rows; i++){
		//获取行指针
		const uchar* data = result.ptr<uchar>(i);
		for (int j = 0; j < result.cols; j++){
			//如果是角点,则绘制圆圈
			if (data[j]){
				circle(srcImg, Point(j, i), 8,
					Scalar(0, 0, 255));
			}
		}
	}
	imshow("src", srcImg);
	imshow("result", result);
	waitKey(0);


}

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值