计算机视觉讨论群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 – 边界值,当边界类型为常数填充时启用
(膨胀公式,灰度图像形态学膨胀与腐蚀此文都有介绍)
腐蚀操作对应的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”
其他的参数和腐蚀,膨胀是一样的
- op – 操作类型,今天我们只关注梯度,也就是第3个
Morphological gradient:
荷枪实弹
先介绍一个类
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; }
效果图:
我们再基于公式自己实现一下,修改的地方很少,主函数没有变化(不一样的地方有注释)
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; }
OpenCV2马拉松第16圈——边缘检测(形态学梯度),布布扣,bubuko.com