OpenCV 2 学习笔记(22): 腐蚀与膨胀
2013-09-26 15:14
465 查看
我们来看一下形态学算子,一般情况下形态学处理的都是二值图像。这样效果才明显。腐蚀和膨胀是最基本的形态学算子。在数学形态学中最基本的一个工具就是结构元素(structuring element)。结构元素就相当于我们在滤波中所涉及到的模板,也就是说它是一个给定像素的矩阵,这个矩阵可以是任意形状的,但是一般情况下都是正方形,圆形或者菱形的但是在结构元素中有一个中心点(也叫做anchor
point)。和模板中心一样,处理后的结果赋值给和这个中心点对齐的像素点。处理的过程也是基本相同。
结构元素和卷积模板的区别在于,膨胀是以集合运算为基础的,卷积是以算数运算为基础的。
膨胀:
1. 用结构元素,扫描图像的每一个像素
2. 用结构元素与其覆盖的二值图像做“与”操作
3. 如果都为0,结果图像的该像素为0。否则为1
也就是在结构元素覆盖范围下,只要有一个像素符和结构元素像素相同,那么中心点对应点就为1,否则为0,下面是一个例子,其中心点为(3, 3);
腐蚀:
1. 用结构元素,扫描图像的每一个像素
2. 用结构元素与其覆盖的二值图像做“与”操作
3. 如果都为1,结果图像的该像素为1。否则为0
也就是查找被处理图像中能不能找到和结构元素相同的矩阵。如果存在那么中心点所对应的点就为1,否则为0.,下面是一个例子,其中心点为(2,
2);
注意膨胀和腐蚀操作并不是互逆的操作,它们两个的先后运算得出了另外两种运算:开运算和闭运算·
1. 开操作是先腐蚀、后膨胀处理。
2. 闭操作是先膨胀、后腐蚀处理。
这个处理大家自己去做实验吧。
但是腐蚀和膨胀还是有很大的联系的:
1. 对于前景的腐蚀就等于对于对互补的背景的膨胀
2. 对于前景的膨胀就等于对于对互补背景的侵蚀
3. 对于图像的腐蚀两次相当于对于它的结构元素膨胀一次之后再腐蚀
4. 对于图像的膨胀两次相当于对于它的结构元素膨胀一次之后再膨胀
关于腐蚀和膨胀更详细的信息请看:
http://www.cnblogs.com/slysky/archive/2011/10/16/2214015.html
这个博客中的把腐蚀和膨胀的相关知识讲解的非常好。但是演示的膨胀腐蚀图我不敢苟同,是对是错,大家自己辨别吧,如果我的演示例子错了,麻烦告诉一声。
上面我们说了一下腐蚀和膨胀的基本原理,下面我们看看它在opencv中是怎么实现的,其源代码在:opencv根目录\
modules\imgproc\src\morph.cpp中,感兴趣的人可以把代码拷出来,然后单步执行研究一下:
下面我们看一下腐蚀和膨胀在opencv中的怎么应用的:
C++: void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1),
int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
C++: void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1),
int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
src – input image; the number of channels can be arbitrary, but the depth should be one of CV_8U, CV_16U, CV_16S, CV_32F‘ or ‘‘CV_64F.
dst – output image of the same size and type as src.
element – structuring element used for erosion; if element=Mat() , a 3 x 3 rectangular structuring element is used.
anchor – position of the anchor within the element; default value (-1, -1) means that the anchor is at the element center.
iterations – number of times erosion is applied.
borderType – pixel extrapolation method (see borderInterpolate() for details).
borderValue – border value in case of a constant border (see createMorphologyFilter() for details).
对于图像腐蚀与膨胀后的结果:
原图
腐蚀后的结果
膨胀后的结果
注意:腐蚀和膨胀是对于非零像素而言的,明白这一点是看懂上图的前提
这个例子中我们的结构元素为空,从源代码中看出,如果它为空,系统会为我们自动创建。我们也可以自己手动创建一个结构元素,就使用cv::Mat element(; ; ;);。
附上源码,上面的矩阵腐蚀与膨胀:
下面的图像膨胀与腐蚀:
point)。和模板中心一样,处理后的结果赋值给和这个中心点对齐的像素点。处理的过程也是基本相同。
结构元素和卷积模板的区别在于,膨胀是以集合运算为基础的,卷积是以算数运算为基础的。
膨胀:
1. 用结构元素,扫描图像的每一个像素
2. 用结构元素与其覆盖的二值图像做“与”操作
3. 如果都为0,结果图像的该像素为0。否则为1
也就是在结构元素覆盖范围下,只要有一个像素符和结构元素像素相同,那么中心点对应点就为1,否则为0,下面是一个例子,其中心点为(3, 3);
腐蚀:
1. 用结构元素,扫描图像的每一个像素
2. 用结构元素与其覆盖的二值图像做“与”操作
3. 如果都为1,结果图像的该像素为1。否则为0
也就是查找被处理图像中能不能找到和结构元素相同的矩阵。如果存在那么中心点所对应的点就为1,否则为0.,下面是一个例子,其中心点为(2,
2);
注意膨胀和腐蚀操作并不是互逆的操作,它们两个的先后运算得出了另外两种运算:开运算和闭运算·
1. 开操作是先腐蚀、后膨胀处理。
2. 闭操作是先膨胀、后腐蚀处理。
这个处理大家自己去做实验吧。
但是腐蚀和膨胀还是有很大的联系的:
1. 对于前景的腐蚀就等于对于对互补的背景的膨胀
2. 对于前景的膨胀就等于对于对互补背景的侵蚀
3. 对于图像的腐蚀两次相当于对于它的结构元素膨胀一次之后再腐蚀
4. 对于图像的膨胀两次相当于对于它的结构元素膨胀一次之后再膨胀
关于腐蚀和膨胀更详细的信息请看:
http://www.cnblogs.com/slysky/archive/2011/10/16/2214015.html
这个博客中的把腐蚀和膨胀的相关知识讲解的非常好。但是演示的膨胀腐蚀图我不敢苟同,是对是错,大家自己辨别吧,如果我的演示例子错了,麻烦告诉一声。
上面我们说了一下腐蚀和膨胀的基本原理,下面我们看看它在opencv中是怎么实现的,其源代码在:opencv根目录\
modules\imgproc\src\morph.cpp中,感兴趣的人可以把代码拷出来,然后单步执行研究一下:
void cv::erode( InputArray src, OutputArray dst, InputArray kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { morphOp( MORPH_ERODE, src, dst, kernel, anchor, iterations, borderType, borderValue ); } void cv::dilate( InputArray src, OutputArray dst, InputArray kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { morphOp( MORPH_DILATE, src, dst, kernel, anchor, iterations, borderType, borderValue ); }
static void morphOp( int op, InputArray _src, OutputArray _dst, InputArray _kernel, Point anchor, int iterations, int borderType, const Scalar& borderValue ) { Mat src = _src.getMat(), kernel = _kernel.getMat(); Size ksize = kernel.data ? kernel.size() : Size(3,3); anchor = normalizeAnchor(anchor, ksize); CV_Assert( anchor.inside(Rect(0, 0, ksize.width, ksize.height)) ); _dst.create( src.size(), src.type() ); Mat dst = _dst.getMat(); if( iterations == 0 || kernel.rows*kernel.cols == 1 ) { src.copyTo(dst); return; } if( !kernel.data ) { kernel = getStructuringElement(MORPH_RECT, Size(1+iterations*2,1+iterations*2)); anchor = Point(iterations, iterations); iterations = 1; } else if( iterations > 1 && countNonZero(kernel) == kernel.rows*kernel.cols ) { anchor = Point(anchor.x*iterations, anchor.y*iterations); kernel = getStructuringElement(MORPH_RECT, Size(ksize.width + (iterations-1)*(ksize.width-1), ksize.height + (iterations-1)*(ksize.height-1)), anchor); iterations = 1; } int nStripes = 1; #if defined HAVE_TBB && defined HAVE_TEGRA_OPTIMIZATION if (src.data != dst.data && iterations == 1 && //NOTE: threads are not used for inplace processing (borderType & BORDER_ISOLATED) == 0 && //TODO: check border types src.rows >= 64 ) //NOTE: just heuristics nStripes = 4; #endif parallel_for(BlockedRange(0, nStripes), MorphologyRunner(src, dst, nStripes, iterations, op, kernel, anchor, borderType, borderType, borderValue)); //Ptr<FilterEngine> f = createMorphologyFilter(op, src.type(), // kernel, anchor, borderType, borderType, borderValue ); //f->apply( src, dst ); //for( int i = 1; i < iterations; i++ ) // f->apply( dst, dst ); }
下面我们看一下腐蚀和膨胀在opencv中的怎么应用的:
C++: void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1),
int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
C++: void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1),
int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue() )
src – input image; the number of channels can be arbitrary, but the depth should be one of CV_8U, CV_16U, CV_16S, CV_32F‘ or ‘‘CV_64F.
dst – output image of the same size and type as src.
element – structuring element used for erosion; if element=Mat() , a 3 x 3 rectangular structuring element is used.
anchor – position of the anchor within the element; default value (-1, -1) means that the anchor is at the element center.
iterations – number of times erosion is applied.
borderType – pixel extrapolation method (see borderInterpolate() for details).
borderValue – border value in case of a constant border (see createMorphologyFilter() for details).
对于图像腐蚀与膨胀后的结果:
原图
腐蚀后的结果
膨胀后的结果
注意:腐蚀和膨胀是对于非零像素而言的,明白这一点是看懂上图的前提
这个例子中我们的结构元素为空,从源代码中看出,如果它为空,系统会为我们自动创建。我们也可以自己手动创建一个结构元素,就使用cv::Mat element(; ; ;);。
附上源码,上面的矩阵腐蚀与膨胀:
#include<opencv2\core\core.hpp> #include<opencv2\highgui\highgui.hpp> #include<opencv2\imgproc\imgproc.hpp> #include<iostream> using namespace std; void main() { //膨胀: cv::Mat mat1(6,10, CV_8U, cv::Scalar(0)); cv::Mat erode(5,5,CV_8U, cv::Scalar(1)); cv::Mat mat2;; mat1.at<uchar>(3,2) = mat1.at<uchar>(3,6) = mat1.at<uchar>(3,7 ) = 1; erode.col(0) = 0; erode.col(4) = 0; erode.row(0) = 0; erode.row(4) = 0; cout<<"Mat: "<<endl; cout<<mat1<<endl; cout<<endl; cout<<"StrElement: "<<endl; cout<<erode<<endl; cout<<endl; cv::dilate(mat1, mat2, erode, cv::Point(3,3)); cout<<"DilateMat: "<<endl; cout<<mat2<<endl; cout<<endl; //腐蚀: //cv::Mat mat1(6,6, CV_8U, cv::Scalar(1)); //cv::Mat erode(4,4,CV_8U, cv::Scalar(0)); //cv::Mat mat2;; //mat1.col(0) = 0; //mat1.col(5) = 0; //mat1.row(0) = 0; //mat1.row(5) = 0; //mat1.at<uchar>(1,4) = 0; //erode.at<uchar>(2,1) = erode.at<uchar>(2,2) = erode.at<uchar>(1,2 ) = 1; //cout<<"Mat: "<<endl; //cout<<mat1<<endl; //cout<<endl; //cout<<"StrElement: "<<endl; //cout<<erode<<endl; //cout<<endl; //cv::erode(mat1, mat2, erode, cv::Point(2,2)); //cout<<"ErodeMat: "<<endl; //cout<<mat2<<endl; //cout<<endl; system("pause"); }
下面的图像膨胀与腐蚀:
#include<opencv2\core\core.hpp> #include<opencv2\highgui\highgui.hpp> #include<opencv2\imgproc\imgproc.hpp> void main() { cv::Mat img, cvtcolor,result; img = cv::imread("E:/StandardImage/tower.jpg"); cv::cvtColor(img, cvtcolor, CV_RGB2GRAY); if(!img.data) return; cv::imshow("img", img); cv::imshow("cvtcolor", cvtcolor); cv::threshold(cvtcolor, result, 100, 255, CV_THRESH_BINARY); cv::imshow("result", result); cv::Mat eroded; cv::erode(result, eroded, cv::Mat()); cv::imshow("erode", eroded); cv::Mat dilate; cv::dilate(result, dilate, cv::Mat()); cv::imshow("dilate", dilate); cv::waitKey(); }
相关文章推荐
- OpenCV学习笔记——腐蚀与膨胀
- Opencv学习笔记-膨胀和腐蚀
- OpenCV学习笔记:二值图像的腐蚀和膨胀的原理
- openCv学习笔记(五)-数学形态学2(灰度级膨胀和腐蚀及c语言实现)
- opencv学习笔记(十一)——图像腐蚀和膨胀混合运用练习
- OpenCV学习笔记(4):膨胀,腐蚀,开闭操作(argc,argv)
- 【OpenCV学习笔记】2.3图像的腐蚀、膨胀、模糊、边缘检测
- OpenCV学习笔记(二):腐蚀与膨胀
- openCv学习笔记(四)-数学形态学1(二值图像的膨胀、腐蚀、开运算和闭运算)
- OpenCV学习笔记-形态学操作-腐蚀膨胀-开闭运算
- opencv学习笔记第五章:基于形态学运算的图像变换(1)形态学运算进行腐蚀和膨胀
- Opencv学习笔记:膨胀与腐蚀
- Opencv学习笔记(七):腐蚀,膨胀,开操作,闭操作及其他相关的形态学操作
- OpenCV学习笔记(六) 滤波器 形态学操作(腐蚀、膨胀等)
- opencv学习笔记(3)----腐蚀与膨胀
- 【OpenCV学习笔记】十七、膨胀与腐蚀(一)
- opencv 2.x学习笔记(十五)腐蚀和膨胀
- Opencv 学习笔记之膨胀/腐蚀综合实例
- 学习【OpenCV入门教程之十】 形态学图像处理(一):膨胀与腐蚀----思维导图笔记
- opencv学习笔记(十二)腐蚀和膨胀