欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

OpenCV中形态学操作:膨胀、腐蚀、开闭运算

程序员文章站 2022-07-14 11:50:41
...

1、基本概念

图像形态学即数学形态学(Mathematical morphology)是一门建立在格伦和拓扑学基础上的图像分析学科,是数学形态学图像处理的基本理论;常见图像形态学运算:腐蚀,膨胀,开运算,闭运算,骨架抽取,极线腐蚀,击中击不中变换,顶帽变换,颗粒分析,流域变换,形态学梯度等。

腐蚀和膨胀是最基本的形态学运算。

腐蚀和膨胀是针对白色部分(高亮部分)而言的。

膨胀(dilate)是对图像高亮部分进行“领域扩张”,领域扩张,效果图拥有比原图更大的高亮区域;

腐蚀(erode)是原图中的高亮区域被蚕食,领域缩减,效果图拥有比原图更小的高亮区域。

开运算:先腐蚀再膨胀,用来消除小物体

闭运算:先膨胀再腐蚀,用于排除小型黑洞

形态学梯度:就是膨胀图与俯视图之差,用于保留物体的边缘轮廓。

顶帽:原图像与开运算图之差,用于分离比邻近点亮一些的斑块。

黑帽:闭运算与原图像之差,用于分离比邻近点暗一些的斑块。

opencv里有一个很好的函数getStructuringElement,我们只要往这个函数传相应的处理参数,就可以进行相应的操作了,使用起来非常方便。

getStructuringElement():返回指定形状和尺寸的结构元素;

格式:
getStructuringElement(int shape,Size ksize,Point anchor = Point(-1,-1));

参数:
shape:表核的形状,矩形MORPH_RECT;交叉形MORPH_CROSS;椭圆形MORPH_ELLIPSE;
ksize:核尺寸大小;
anchor:锚点的位置,锚点只影响形态学运算结果的偏移;

下面列举一下相应的操作宏定义。

OpenCV中形态学操作:膨胀、腐蚀、开闭运算

2、膨胀(dilate)

膨胀就是求局部最大值的操作,从图像直观看来,就是将图像光亮部分放大,黑暗部分缩小。

OpenCV的中膨胀函数为dilate()。

dilate(
InputArray src,//输入
OutputArray dst,//输出
InputArray kernel,//核大小
Point anchor = Point(-1,-1),//锚位置,( - 1,-1)为中心
int iterations = 1,//迭代次数
int borderType = BORDER_CONSTANT,//图像边界像素模式
const Scalar&borderValue = morphologyDefaultBorderValue()//边界值
)
实现方法:
1、定义一个卷积核B,核可以是任何的形状和大小,且拥有一个单独定义出来的参考点 - 锚点(anchorpoint);
通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;
2、将核乙与图像甲进行卷积,计算核乙覆盖区域的像素点最大值;
3、将这个最大值赋值给参考点指定的像素;
因此,图像中的高亮区域逐渐增长。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
	cout << img.size() << endl;
	imshow("原图",img);

	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	dilate(img, dst, element);
	imshow("膨胀操作", dst);
	waitKey();
	return 0;
}

OpenCV中形态学操作:膨胀、腐蚀、开闭运算

3、腐蚀(erode)

腐蚀就是与膨胀相反,求局部最小值,从图像直观看来,就是将图像光亮部分缩小,黑暗部分放大。

OpenCV的中腐蚀函数为erode()。

erode(
InputArray src,//输入
OutputArray dst,//输出
InputArray kernel,//核大小
Point anchor = Point(-1,-1),//锚位置,( - 1,-1)为中心
int iterations = 1,//迭代次数
int borderType = BORDER_CONSTANT,//图像边界像素模式
const Scalar&borderValue = morphologyDefaultBorderValue()//边界值
)
实现方法:
1、定义一个卷积核B,核可以是任何的形状和大小,且拥有一个单独定义出来的参考点 - 锚点(anchorpoint);
通常和为带参考点的正方形或者圆盘,可将核称为模板或掩膜;
2、将核乙与图像甲进行卷积,计算核乙覆盖区域的像素点最小值;
3、将这个最小值赋值给参考点指定的像素;
因此,图像中的高亮区域逐渐减小。
#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
	cout << img.size() << endl;
	imshow("原图",img);

	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	//腐蚀操作
	erode(img, dst, element);
	imshow("腐蚀操作", dst);
	waitKey();
	return 0;
}

OpenCV中形态学操作:膨胀、腐蚀、开闭运算

4、形态学开运算

开操作(先腐蚀后膨胀)可以平滑物体轮廓,断开狭窄的间断和消除细小的突出物。

它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
	cout << img.size() << endl;
	imshow("原图",img);

	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	//形态学开操作
#if 1
	morphologyEx(img, dst, MORPH_OPEN, element);
#else
	erode(img, dst, element);
	dilate(dst, dst, element);
#endif
	imshow("形态学开操作", dst);
	waitKey();
	return 0;
}

OpenCV中形态学操作:膨胀、腐蚀、开闭运算

注:形态学操作可使用高级函数morphologyEx。

//形态学操作(开、闭、形态学梯度、顶帽、黑帽)
	morphologyEx(src, dst, MORPH_BLACKHAT, kernel);
	//第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F。
	//第二个参数,OutputArray类型的dst,即目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
	//第三个参数,int类型的op,表示形态学运算的类型,可以是如下之一的标识符:
	//MORPH_OPEN – 开运算(Opening operation):先腐蚀后膨胀,去掉小对象
	//MORPH_CLOSE – 闭运算(Closing operation):先膨胀后腐蚀,可以填充一些小的空洞(fill hole)
	//MORPH_GRADIENT - 形态学梯度(Morphological gradient):膨胀后的图减去腐蚀后的图(设置恰当的参数可以得到目标的大致边缘)
	//MORPH_TOPHAT - “顶帽”(“Top hat”):原图像与开操作之间的差值图像(可以用来观察开运算除去了哪些小目标)
	//MORPH_BLACKHAT - “黑帽”(“Black hat“):闭操作图像与源图像的差值图像(可以观察闭运算的效果)
	//第四个参数:结构元素即形态学运算的内核
	//第五个参数,Point类型的anchor,锚的位置,其有默认值( - 1, - 1),表示锚位于中心。
	//第六个参数,int类型的iterations,迭代使用函数的次数,默认值为1。
	//第七个参数,int类型的borderType,用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTANT。
	//第八个参数,const Scalar&类型的borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般我们不用去管他。需要用到它时,可以看官方文档

5、形态学闭运算

闭操作(先膨胀后腐蚀)可以消弭狭窄的间断,消除小的孔洞。先膨胀后腐蚀的操作称之为闭操作。

它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。

#include<iostream>
#include<opencv2\opencv.hpp>
#include<opencv2\highgui\highgui.hpp>
using namespace cv;
using namespace std;

int main()
{
	Mat img = imread("C:\\Users\\cf\\Desktop\\测试数据\\test00.jpg");
	cout << img.size() << endl;
	imshow("原图",img);

	Mat dst;
	//获取自定义核
	Mat element = getStructuringElement(MORPH_RECT, Size(10, 10));
	//形态学闭操作
#if 1
	morphologyEx(img, dst, MORPH_CLOSE, element);
#else
	dilate(dst, dst, element);
	erode(img, dst, element);
#endif
	imshow("形态学闭操作", dst);
	waitKey();
	return 0;
}

OpenCV中形态学操作:膨胀、腐蚀、开闭运算

相关标签: opencv