目录
形态学梯度概述
作用:保留物体的边缘轮廓,便于轮廓分析(突出高亮区域)
形态学梯度定义: 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/weixin_41695564/article/details/79935028