计算机视觉全系列实战教程 (十三):图像形态学操作

发布于:2024-07-02 ⋅ 阅读:(14) ⋅ 点赞:(0)

1.基本概述

(1)What

图像的形态学操作的本质:集合间的运算 + 几何学

(2)Why(有什么用途)

消除噪声、边缘提取、区域填充、细化和粗化、分割独立的图像元素、求图像梯度、求极大值区域或极小值区域等。

(3)Which(有哪些常见的形态学操作)

A.膨胀
使得图像中“亮色”范围依据传入的结构元kernel扩张
B.腐蚀
使得图像中“暗色”范围依据传入的结构元kernel扩张
C.开运算
先腐蚀,后膨胀(移除小的“亮色”对象)
D.闭运算
先膨胀,后腐蚀(移除小的“暗色”对象)
E.顶帽运算
顶帽 = 原图 - 开运算的结果(分离得到一些“亮”区域)
F.黑帽运算
黑猫 = 闭运算 - 原图(分离得到一些“暗”区域)
G.击中与击不中
根据给定的模板来寻找二值图像中特定的结构的位置(和模板结构一致的结构);击中与击不中是高级形态学变换的基础(如图像细化、剪枝操作等)

2. 如何进行形态学操作

(1)膨胀和腐蚀

这是形态学中最基本的两种操作,其它形态学操作都是基于这两种基本操作进行的。我这里称之为形态学的“基元操作”

step01:获取结构元
矩形(MORPH_RECT)、十字形(MORPH_CROSS)、椭圆形(MORPH_ELLIPSE)

//得到3阶矩阵,形状为矩形(值全为1)
cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3));
//形状为十字形(十字形区域全为1,其它为0)
kernel = cv::getStructuringElement(cv::MORPH_CROSS, cv::Size(3,3));

step02:膨胀和腐蚀
方式一:erode和dilate

int iTms = 10; //腐蚀和膨胀的次数
cv::Mat imTmp01, imTmp02;
cv::dilate(imGray, imTmp01, kernel, cv::Point(-1, -1), iTms);
cv::erode(imGray, imTmp02, kernel, cv::Point(-1, -1), iTms);

方式二:morphologyEx(还可以进行其它形态学操作:开、闭、顶帽、黑帽等)

int iTms = 10; //腐蚀和膨胀的次数
cv::Mat imTmp03, imTmp04;
cv::morphologyEx(imGray, imTmp03, cv::MORPH_ERODE, kernel, cv::Point(-1, -1), iTms);
cv::morphologyEx(imGray, imTmp04, cv::MORPH_DILATE, kernel, cv::Point(-1, -1), iTms);

(2)开运算和闭运算

MORPH_OPEN、MORPH_CLOSE

int iTms = 10; //腐蚀和膨胀的次数
cv::Mat imTmp05, imTmp06;
cv::morphologyEx(imGray, imTmp05, cv::MORPH_OPEN, kernel, cv::Point(-1, -1), iTms);
cv::morphologyEx(imGray, imTmp06, cv::MORPH_CLOSE, kernel, cv::Point(-1, -1), iTms);

(3)顶帽和黑帽

int iTms = 10; //腐蚀和膨胀的次数
cv::Mat imTmp07, imTmp08;
cv::morphologyEx(imGray, imTmp07, cv::MORPH_TOPHAT, kernel, cv::Point(-1, -1), iTms);
cv::morphologyEx(imGray, imTmp08, cv::MORPH_BLACKHAT, kernel, cv::Point(-1, -1), iTms);

(4)击中与击不中

A.Why(目的)
通过定义形状模板获取同一形状物体在图像中的位置。
B.What(相关概念)
击中结构元:用于腐蚀原始图像,得到击中的中间结果X
击不中结构元:用于腐蚀原始图像的补集,得到击不中的中间结果
C.How(如何使用击中和击不中)
step01:用击中结构元腐蚀图像A,得到X
step02:用击不中结构元腐蚀图像A的补集,得到Y
step03:X和Y进行与运算,得到结果图像,此时的结果图像击中结构元和击不中机构元相加的形状

cv::Mat kernel_hit = (cv::Mat_<int>(3, 3) << 0, 1, 0,
	1, 0, 1,
	0, 1, 0);
cv::Mat kernel_miss = (cv::Mat_<int>(3, 3) << 0, 0, 0,
	0, -1, 0,
	0, 0, 0);
cv::Mat kernel = kernel_hit + kernel_miss;
cv::Mat imInput = (cv::Mat_<uchar>(8, 8) <<   0,  0,   0,   0,  0,  0,  0,  0,
											0, 255, 255, 255, 0,  0,  0, 255,
											0, 255, 255, 255, 0,  0,  0,  0,
											0, 255, 255, 255, 0, 255, 0,  0,
											0,  0,  255,  0,  0,  0,  0,  0,
											0,  0,  255,  0,  0, 255,255, 0,
											0, 255,  0,  255, 0,  0, 255, 0,
											0, 255, 255, 255, 0,  0,  0,  0);
cv::Mat imOut;
cv::morphologyEx(imInput, imOut, cv::MORPH_HITMISS, kernel);

注意:imInput是uchar类型,其它是int类型;imOut是kernel在原图中的定位
在kernel中0可以匹配任意元素,1匹配255,-1匹配0


网站公告

今日签到

点亮在社区的每一天
去签到