一、图像形态学处理:
一种基于图像形状和结构的图像分析方法,主要使用二值图像。它涉及到几种基本的运算,包括腐蚀、膨胀、开运算(先腐蚀后膨胀)和闭运算(先膨胀后腐蚀)。
示例使用图片:(将硬币看为了背景)
示例图片:(将硬币看为了前景,可用于硬币计数)
二、结构元素:
(1)函数原型:
CV_EXPORTS_W Mat getStructuringElement(int shape, Size ksize,
Point anchor = Point(-1,-1));
(2)函数功能:
返回用于形态学操作的指定大小和形状的结构元素。
(3)参数:
shape
:指定结构元素的形状,可以是#MorphShapes
枚举类型中的一个值。#MorphShapes
包括:MORPH_RECT
:矩形,MORPH_CROSS
:十字形,MORPH_ELLIPSE
:椭圆形。ksize
:结构元素的大小,用Size
类型表示,Size
是一个包含宽度和高度的简单结构。anchor
:结构元素内部的锚点位置。默认值Point(-1, -1)
表示锚点位于结构元素的中心。对于十字形结构元素,锚点的位置会影响其形状,因为十字形是围绕锚点对称的。对于其他形状,锚点主要影响形态学操作结果的偏移量。
三、腐蚀:
- 腐蚀操作会减少对象的尺寸,移除对象的边缘,并且可以移除小的物体或细节。
- 腐蚀是通过将结构元素(通常是一个简单的几何形状,如矩形、圆形等)滑动到图像上,只有当结构元素完全包含在前景(非零值)时,中心元素才被保留。
(1)函数原型:
CV_EXPORTS_W void erode( InputArray src, OutputArray dst,
InputArray kernel, Point anchor = Point(-1,-1),
int iterations = 1, int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
(2)函数功能:
通过使用特定的结构元素对图像进行腐蚀。
(3)参数:
-
src
:输入图像,可以有任意数量的通道,但深度应该是CV_8U
、CV_16U
、CV_16S
、CV_32F
或CV_64F
中的一种。 -
dst
:输出图像,其大小和类型应与src
相同。 -
kernel
:用于腐蚀的结构元素,决定了在图像上取最小值时考虑的像素邻域的形状。如果element=Mat()
(即未指定),则默认使用3 x 3
矩形结构元素。结构元素可以使用#getStructuringElement
函数创建。 -
anchor
:结构元素内锚点的位置。默认值Point(-1, -1)
表示锚点位于结构元素的中心。 -
iterations
:腐蚀操作应用的次数。 -
borderType
:边界外推方法,用于确定图像边界外的像素值。#BorderTypes
定义了不同的边界类型,但BORDER_WRAP
不受支持。 -
borderValue
:在常数边界情况下的边界值。
(4)腐蚀操作的影响:
a.前景(白色区域):
- 腐蚀操作会优先作用于前景区域,尤其是前景的边缘部分。如果前景对象的边缘像素在结构元素覆盖下不完全被前景像素填满,这些像素将被移除,导致前景对象的尺寸减小。
- 小的前景对象或细节,如噪点或细小的纹理,可能会在腐蚀过程中被完全移除。
- 腐蚀还可以平滑前景对象的边缘,使其变得更加圆润或平直。
b.背景(黑色区域):
- 腐蚀操作通常不会改变背景区域,除非结构元素足够大,以至于触及了背景和前景的边界。
- 如果前景对象非常接近背景,腐蚀操作可能会使这些对象与背景分离,从而增加背景区域的尺寸。
(5)代码示例:
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);
//读取图片并转化为灰度图
Mat srcMat = imread("C:\\Users\\86173\\Desktop\\TI\\Coin.jpg", 0);
//判断读取图片是否失败
if (srcMat.empty()) {
cout << "fail to read pic!" << endl;
return 0;
}
//定义图像容器
Mat image;
Mat erode_image;
//二值化
threshold(srcMat,image, 100, 255, THRESH_OTSU);
//定义结构元素
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
//腐蚀
erode(image, erode_image, element, Point(-1, -1), 1);
//显示结果
imshow("二值化", image);//二值化
imshow("腐蚀", erode_image);//腐蚀
waitKey(0);
destroyAllWindows();
return 0;
}
(6)运行结果:
(白色为前景,黑色为背景,)
四、膨胀:
- 膨胀操作会增加前景对象的尺寸,向对象的边界外扩展。这可以填充前景对象中的小洞,并且可能连接邻近的前景对象。膨胀通常不会改变背景区域,除非膨胀的内核足够大,以至于触及了背景和前景的边界。
(1)函数原型:
CV_EXPORTS_W 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)函数功能:
dilate
函数用于对图像进行膨胀操作,这是一种形态学处理,可以增加图像中前景对象的尺寸。
(3)原地模式:
- 函数支持原地模式(in-place mode),即输入图像
src
和输出图像dst
可以使用相同的内存空间。
(4)参数:
src
:输入图像,可以有任意数量的通道,但深度应该是CV_8U
、CV_16U
、CV_16S
、CV_32F
或CV_64F
中的一种。dst
:输出图像,其大小和类型应与src
相同。kernel
:用于膨胀操作的结构元素。如果element=Mat()
(即未指定),则默认使用3 x 3
矩形结构元素。结构元素可以使用getStructuringElement
函数创建。anchor
:结构元素内锚点的位置。默认值Point(-1, -1)
表示锚点位于结构元素的中心。iterations
:膨胀操作应用的次数。borderType
:边界外推方法,用于确定图像边界外的像素值。BORDER_WRAP
不受支持。详见BorderTypes
。borderValue
:在常数边界情况下的边界值。
(5)代码示例:
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);
//读取图片并转化为灰度图
Mat srcMat = imread("C:\\Users\\86173\\Desktop\\TI\\Coin.jpg", 0);
//判断读取图片是否失败
if (srcMat.empty()) {
cout << "fail to read pic!" << endl;
return 0;
}
//定义图像容器
Mat image;
Mat erode_image;
//二值化
threshold(srcMat,image, 100, 255, THRESH_OTSU);
//定义结构元素
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
//膨胀
dilate(image, erode_image, element, Point(-1, -1), 1);
//显示结果
imshow("二值化", image);//二值化
imshow("膨胀", erode_image);//膨胀
waitKey(0);
destroyAllWindows();
return 0;
}
(6)运行结果:
五、开运算:
- 执行高级形态学变换,先腐蚀再膨胀
(1)函数原型:
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() );
(2)函数功能:
morphologyEx
函数使用腐蚀和膨胀作为基本操作,可以执行高级形态学变换。
(3)参数:
src
:源图像,可以有任意数量的通道,但深度应该是CV_8U
、CV_16U
、CV_16S
、CV_32F
或CV_64F
中的一种。dst
:目标图像,其大小和类型应与源图像src
相同。op
:要执行的形态学操作类型,见#MorphTypes
。kernel
:结构元素,用于定义形态学操作的形状和大小,可以使用#getStructuringElement
创建。anchor
:结构元素内的锚点位置。负值意味着锚点位于结构元素的中心。iterations
:腐蚀和膨胀操作应用的次数。borderType
:边界外推方法,用于确定图像边界外的像素值,见#BorderTypes
。BORDER_WRAP
不受支持。borderValue
:在常数边界情况下的边界值,默认值具有特殊含义。
(4)注意事项:
迭代次数实际上是腐蚀或膨胀操作将被应用的次数。例如,对于形态学开操作(#MORPH_OPEN
),两次迭代相当于依次应用:腐蚀 -> 腐蚀 -> 膨胀 -> 膨胀(而不是腐蚀 -> 膨胀 -> 腐蚀 -> 膨胀)。
(5)形态学操作类型(#MorphTypes
枚举类型的说明):
a.MORPH_ERODE:
- 腐蚀操作。减少前景对象的尺寸,移除前景边缘的像素。
b.MORPH_DILATE:
- 膨胀操作。增加前景对象的尺寸,填充前景内部的空洞。
c.MORPH_OPEN:
- 开运算。先腐蚀再膨胀,有助于去除小的物体和细节,分离相邻对象。
- 数学表达式为:
d.MORPH_CLOSE:
- 闭运算。先膨胀再腐蚀,有助于填充小的空洞和缝隙,连接断裂的对象。
- 数学表达式为:
e.MORPH_GRADIENT:
- 形态学梯度。膨胀结果减去腐蚀结果,突出显示前景对象的边缘。
- 数学表达式为:
f.MORPH_TOPHAT:
- 顶帽操作。原图像减去开运算结果,显示比前景小的物体或细节。
- 数学表达式为:
g.MORPH_BLACKHAT:
- 黑帽操作。闭运算结果减去原图像,显示比前景大的区域或背景。
- 数学表达式为:
h.MORPH_HITMISS:
- 命中或错过操作。这是一种特殊的形态学操作,仅支持单通道8位二值图像。通常用于特定形状的匹配或检测。
(6)示例代码:
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);
//读取图片并转化为灰度图
Mat srcMat = imread("C:\\Users\\86173\\Desktop\\TI\\Coin.jpg", 0);
//判断读取图片是否失败
if (srcMat.empty()) {
cout << "fail to read pic!" << endl;
return 0;
}
//定义图像容器
Mat image;
Mat erode_image;
//二值化
threshold(srcMat,image, 100, 255, THRESH_OTSU);
//定义结构元素
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
//闭运算
morphologyEx(image, erode_image, MORPH_CLOSE, element, Point(-1, -1), 1);
//显示结果
imshow("二值化", image);//二值化
imshow("闭运算", erode_image);//闭运算
waitKey(0);
destroyAllWindows();
return 0;
}
(7)运行结果
六、闭运算:
- 执行高级形态学变换,先膨胀再腐蚀。
(1)函数同开运算。
(2)示例代码:
#include <opencv2/core/utils/logger.hpp>
#include <opencv2/opencv.hpp>
#include <opencv2/videoio.hpp>
#include <opencv2/objdetect.hpp>
#include <opencv2/highgui/highgui_c.h>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
utils::logging::setLogLevel(utils::logging::LOG_LEVEL_SILENT);
//读取图片并转化为灰度图
Mat srcMat = imread("C:\\Users\\86173\\Desktop\\TI\\Coin.jpg", 0);
//判断读取图片是否失败
if (srcMat.empty()) {
cout << "fail to read pic!" << endl;
return 0;
}
//定义图像容器
Mat image;
Mat erode_image;
//二值化
threshold(srcMat,image, 100, 255, THRESH_OTSU);
//定义结构元素
Mat element = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
//开运算
morphologyEx(image, erode_image, MORPH_OPEN, element, Point(-1, -1), 1);
//显示结果
imshow("二值化", image);//二值化
imshow("开运算", erode_image);//开运算
waitKey(0);
destroyAllWindows();
return 0;
}