1. 函数

1.1 getStructuringElement

OpenCV官方文档getStructuringElement链接

  • getStructuringElement 是为了给形态学操作算子返回指定大小和形状的结构元素。
  • 当然你也可以自己构造一个任意的二进制掩码,并将其用作形态学处理函数的结构元素。
	Mat getStructuringElement(
		int shape,  //形状
		Size ksize, //尺寸
		Point anchor = Point(-1, -1) //锚点
		);

参数 shape 是枚举变量 enum cv::MorphShapes

在这里插入图片描述

1.2 morphologyEx

OpenCV官方文档morphologyEx链接

  • 这其实是一个非常强大的函数,它可以通过调整参数 op 完成八种操作:腐蚀、膨胀、开运算、闭运算、顶帽、黑帽、梯度、击中击不中。
	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()
		);
  • 参数 op 是枚举变量 enum cv::MorphTypes

    在这里插入图片描述
  • 对于腐蚀和膨胀,OpenCV还有专门的函数 erode  dialte,它们和 morphologyEx 使用 MORPH_ERODE  MORPH_DILATE 是完全相同的。
  • 所有操作都支持就地调用。对于多通道图像,每个通道是被独立处理的。
  • borderType :不支持BORDER_WRAP
  • 《学习OpenCV3》有这样的描述:尽管开和闭操作的效果与腐蚀相近,但这些新操作在保持连通域的精度上更加可靠。

1.3 erode

	void erode(
		InputArray src, 
		OutputArray dst, 
		InputArray kernel,
		Point anchor = Point(-1, -1), 
		int iterations = 1,
		int borderType = BORDER_CONSTANT,
		const Scalar& borderValue = morphologyDefaultBorderValue()
		);

1.4 dilate

	void dilate(
		InputArray src, 
		OutputArray dst, 
		InputArray kernel,
		Point anchor = Point(-1, -1),
		int iterations = 1,
		int borderType = BORDER_CONSTANT,
		const Scalar& borderValue = morphologyDefaultBorderValue()
		);

2. 例程

2.1 图像处理效果

原图

在这里插入图片描述

二值化图像

在这里插入图片描述

对二值化图像进行腐蚀、膨胀、开操作、闭操作

  • 开操作和闭操作实际上就是腐蚀和膨胀的简单组合。
  • 开操作是先腐蚀后膨胀,常用于对二值图像中的区域进行计数。
  • 闭操作是先膨胀后腐蚀,作用于复杂连通分支算法中减少无用或噪声驱动的片段。对于连通分支,通常先进行腐蚀或闭操作消除噪声,然后通过开操作连接相互靠近的大型区域。
  • 尽管开和闭操作的效果与腐蚀相近,但这些新操作在保持连通域的精度上更加可靠。
    在这里插入图片描述

梯度图

  • 形态学梯度 是 膨胀操作的结果(扩张亮域)减 腐蚀操作的结果(缩减亮域) ,这就是边缘。
  • 对于灰度图,其结果就是计算明暗变换的趋势。形态学梯度通常用于显示明亮区域的边界,然后便可以将他们看做目标或者目标的部分。用扩张的图像减去了收缩的图像,如此一来就找出了完整的边界。这与计算梯度不同,它不会关注某一个物体的周围。
    在这里插入图片描述

顶帽和黑帽

  • 这两种操作分别用于显示与其邻域相比更亮或更暗的部分。当试图根据物体的亮度变化分离依附于物体的某些部分时,就会用到这些方法。
  • 顶帽作用源图像减去其开操作后的图像。开操作的效果是放大裂缝和局部小洞。因此用源图像减去开操作后的图像得到了比源图像更亮的环绕部分。
  • 黑帽操作显示的是比源图像更暗的环绕部分。
  • 在这里插入图片描述

击中击不中

在这里插入图片描述

2.2 代码

#include "stdafx.h"
#include <opencv.hpp>
using namespace cv;
int main()
{
	Mat m_SrcImg = imread("./1.jpg", IMREAD_GRAYSCALE);
	imshow("原图", m_SrcImg);

	//阈值化操作
	Mat m_SrcImg2;
	threshold(m_SrcImg, m_SrcImg2, 100, 255, THRESH_BINARY_INV);
	imshow("原图2", m_SrcImg2);

	Mat m_DstImg;
	Mat elementRect = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
	Mat elementEllipse = getStructuringElement(MORPH_ELLIPSE, Size(5, 5), Point(-1, -1));
	int m_nIterations = 1;

	//腐蚀
	morphologyEx(m_SrcImg2, m_DstImg, MORPH_ERODE, elementEllipse, Point(-1, -1), m_nIterations);
	imshow("MORPH_ERODE", m_DstImg);

	//膨胀
	morphologyEx(m_SrcImg2, m_DstImg, MORPH_DILATE, elementEllipse, Point(-1, -1), m_nIterations);
	imshow("MORPH_DILATE", m_DstImg);

	//开操作
	morphologyEx(m_SrcImg2, m_DstImg, MORPH_OPEN, elementEllipse, Point(-1, -1), m_nIterations);
	imshow("MORPH_OPEN", m_DstImg);

	//闭操作 
	morphologyEx(m_SrcImg2, m_DstImg, MORPH_CLOSE, elementEllipse, Point(-1, -1), m_nIterations);
	imshow("MORPH_CLOSE", m_DstImg);

	//梯度 如果是空的Mat,则会被默认为是3×3的核
	morphologyEx(m_SrcImg2, m_DstImg, MORPH_GRADIENT, Mat(), Point(-1, -1), m_nIterations);
	imshow("MORPH_GRADIENT", m_DstImg);

	//顶帽 这里我使用了一个Mat的构造函数,自行创建了掩码,同样也可以作为形态学操作函数的结构化元素来使用	
	morphologyEx(m_SrcImg, m_DstImg, MORPH_TOPHAT, Mat(Size(11, 11), m_SrcImg.type()), Point(-1, -1), m_nIterations);
	imshow("MORPH_TOPHAT", m_DstImg);

	//黑帽 
	morphologyEx(m_SrcImg, m_DstImg, MORPH_BLACKHAT, Mat(Size(11, 11), m_SrcImg.type()), Point(-1, -1), m_nIterations);
	imshow("MORPH_BLACKHAT", m_DstImg);

	//击中击不中
	morphologyEx(m_SrcImg2, m_DstImg, MORPH_HITMISS, elementEllipse, Point(-1, -1), 1);
	imshow("MORPH_HITMISS", m_DstImg);

	waitKey(0);
    return 0;
}


转载自:https://liuhui.blog.csdn.net/article/details/121746410