首页 > 其他 > 详细

OpenCV2马拉松第16圈——边缘检测(形态学梯度)

时间:2014-05-14 01:21:21      阅读:596      评论:0      收藏:0      [点我收藏+]
计算机视觉讨论群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 – 边界值,当边界类型为常数填充时启用

bubuko.com,布布扣(膨胀公式,灰度图像形态学膨胀与腐蚀此文都有介绍)


腐蚀操作对应的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:

bubuko.com,布布扣



荷枪实弹

先介绍一个类

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;  
} 

效果图:

bubuko.com,布布扣


我们再基于bubuko.com,布布扣公式自己实现一下,修改的地方很少,主函数没有变化(不一样的地方有注释)

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;
   	}
   	
};

效果图:好像一样哦

bubuko.com,布布扣



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

代码改的地方也很少,为了方便大家,这个代码就全部发出来了
#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;  
} 


OpenCV2马拉松第16圈——边缘检测(形态学梯度),布布扣,bubuko.com

OpenCV2马拉松第16圈——边缘检测(形态学梯度)

原文:http://blog.csdn.net/abcd1992719g/article/details/25599131

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!