c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)

图像形态学中的几个基本操作:腐蚀、膨胀、开操作、闭操作

膨胀

  • 该操作包括将图像与某些内核进行卷积,其可以具有任何形状或尺寸,通常为正方形或圆形。
  • 内核具有定义的锚点,通常是内核的中心。
  • 当内核在图像上扫描时,我们计算由B重叠的最大像素值,并用该最大值替换锚点位置中的图像像素。您可以推断,这种最大化的操作会使图像中的亮区“增长”(因此称为膨胀)。应用扩张我们可以得到: 字母(明亮)扩大了,背景的黑色地区缩小了。
    c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第1张图片
    膨胀使物体变大。其实就是选择滑动窗口中像素值最大的点(局部最大值)公式表示:

dst(x,y)=dilate(src(x,y))=max(x′,y′)src(x+x′,y+y′)

腐蚀

  • 这个操作是扩张的姊妹。它计算给定内核区域的局部最小值。
  • 当内核在图像上扫描时,我们计算由重叠的最小像素值,并用该最小值替换锚点下的图像像素。
  • 对于扩张的例子,我们可以将侵蚀算子应用于原始图像(如上所示)。您可以在下面的结果中看到,图像的明亮区域(字母)变得更小,而黑暗区域(背景)变得更大。
    c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第2张图片

腐蚀使物体变小。其实就是选择滑动窗口中像素值最小的点(局部最小值)公式表示:

dst(x,y)=erode(src(x,y))=min(x′,y′)src(x+x′,y+y′)

开操作

  • 它是通过图像的腐蚀获得的,随后是膨胀。先腐蚀后膨胀的操作称之为开操作。它具有消除细小物体,在纤细处分离物体和平滑较大物体边界的作用。

dst = open(src,element) = dilate(erode(src,element))

  • 用于去除小物体(假设物品是亮色,前景色是黑色),被用来抹除比背景亮的噪点。
  • 例如,请查看下面的示例。左侧的图像是原始图像,右侧的图像是应用打开转换后的结果。我们可以观察到,信中角落的小空间往往会消失。
    在这里插入图片描述

为了清楚起见,我们7x7在相同的原始图像上执行了开操作(矩形结构元素),但是反转,例如白色的对象现在是字母。
c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第3张图片
开操作 = 腐蚀 + 膨胀 消除部分高亮区域(二值化中的白色区域)

闭操作

  • 它是通过图像的膨胀,然后是腐蚀获得的。先膨胀后腐蚀的操作称之为闭操作。它具有填充物体内细小空洞,连接邻近物体和平滑边界的作用。用来抹除比背景暗的噪点。

dst = close(src,element) = erode(dilate(src,element))

  • 有用的是去除小孔(暗区)。
    c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第4张图片
    在倒置图像上,我们执行了闭操作(7x7矩形结构元素):
    c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第5张图片
    闭操作 = 膨胀 + 腐蚀 消除高亮区域的内部黑洞(二值化中的黑色区域)

先开后闭可以有效除去噪声

形态梯度

  • 膨胀以后的图像减去腐蚀以后的图像,可以用来提取图片中的边缘。

dst(x,y)=morph_grad(src,element)=dilate(src,element)−erode(src,element)

  • 找到对象的轮廓是有用的,如下所示:
    c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第6张图片

顶帽

  • 原图减去开运算以后的图像,取出高亮的小目标前景(适用于原始图像背景是暗的,前景是亮的,把明亮的前景突出出来)

dst(x,y)=top_hat(src,element)=src−open(src,element))

c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第7张图片

黑帽

  • 闭运算以后的图像减去原图,取出非高亮的小目标前景。(适用于原始图像背景是亮的,前景是暗的,把暗色的前景突出出来)

dst(x,y)=black_hat(src,element)=close(src,element)−src

c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第8张图片
先顶帽后黑猫可以增强对比度

C++ Code API

膨胀、腐蚀、其余形态学操作API

/**
  *获取,卷积核
  *shape 卷积核形状
		MORPH_RECT  矩形    
		MORPH_CROSS  十字形   
		MORPH_ELLIPSE   椭圆形
  *ksize 大小
  *anchor 锚点位置
  **/
Mat getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1));
      
/**
  *膨胀
  *src:源图
  *dst:结果 
  *kernel:运算核 
  *anchor:锚点位置
  *iterations:迭代次数
  *borderType:边界扩充类型
  *borderValue:边界扩充值
  **/ 
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 源图
  *dst 结果
  *kernel:运算核    
  *anchor 锚点位置
  *iterations 迭代次数
  *borderType:边界扩充类型
  *borderValue:边界扩充值
  **/ 
void erode( InputArray src, OutputArray dst, InputArray kernel,
                          Point anchor = Point(-1,-1), int iterations = 1,
                          int borderType = BORDER_CONSTANT,
                          const Scalar& borderValue = morphologyDefaultBorderValue() );

 /**
  *形态学操作
  *src 源图
  *dst 结果
  *op 运算类型
		MORPH_CLOSE  闭
		MORPH_OPEN   开
		MORPH_GRADIENT   梯度
		MORPH_TOPHAT      顶帽
		MORPH_BLACKHAT    黑帽
		MORPH_DILATE      膨胀
		MORPH_ERODE       腐蚀
  *kernel:运算核    
  *anchor 锚点位置
  *iterations 迭代次数
  *borderType:边界扩充类型
  *borderValue:边界扩充值
  **/ 
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() );


实操代码

lena图片
c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第9张图片
测试代码

#include 
#include 

#define WINDOWNAME "【效果图】"


int g_nStructElementSize = 3;
int g_nTrackbarNumber = 0;     
int anchor = -1;
int model = 0;
cv::Mat g_srcImage, g_dstImage;

std::map<int, int> SizeShape;
std::map<int, int> ProcessModel;
std::map<int, std::string> ModelName;

void Process()
{
	//MORPH_RECT  矩形    
	//MORPH_CROSS  十字形   
	//MORPH_ELLIPSE   椭圆形
	SizeShape[0] = cv::MORPH_RECT;
	SizeShape[1] = cv::MORPH_CROSS;
	SizeShape[2] = cv::MORPH_ELLIPSE;

	//cv::MORPH_CLOSE  闭
	//cv::MORPH_OPEN   开
	//cv::MORPH_GRADIENT   梯度
	//cv::MORPH_TOPHAT      顶帽
	//cv::MORPH_BLACKHAT    黑帽
	//cv::MORPH_DILATE      膨胀
	//cv::MORPH_ERODE       腐蚀
	ProcessModel[0] = cv::MORPH_CLOSE;
	ProcessModel[1] = cv::MORPH_OPEN;
	ProcessModel[2] = cv::MORPH_GRADIENT;
	ProcessModel[3] = cv::MORPH_TOPHAT;
	ProcessModel[4] = cv::MORPH_BLACKHAT;
	ProcessModel[5] = cv::MORPH_DILATE;
	ProcessModel[6] = cv::MORPH_ERODE;

	ModelName[0] = "MORPH_CLOSE";
	ModelName[1] = "MORPH_OPEN";
	ModelName[2] = "MORPH_GRADIENT";
	ModelName[3] = "MORPH_TOPHAT";
	ModelName[4] = "MORPH_BLACKHAT";
	ModelName[5] = "MORPH_DILATE";
	ModelName[6] = "MORPH_ERODE";
	cv::Mat element;

	if (anchor >= (2 * g_nStructElementSize))
	{
		anchor = 2 * g_nStructElementSize;
	}

	element = cv::getStructuringElement(SizeShape[model], cv::Size(2 * g_nStructElementSize + 1, 2 * g_nStructElementSize + 1),cv::Point(anchor, anchor));
	cv::morphologyEx(g_srcImage, g_dstImage, ProcessModel[g_nTrackbarNumber], element);

	cv::putText(g_dstImage, ModelName[g_nTrackbarNumber],cv::Point(0, 40), cv::FONT_HERSHEY_COMPLEX, 0.8, cv::Scalar(25,25, 255), 1,  1);
	cv::imshow(WINDOWNAME, g_dstImage);
}

void on_ElementSizeChange(int, void*)
{
	Process();
}

void on_TrackbarNumChange(int, void*)
{
	Process();
}

void on_AnchorChange(int, void*)
{
	Process();
}

void on_ModelChange(int, void*)
{
	Process();
}

int main()
{
	std::string filename = "Standard_image/lena.jpg";
	g_srcImage = cv::imread(filename, cv::IMREAD_GRAYSCALE);
	
	//显示原始图
	const char* pName1 = "图";
	cv::namedWindow(pName1);
	cv::imshow(pName1, g_srcImage);

	cv::namedWindow(WINDOWNAME);
	cv::createTrackbar("处理方法", WINDOWNAME, &g_nTrackbarNumber, 6, on_TrackbarNumChange);
	cv::createTrackbar("锚点位置", WINDOWNAME, &anchor, 10, on_AnchorChange);
	cv::createTrackbar("内核形状", WINDOWNAME, &model, 2, on_ModelChange);
	cv::createTrackbar("内核尺寸", WINDOWNAME, &g_nStructElementSize, 21, on_ElementSizeChange);

	cv::waitKey(0);

}

闭操作效果
c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第10张图片

开操作效果
c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第11张图片

形态梯度效果
c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第12张图片
顶帽效果
c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第13张图片
黑帽效果
c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第14张图片
膨胀效果
c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第15张图片

腐蚀效果
c++ opencv4.5.5 学习笔记(四)形态学操作(膨胀、腐蚀、开操作、闭操作、形态梯度、顶帽以及黑帽)_第16张图片

最后感谢大佬的分享:
https://blog.csdn.net/fan1102958151/article/details/106996717/

你可能感兴趣的:(opencv,学习笔记,opencv,计算机视觉,图像处理)