OpenCV(八)形态学操作3--形态学梯度实现轮廓分析(基本梯度、内部梯度、外部梯度、方向梯度X(Y))

本文详细介绍了形态学梯度的四种类型:基本梯度、内部梯度、外部梯度和方向梯度。通过膨胀和腐蚀操作,结合OpenCV库展示了如何在C++中实现这些梯度,并提供了相应的代码示例。形态学梯度主要用于突出图像边缘,适用于轮廓分析和二值图像处理。
摘要由CSDN通过智能技术生成

目录

 形态学梯度概述

一、基本梯度

1、原理 

2、代码

3、效果

二、内部梯度

1、原理 

2、代码

 3、效果

三、外部梯度

1、原理 

2、代码

3、效果

四、方向梯度

1、原理

2、二值化图像(黑白)

 3、求X(Y)轴方向梯度

X轴: 

Y轴:

总代码

参考资料:


 形态学梯度概述

作用:保留物体的边缘轮廓,便于轮廓分析突出高亮区域

形态学梯度定义:        G = I⊕S − I!S

(其中G为输出图像,I为输入图像,S为卷积核函数。为膨胀运算,!为腐蚀运算。

  • 形态学梯度操作的输出图像像素值是在对应结构元素而非局部过渡区域所定义的领域中灰度级强度变化的最大值。
  • 对二值图像进行形态学操作可以将团块(blob)的边缘突出出来,可以用形态学梯度来保留物体的边缘轮廓

一、基本梯度

1、原理 

基本梯度 = 膨胀图像 - 腐蚀图像

基本梯度是用膨胀后的图像减去腐蚀后的图像得到差值图像,称为梯度图像也是OpenCV中支持的计算形态学梯度的方法,而此方法得到梯度有被称为基本梯度。

2、代码

//基本梯度(膨胀-腐蚀)
void BasicGrad()
{
	//创建卷积核(结构元)
	Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));
	//创建新图像(膨胀、腐蚀)
	Mat dilate_output, erode_ouput;
	dilate(img, dilate_output, kernel, Point(-1, -1));	//膨胀
	erode(img, erode_ouput, kernel, Point(-1, -1));		//腐蚀
	//计算基本梯度
	subtract(dilate_output, erode_ouput, dst, Mat());	//膨胀-腐蚀
	//			膨胀					腐蚀				   结果

	imshow("基本梯度", dst);
}

3、效果

二、内部梯度

1、原理 

内部梯度 = 原图像 - 腐蚀图像

内部梯度是用原图像减去腐蚀之后的图像得到差值图像。

2、代码

//内部梯度(原图-腐蚀)
void InternalGrad()
{
	//创建卷积核(结构元)
	Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));
	//创建新图(腐蚀)
	Mat erode_ouput;
	erode(img, erode_ouput, kernel, Point(-1, -1));		//腐蚀
	//计算内部梯度(原图-腐蚀)
	subtract(img, erode_ouput, dst, Mat());
	imshow("内部梯度", dst);
}

 3、效果

三、外部梯度

1、原理 

外部梯度 = 膨胀图像 - 原图像

外部梯度使用膨胀之后的图像减去原来的图像得到的差值图像。

2、代码

//外部梯度(膨胀-原图)
void ExternalGrad()
{
	//创建卷积核(结构元)
	Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));
	//创建新图(膨胀)
	Mat dilate_output;
	dilate(img, dilate_output, kernel, Point(-1, -1));		//膨胀
	//计算外部梯度(膨胀-原图)
	subtract(dilate_output, img, dst, Mat());
	imshow("外部梯度", dst);
}

3、效果

四、方向梯度

1、原理

方向梯度是使用X方向与Y方向的直线作为结构元素之后得到图像梯度

用X方向直线做结构元素分别膨胀与腐蚀之后得到图像求差值之后称为X方向梯度;

用Y方向直线做结构元素分别膨胀与腐蚀之后得到图像求差值之后称为Y方向梯度。

2、二值化图像(黑白)

开始计算方向梯度前,先把图像二值化(黑白化)。

二值化步骤:

1、先把彩图转灰度图

2、再把灰度图转黑白图(二值化)

//图像二值化
void ToBin()
{
	// 1、转为灰度图
	cvtColor(img, grayImage, COLOR_BGR2GRAY);
	// 2、将灰度图二值化
	threshold(grayImage, binImg, 0, 255, THRESH_OTSU);
}

 3、求X(Y)轴方向梯度

X方向梯度 = X轴方向膨胀 - X轴方向腐蚀        (黑白图像)

Y方向梯度 = Y轴方向膨胀 - Y轴方向腐蚀        (黑白图像)

把黑白图像分别沿X(Y)轴膨胀和腐蚀,最后求差值。

X轴: 

//X方向梯度(黑白图:沿X轴方向膨胀 - 沿X方向腐蚀)
void XDirectGrad()
{
	//X方向梯度:使用X方向的直线作为结构元素
	Mat X = getStructuringElement(MORPH_RECT, Size(img.cols / 32, 1));	  //X向量:宽XX,高1
	Mat dilate_direct, erode_direct;                //膨胀与腐蚀图像
	Mat xDirectImg;                                 //X方向梯度图像

	// 1、图像二值化
	ToBin();
	// 2、沿X轴方向分别膨胀和腐蚀
	dilate(binImg, dilate_direct, X);				//沿X轴方向膨胀
	erode(binImg, erode_direct, X);					//沿X轴方向腐蚀
	// 3、X 方向梯度:X轴方向膨胀 - X轴方向腐蚀
	subtract(dilate_direct, erode_direct, xDirectImg, Mat());

	imshow("X 方向梯度", xDirectImg);
}

Y轴:

//Y方向梯度(黑白图:沿Y轴方向膨胀 - 沿Y方向腐蚀)
void YDirectGrad()
{
	//Y方向梯度:使用Y方向的直线作为结构元素
	Mat Y = getStructuringElement(MORPH_RECT, Size(1, img.rows / 32));		//Y向量:宽1,高XX
	Mat dilate_direct, erode_direct;                //膨胀与腐蚀图像
	Mat yDirectImg;                                 //Y方向梯度图像

	// 1、图像二值化
	ToBin();
	// 2、沿Y轴方向分别膨胀和腐蚀
	dilate(binImg, dilate_direct, Y);				//沿Y轴方向膨胀
	erode(binImg, erode_direct, Y);					//沿Y轴方向腐蚀
	// 3、Y 方向梯度:Y轴方向膨胀 - Y轴方向腐蚀
	subtract(dilate_direct, erode_direct, yDirectImg, Mat());

	imshow("Y 方向梯度", yDirectImg);
}

总代码

//形态学梯度(基本梯度、内部梯度、外部梯度、方向梯度X(Y))
#include <iostream>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

Mat img, dst;
Mat grayImage, binImg;

//图像初始化
void Image_Init()
{
	img = imread("Resource/test7.jpg");
	dst = Mat::zeros(img.size(), img.type());

	if (img.empty())
	{
		printf("图像加载失败");
		exit(0);
	}
}

//基本梯度(膨胀-腐蚀)
void BasicGrad()
{
	//创建卷积核(结构元)
	Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));
	//创建新图像(膨胀、腐蚀)
	Mat dilate_output, erode_ouput;
	dilate(img, dilate_output, kernel, Point(-1, -1));		//膨胀
	erode(img, erode_ouput, kernel, Point(-1, -1));		//腐蚀
	//计算基本梯度
	subtract(dilate_output, erode_ouput, dst, Mat());	//膨胀-腐蚀
	//			膨胀					腐蚀				   结果

	imshow("基本梯度", dst);
}

//内部梯度(原图-腐蚀)
void InternalGrad()
{
	//创建卷积核(结构元)
	Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));
	//创建新图(腐蚀)
	Mat erode_ouput;
	erode(img, erode_ouput, kernel, Point(-1, -1));		//腐蚀
	//计算内部梯度(原图-腐蚀)
	subtract(img, erode_ouput, dst, Mat());
	imshow("内部梯度", dst);
}

//外部梯度(膨胀-原图)
void ExternalGrad()
{
	//创建卷积核(结构元)
	Mat kernel = getStructuringElement(MORPH_RECT, Size(15, 15), Point(-1, -1));
	//创建新图(膨胀)
	Mat dilate_output;
	dilate(img, dilate_output, kernel, Point(-1, -1));		//膨胀
	//计算外部梯度(膨胀-原图)
	subtract(dilate_output, img, dst, Mat());
	imshow("外部梯度", dst);
}

//图像二值化
void ToBin()
{
	// 1、转为灰度图
	cvtColor(img, grayImage, COLOR_BGR2GRAY);
	// 2、将灰度图二值化
	threshold(grayImage, binImg, 0, 255, THRESH_OTSU);
}

//X方向梯度(黑白图:沿X轴方向膨胀 - 沿X方向腐蚀)
void XDirectGrad()
{
	//X方向梯度:使用X方向的直线作为结构元素
	Mat X = getStructuringElement(MORPH_RECT, Size(img.cols / 32, 1));	  //X向量:宽XX,高1
	Mat dilate_direct, erode_direct;				//膨胀与腐蚀图像
	Mat xDirectImg;										//X方向梯度图像

	// 1、图像二值化
	ToBin();
	// 2、沿X轴方向分别膨胀和腐蚀
	dilate(binImg, dilate_direct, X);				//沿X轴方向膨胀
	erode(binImg, erode_direct, X);				//沿X轴方向腐蚀
	// 3、X 方向梯度:X轴方向膨胀 - X轴方向腐蚀
	subtract(dilate_direct, erode_direct, xDirectImg, Mat());

	imshow("X 方向梯度", xDirectImg);
}

//Y方向梯度(黑白图:沿Y轴方向膨胀 - 沿Y方向腐蚀)
void YDirectGrad()
{
	//Y方向梯度:使用Y方向的直线作为结构元素
	Mat Y = getStructuringElement(MORPH_RECT, Size(1, img.rows / 32));		//Y向量:宽1,高XX
	Mat dilate_direct, erode_direct;				//膨胀与腐蚀图像
	Mat yDirectImg;										//Y方向梯度图像

	// 1、图像二值化
	ToBin();
	// 2、沿Y轴方向分别膨胀和腐蚀
	dilate(binImg, dilate_direct, Y);				//沿Y轴方向膨胀
	erode(binImg, erode_direct, Y);				//沿Y轴方向腐蚀
	// 3、Y 方向梯度:Y轴方向膨胀 - Y轴方向腐蚀
	subtract(dilate_direct, erode_direct, yDirectImg, Mat());

	imshow("Y 方向梯度", yDirectImg);
}

//显示图像
void Show()
{
	imshow("原图", img);
}

int main()
{
	Image_Init();							//图像初始化

	BasicGrad();							//基本梯度

	InternalGrad();							//内部梯度

	ExternalGrad();							//外部梯度

	XDirectGrad();							//X方向梯度
	YDirectGrad();							//Y方向梯度

	Show();									//显示原图像

	waitKey(0);

	return 0;
}

参考资料:

https://blog.csdn.net/sinat_36264666/article/details/78629600?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162856242416780261952100%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=162856242416780261952100&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-78629600.pc_search_result_control_group&utm_term=%E5%BD%A2%E6%80%81%E5%AD%A6%E6%A2%AF%E5%BA%A6&spm=1018.2226.3001.4187

https://blog.csdn.net/weixin_41695564/article/details/79935028

https://blog.csdn.net/qq_41498261/article/details/103112661?ops_request_misc=&request_id=&biz_id=102&utm_term=%E5%BD%A2%E6%80%81%E5%AD%A6%E6%A2%AF%E5%BA%A6&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduweb~default-7-.nonecase&spm=1018.2226.3001.4187

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_(*^▽^*)_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值