【OpenCv】三天学会C++/OPENCV2基本操作之形态学滤波检测边缘和角点

形态学滤波可以用于检测图像中的特征,如边缘和角点,Opencv中利用形态学检测角点必须使用结构元素,自己需要定义一些结构元素如菱形、方形、十字形等。

实例:

#include "stdafx.h"
#include "ColorHistogram.h"
#include "ObjectFinder.h"
#include <opencv2\core\core.hpp>
#include<opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include <opencv2\video\video.hpp>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
 
class MorphoFeatures{
 
private:
	//用于生成二值图像的阈值
	int threshold;
	//角点检测用到的结构元素
	Mat cross;
	Mat diamond;
	Mat square;
	Mat x;
 
public:
	//检测角点
	//opencv没有直接实现它,需要定义四种不同的结构元素,
	//包括:菱形,方形,十字形,x形。并在构造函数中完成
	MorphoFeatures() :threshold(-1),
		cross(5, 5, CV_8U, Scalar(0)),
		diamond(5, 5, CV_8U, Scalar(1)),
		square(5, 5, CV_8U, Scalar(1)),
		x(5, 5, CV_8U, Scalar(0)){
 
		//创建十字形元素
		for (int i = 0; i < 5; i++)
		{
			cross.at<uchar>(2, i) = 1;
			cross.at<uchar>(i, 2) = 1;
		}
		//创建菱形
		diamond.at<uchar>(0, 0) = 0;
		diamond.at<uchar>(0, 1) = 0;
		diamond.at<uchar>(1, 0) = 0;
		diamond.at<uchar>(4, 4) = 0;
		diamond.at<uchar>(3, 4) = 0;
		diamond.at<uchar>(4, 3) = 0;
		diamond.at<uchar>(4, 0) = 0;
		diamond.at<uchar>(4, 1) = 0;
		diamond.at<uchar>(3, 0) = 0;
		diamond.at<uchar>(0, 4) = 0;
		diamond.at<uchar>(0, 3) = 0;
		diamond.at<uchar>(1, 4) = 0;
 
		//创建x形
		for (int i = 0; i < 5; i++)
		{
			x.at<char>(i, i) = 1;
			x.at<char>(4 - i, i) = 1;
		}
	}
 
	Mat getEdges(const Mat &image)
	{
		//得到梯度图
		Mat result;
		//morphology函数配上合适的滤波器就可以实现直线检测
		morphologyEx(image, result, MORPH_GRADIENT, Mat());
		applyThreshold(result);
		return result;
	}
	void setThreshold(int t)
	{
		threshold = t;
	}
	void applyThreshold(Mat & result)
	{
		if (threshold > 0)
			cv::threshold(result, result, threshold, 255, THRESH_BINARY);
	}
 
	//需要连接使用这些结构元素,得到最终的角点映射图
	Mat getCorners(const Mat&image)
	{
		Mat result;
		//十字形膨胀
		dilate(image, result, cross);
		//菱形腐蚀
		erode(result, result, diamond);
 
		Mat result2;
		//x形膨胀
		dilate(image, result2, x);
		//方形腐蚀
		erode(result2, result2, square);
 
		//通过对两张图像做差值,得到角点图像
		absdiff(result2, result, result);
		//阈值化得到二值图像
		applyThreshold(result);
		return result;
	}
	//为了可视化,在在二值图像中每个监测点绘制一个圆
	void drawOnImage(const Mat & binary, Mat & image)
	{
		Mat_<uchar>::const_iterator it = binary.begin<uchar>();
		Mat_<uchar>::const_iterator itend = binary.end<uchar>();
 
		//遍历每个像素
		for (int i = 0; it != itend; ++i, ++it)
		{
			if (!*it)
				circle(image, Point(i%image.step, i / image.step), 5, Scalar(0, 255, 0));
				
		}
	}
};
int _tmain(int argc, _TCHAR* argv[])
{
	//边缘检测
	Mat image = imread("imL.png", 0);
	Mat image1 = imread("imL.png");
	//imshow("d", image);
	if (!image.data)
		return -1;
	MorphoFeatures morpho;
	morpho.setThreshold(40);
	Mat edges;
	edges = morpho.getEdges(image);
	imshow("edges", edges);
 
	//角点检测
 
	morpho.setThreshold(-1);
	Mat corners;
	corners = morpho.getCorners(image);
	morphologyEx(corners, corners, MORPH_TOPHAT, Mat());
	threshold(corners, corners, 40, 255, THRESH_BINARY_INV);
	//imshow("角点",corners);  
 
	//展示图片上的角点  
	morpho.drawOnImage(corners, image);
	imshow("corners", image);
	waitKey(0);
	return 0;
}

效果如下:

挑选的这些元素可以保证连续的边缘不受改变,但是由于它们的重复效应,角点的边缘仍受影响,感兴趣可以重点学习一下形态学滤波相关内容,这里只做入门学习。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值