【opencv图像处理中的形态学操作】

腐蚀膨胀都是用一个卷积核对图像进行卷积处理,并取出结果中的极值作为结果,腐蚀是图片中黑的区域增加,膨胀是图片中高亮区域增加(消除这些小的黑斑)。

dilate使用像素邻域内的局部极大运算符来膨胀。

erode使用像素邻域内的局部极小运算符来腐蚀。

API:Mat getStructuringElement(int 内核形状,Size 内核尺寸,Point 锚点位置)

 注:内核形状可以取方形MORPH_RECT,十字形MORPH_CROSS,椭圆形MORPH_ELLIPSE

锚点位置默认值Point(-1,-1),取形状的中心

通过该API就可以获得相应的计算核,接下来计算膨胀的函数为

 API:void dilate(源图像,目标图像,膨胀核,锚点,int 迭代次数,int边界模式,int 边界为常数时边界值)


开运算与闭运算的结合经常用于二值图像的后处理阶段,整个过程消除了二值图像中的孤立目标,并且填补了目标区域的内部孔洞。但是这两种运算会破坏目标原本轮廓和形状,特别是对于小尺寸目标会变得十分明显。

开运算:开运算是一个先腐蚀,后膨胀的过程,用于在图像中消除小的物体,在纤细点处分离物体,在平滑化较大的物体的边界的同时不明显改变物体的体积.

闭运算:先膨胀后腐蚀的过程,能够用于消除物体中的小型黑洞

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

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

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

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

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

具体效果如:https://blog.csdn.net/steph_curry/article/details/78837633

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

API:void morpholgyEx(源,目标,int 形态学操作标志,mat 形态学操作内核,Point 锚点,int 迭代次数,int 边界模式,int 边界为常数时的边界值).

注:形态学操作标志的取值如下:MORPH_OPEN开运算  MORPH_CLOSE 闭运算 MORPH_GRENIENT 形态学梯度 MORPH_TOPHAT顶帽 MORPH_BLACKHAT黑帽 MORPH_ERODE腐蚀 MORPH_DILATE 膨胀

形态学操作内核就是前面膨胀腐蚀使用的内核

getStructuringElement
getStructuringElement函数会返回指定形状和尺寸的结构元素(内核矩阵)。

函数原型:

CV_EXPORTS_W Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));

参数说明:
shape:表示内核的形状

              MORPH_RECT, 矩形;
              MORPH_CROSS,交叉形;
              MORPH_ELLIPSE,椭圆形;

ksize:内核的尺寸;
anchor
 :锚点的位置。

morphologyEx
morphologyEx函数利用基本的膨胀和腐蚀技术,来执行更加高级形态学变换,如开闭运算,形态学梯度,“顶帽”、“黑帽”等等。

函数原型:
CV_EXPORTS_W void morphologyEx( InputArray src, OutputArray dst,

                                int op, InputArray kernel,
                                Point anchor = Point(-1,-1), int iterations = 1,
                                int borderType = BORDER_CONSTANT,
                                const Scalar& borderValue = morphologyDefaultBorderValue() );

参数说明:
src:输入图像,即源图像,填Mat类的对象即可。图像位深应该为以下五种之一:CV_8U, C 
        V_16U,CV_16S, CV_32F 或CV_64F;
dst:目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型;
op:形态学运算的类型,可以是如下之一的标识符:

        MORPH_OPEN – 开运算(Opening operation);
        MORPH_CLOSE – 闭运算(Closing operation);
        MORPH_GRADIENT -形态学梯度(Morphological gradient);
        MORPH_TOPHAT - “顶帽”(“Top hat”);
        MORPH_BLACKHAT - “黑帽”(“Black hat“);

kernel:InputArray类型的kernel,形态学运算的内核。若为NULL时,表示的是使用参考点
              位于中心3x3的核;
anchor
 :锚的位置,其有默认值(-1,-1),表示锚位于中心;
iterations
 :迭代使用函数的次数,默认值为1;
borderType
 :用于推断图像外部像素的某种边界模式。注意它有默认值BORDER_ CONSTA
                        NT;
borderValue
 :当边界为常数时的边界值,有默认值morphologyDefaultBorderValue()。

PS:自定义核流程
Mat element = getStructuringElement(element_shape, Size(3,3), Point(1, 1) );
morphologyEx(src, dst, MORPH_OPEN, element);


使用滑动条迭代一次进行处理:

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

Mat srcImage;
//开
const int g_openCoreMax = 100;
int g_nopenCoreValue=5;
void onopenCoreSizeTrackBar(int , void* );

//闭

const int g_closeCoreMax = 100;
int g_ncloseCoreValue=5;

void oncloseCoreSizeTrackBar(int, void* );



int main(int argc, char* argv[])
{
	srcImage = imread("123.jpg");
	namedWindow("src image", WINDOW_AUTOSIZE);
	
	
	namedWindow("open image", WINDOW_AUTOSIZE);
	createTrackbar("core size", "open image", &g_nopenCoreValue, g_openCoreMax, onopenCoreSizeTrackBar, 0);
	onopenCoreSizeTrackBar(0, 0);
   
	
	namedWindow("close image", WINDOW_AUTOSIZE);
	createTrackbar("core size", "close image", &g_ncloseCoreValue, g_closeCoreMax, oncloseCoreSizeTrackBar, 0);
	oncloseCoreSizeTrackBar(0, 0);

	imshow("src image", srcImage);

	
	
	
	waitKey(0);
	return 0;
}

void onopenCoreSizeTrackBar(int , void* )
{
	Mat openImage;
	if (g_nopenCoreValue == 0 )
	{
		imshow("open image", srcImage);
	}
	else
	{
		if (g_nopenCoreValue % 2 == 0)
			g_nopenCoreValue++;
		Mat core = getStructuringElement(MORPH_RECT, Size(g_nopenCoreValue, g_nopenCoreValue));
		morphologyEx(srcImage, openImage, MORPH_OPEN, core, Point(-1, -1), 1);
		imshow("open image", openImage);
	}
}

void oncloseCoreSizeTrackBar(int, void*)
{
	Mat closeImage;
	if (g_ncloseCoreValue ==  0)
	{
		imshow("close image", srcImage);
	}
	else
	{
		if (g_ncloseCoreValue % 2 == 0)
			g_ncloseCoreValue++;
		Mat core = getStructuringElement(MORPH_RECT, Size(g_ncloseCoreValue, g_ncloseCoreValue));
		morphologyEx(srcImage, closeImage, MORPH_CLOSE, core, Point(-1, -1),1);
		imshow("close image", closeImage);
	}
}

运行输出:

参考博客:https://blog.csdn.net/u012566751/article/details/54632150

猜你喜欢

转载自blog.csdn.net/qq_35054151/article/details/82849016