• 热门专题

OpenCV 边缘检测(形态学梯度)

作者:  发布日期:2014-05-12 23:52:48
Tag标签:形态学  梯度  边缘  
  • 计算机视觉讨论群162501053 转载请注明:http://blog.csdn.net/abcd1992719g

    收入囊中

    利用OpenCV函数进行形态学梯度操作自定义结构矩阵进行形态学梯度操作

    葵花宝典 在此之前,如果你还没接触过灰度图像形态学膨胀与腐蚀,希望你能仔细阅读灰度图像形态学膨胀与腐蚀 本质上,灰度与二值并不差异,二值不过是0与255,膨胀与腐蚀的操作都是一样的 形态学梯度的定义如下:

    形态梯度

    dst=morph_grad(src,element)=dilate(src,element)-erode(src,element)


    通俗讲,dilate是膨胀操作,相当于把图像稍微变胖,灰度阶梯变高,erode相当于把图像变稍微细一点,两个相减,就产生了边缘。 我在Computer Vision: Algorithms and ApplicationsのImage processing 里对形态学操作有简单的介绍。



    初识API
    C++: Mat getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1))
    这个函数用来获得结构矩阵 shape: MORPH_RECT - 矩形的结构元素:值全为1 MORPH_ELLIPSE - 椭圆形结构元素 MORPH_CROSS - 十字形,只有中心在的那一行一列的值为1 ksize:结构元素的大小 anchor:默认(-1,-1),指代中心,只有十字形元素才依赖这个
    C++: void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, intborderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
  • src – 输入图像
  • dst – 输出图像
  • element – 结构元素.如果 element=Mat() , 一个3*3的结构元素就被使用
  • anchor – 同上
  • iterations – 迭代次数
  • borderType – 边界类型,我在Computer Vision: Algorithms and ApplicationsのImage processing讨论过
  • borderValue – 边界值,当边界类型为常数填充时启用

\texttt{dst} (x,y) =  \max _{(x(膨胀公式,灰度图像形态学膨胀与腐蚀此文都有介绍)


腐蚀操作对应的API erode和膨胀是一样的


其他形态学操作函数

C++: void morphologyEx(InputArray src, OutputArray dst, int op, InputArray kernel, Point anchor=Point(-1,-1), int iterations=1, intborderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
  • op – 操作类型,今天我们只关注梯度,也就是第3个
    • MORPH_OPEN - an opening operation
    • MORPH_CLOSE - a closing operation
    • MORPH_GRADIENT - a morphological gradient
    • MORPH_TOPHAT - “top hat”
    • MORPH_BLACKHAT - “black hat”
其他的参数和腐蚀,膨胀是一样的

Morphological gradient:

\texttt{dst} = \mathrm{morph\_grad} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \texttt{src} , \texttt{element} )- \mathrm{erode} ( \texttt{src} , \texttt{element} )



荷枪实弹

先介绍一个类

class MorphoFeatures {
private:

	int threshold;  //用于阀值操作
	
	void applyThreshold(Mat& result) {
		if (threshold>0)
			cv::threshold(result, result,threshold, 255, THRESH_BINARY_INV); //注意参数是THRESH_BINARY_INV,当<threshold为255,否则为0,倒过来了
	}

public:

	void setThreshold(int x) {
		threshold = x;
	}

	Mat getEdges(const Mat &image) {
		Mat result;
		morphologyEx(image,result,MORPH_GRADIENT,Mat());  //直接调用,默认3*3
		applyThreshold(result);
		return result;
   	}
   	
};

我们的主函数

int main( int, char** argv )  
{  
	Mat image;
    image = imread( argv[1] );
    cvtColor( image, image, CV_RGB2GRAY );
    
	MorphoFeatures morpho;
	morpho.setThreshold(40); 
	Mat edges;
	edges= morpho.getEdges(image);

    namedWindow("dstImage", 1);  
    imshow("dstImage", edges);  
    waitKey();  
    return 0;  
} 

效果图:



我们再基于\texttt{dst} = \mathrm{morph\_grad} ( \texttt{src} , \texttt{element} )= \mathrm{dilate} ( \texttt{src} , \texttt{element} )- \mathrm{erode} ( \texttt{src} , \texttt{element} )公式自己实现一下,修改的地方很少,主函数没有变化(不一样的地方有注释)

class MorphoFeatures {
private:

	int threshold;
	Mat structedElement;  //自己定义的结构矩阵
	
	void applyThreshold(Mat& result) {
		if (threshold>0)
			cv::threshold(result, result,threshold, 255, THRESH_BINARY_INV);
	}

public:

	MorphoFeatures() : structedElement(3,3,CV_8U,Scalar(1)){} //没有使用API而是直接构造

	void setThreshold(int x) {
		threshold = x;
	}

	Mat getEdges(const Mat &image) {
		Mat result,result1,result2;
		dilate(image,result1,structedElement);  //先膨胀
		erode(image,result2,structedElement);   //再腐蚀
		result = result1 - result2;             //然后相减
		applyThreshold(result);
		return result;
   	}
   	
};

效果图:好像一样哦




举一反三 习惯了用矩形的结构元素,我们用椭圆试一试吧

代码改的地方也很少,为了方便大家,这个代码就全部发出来了
#include "opencv2/highgui/highgui.hpp"  
#include "opencv2/imgproc/imgproc.hpp"  
using namespace cv;  

class MorphoFeatures {
private:

	int threshold;
	Mat structedElement;
	
	void applyThreshold(Mat& result) {
		if (threshold>0)
			cv::threshold(result, result,threshold, 255, THRESH_BINARY_INV);
	}

public:

	MorphoFeatures() {
		structedElement = getStructuringElement( MORPH_ELLIPSE,  Size( 3, 3 ));  
	}

	void setThreshold(int x) {
		threshold = x;
	}

	Mat getEdges(const Mat &image) {
		Mat result,result1,result2;
		dilate(image,result1,structedElement);
      	erode(image,result2,structedElement);
      	result = result1 - result2;
		applyThreshold(result);
		return result;
   	}
   	
};
 

int main( int, char** argv )  
{  
	Mat image;
    image = imread( argv[1] );
    cvtColor( image, image, CV_RGB2GRAY );
    
	MorphoFeatures morpho;
	morpho.setThreshold(40); 
	Mat edges;
	edges= morpho.getEdges(image);

    namedWindow("dstImage", 1);  
    imshow("dstImage", edges);  
    waitKey();  
    return 0;  
} 


About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规