数学形态学(mathematical morphology)是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论,其基本的运算包括:腐蚀和膨胀、开运算和闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换等。
一、cv::morphologyEx
1.1 函数简介
(OpenCV牛逼)OpenCV4.5.1的cv::morphologyEx提供了8种常用的数学形态学操作:腐蚀、膨胀、开运算、闭运算、形态学基本梯度、顶帽、黑帽、击中击不中变换。这个函数以腐蚀和膨胀作为基本操作,进行高级复杂的数学形态学变换。
在多通道图像中,每个通道是单独处理。
void cv::morphologyEx | ( | InputArray | src, |
| | OutputArray | dst, |
| | int | op, |
| | kernel, | |
| | Point | anchor = Point(-1,-1), |
| | int | iterations = 1, |
| | int | borderType = BORDER_CONSTANT, |
| | const Scalar & | borderValue = morphologyDefaultBorderValue() |
| ) | | |
1.2 参数说明
(1)src
原图,可以多通道;但是深度必须是CV_8U、CV_16U、CV_16S、CV_32F、 CV_64F的其中之一。
(2)dst
结果图像(可为原图),与原图的大小和类型相同。
(3)op
形态学操作的选项:0-腐蚀、1-膨胀、2-开运算、3-闭运算、4-形态学基本梯度、5-顶帽、6-黑帽、7-击中击不中变换。详见 Morph Types 。
(4)kernel
结构元素。可通过 getStructuringElement 创建。
(5)anchor
结构元素的锚点位置。负值代表锚点在结构元素的中心。
(6)iterations
应用腐蚀或膨胀的迭代次数。例如,两次迭代的开运算等效于腐蚀-腐蚀-膨胀-膨胀(不是腐蚀-膨胀-腐蚀-膨胀)。
(7)borderType
像素外推方法。详见:BorderTypes, 不支持BORDER_WRAP。
(8)borderValue
固定边缘情况下的边界值。默认值有特殊含义。
二、操作选项
分享给有需要的人,代码质量勿喷。
#include "opencv2/opencv.hpp"
//灰度
cv::Mat img_gray = cv::imread("F:/cs.jpg", cv::IMREAD_GRAYSCALE);
//二值图
cv::Mat img_binary;
double t = threshold(img_gray, img_binary, 0, 255, cv::THRESH_BINARY | cv::THRESH_OTSU);
//结构核尺寸
uint morphSize = 5;
//结构0:矩形
cv::Mat morphRECT = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(morphSize, morphSize));
//结构1:十字交叉
cv::Mat morphCROSS = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(morphSize, morphSize));
//结构2:椭圆
cv::Mat morphELLIPSE = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(morphSize, morphSize));
//自定义菱形结构核
cv::Mat morphDiamond = (cv::Mat_<int>(5, 5) <<
0, 0, 1, 0, 0,
0, 1, 1, 1, 0,
1, 1, 1, 1, 1,
0, 1, 1, 1, 0,
0, 0, 1, 0, 0);
//迭代次数
uint morphIterations = 1;
2.1 腐蚀 erode
(1)操作
用结构元素的每一个像素与其覆盖的像素做“与”操作。如果都为1,则该像素为1,否则为0。用最小值替换中心像素。
(2)作用
①消除物体边界点,消除小于结构元素的噪声点,使目标缩小。
②腐蚀意味着图像中物体的边界被侵蚀了,轮廓向内收缩,体积变小了。
// 0 腐蚀
cv::Mat img0_erode;
cv::morphologyEx(img_binary, img0_erode, 0/*cv::MORPH_ERODE*/, morphCROSS, cv::Point(-1, -1), morphIterations);
//保存
cv::imwrite("F:/img0_erode.png", img0_erode);
2.2 膨胀 dilate
(1)操作
用结构元素的每一个像素与其覆盖的像素做“或”操作。如果都为0,则该像素为0,否则为1。用最大值替换中心像素。
(2)作用
①填补孔洞,将与物体接触的所有背景点合并到物体中,使目标增大。
②膨胀意味着图像中物体的边界被拉伸了,轮廓向外扩张,体积变大了。
// 1 膨胀
cv::Mat img1_dilate;
cv::morphologyEx(img_binary, img1_dilate, 1/*cv::MORPH_DILATE*/, morphCROSS, cv::Point(-1, -1), morphIterations);
//保存
cv::imwrite("F:/img1_dilate.png", img1_dilate);
2.3 开运算=腐蚀+膨胀 open
(1)操作
先腐蚀,后膨胀。
(2)作用
消除细小的对象;在细微处分离物体;平滑较大物体的边界。
// 2 开运算
cv::Mat img2_open;
cv::morphologyEx(img_binary, img2_open, 2/*cv::MORPH_OPEN*/, morphCROSS, cv::Point(-1, -1), morphIterations);
//保存
cv::imwrite("F:/img2_open.png", img2_open);
2.4 闭运算=膨胀+腐蚀 close
(1)操作
先膨胀,后腐蚀。
(2)作用
填补孔洞;将断开的近邻目标连接;在不明显改变物体面积和形状的情况下平滑其边界。
// 3 闭运算
cv::Mat img3_close;
cv::morphologyEx(img_binary, img3_close, 3/*cv::MORPH_CLOSE*/, morphCROSS, cv::Point(-1, -1), 2);
//保存
cv::imwrite("F:/img3_close.png", img3_close);
2.5 形态学基本梯度=膨胀-腐蚀 gradient
(1)操作
膨胀-腐蚀。
(2)作用
突出目标的边缘。
// 4 形态学基本梯度
cv::Mat img4_gradient;
cv::morphologyEx(img_binary, img4_gradient, cv::MORPH_GRADIENT/*4*/, morphCROSS, cv::Point(-1, -1), morphIterations);
//保存
cv::imwrite("F:/img4_gradient.png", img4_gradient);
(3)分类
①基本梯度=膨胀-腐蚀
②内部梯度=原图-腐蚀
③外部梯度=膨胀-原图
④方向梯度是以X方向或Y方向的直线作为结构元素,处理后得到的图像梯度。若用X方向直线作为结构元素,分别膨胀与腐蚀之后,做差值,称为X方向梯度。若用Y方向直线作为结构元素,分别膨胀与腐蚀之后,做差值,称为Y方向梯度。
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.6 顶帽=原图-开运算 tophat
(1)操作
原图-开运算。
(2)作用
①凸显暗背景上的亮物体,突出比原图轮廓周围区域更明亮的区域。
②增强图像的对比度,可以解决光照不均匀的问题。
// 5 顶帽
cv::Mat img5_tophat;
cv::morphologyEx(img_binary, img5_tophat, cv::MORPH_TOPHAT/*5*/, morphCROSS, cv::Point(-1, -1), morphIterations);
//保存
cv::imwrite("F:/img5_tophat.png", img5_tophat);
2.7 黑帽=闭运算-原图 blackhat
(1)操作
闭运算-原图。
(2)作用
凸显亮背景上的暗物体,突出比原图轮廓周围区域更暗的区域。
// 6 黑帽
cv::Mat img6_blackhat;
cv::morphologyEx(img_binary, img6_blackhat, cv::MORPH_BLACKHAT/*6*/, morphCROSS, cv::Point(-1, -1), morphIterations);
//保存
cv::imwrite("F:/img6_blackhat.png", img6_blackhat);
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2.8 击中击不中 hitmiss
(1)操作
仅支持CV_8UC1的二值图。
(①利用结构元素B1腐蚀原图;②利用结构元素B2腐蚀原图的补集;③两个腐蚀的结果求交集。)
结构元素B=B1+B2,当结构元素B与其覆盖的图像区域完全相同时,中心像素的值才会被置为1,否则为0。即结构元素B在图像中完全匹配的原点位置集合。
(2)作用
类似于模板匹配,进行目标检测。
//读取图像
cv::Mat img_gray = cv::imread("F:/test.jpg", cv::IMREAD_GRAYSCALE);
//二值化(反)
cv::Mat img_binary;
double t = threshold(img_gray, img_binary, 0, 255, cv::THRESH_BINARY_INV | cv::THRESH_OTSU);//t为otsu分割阈值
cv::imwrite("F:/img_binary.png", img_binary);
//结构元素大
uint morphSizeBig = 17;
cv::Mat morphCROSSn = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(morphSizeBig, morphSizeBig));
// 7 击中击不中
cv::Mat img7_hitmiss;
cv::morphologyEx(img_binary, img7_hitmiss, cv::MORPH_HITMISS/*7*/, morphCROSSn, cv::Point(-1, -1), 1);
//保存
cv::imwrite("F:/img7_hitmiss.png", img7_hitmiss);