本文作者:小嗷
微信公众号:aoxiaoji
吹比QQ群:736854977
简书链接:https://www.jianshu.com/u/45da1fbce7d0
在本篇中,您将学习如何通过使用“Hit-or-Miss”转换(也称为“Hit-or-Miss”转换)在二进制映像中找到给定的配置或模式。(命中/错过)
这种变换也是更高级的形态学操作的基础,如细化或修剪。
我们将使用OpenCV函数morphologyEx()。
二值图像(Binary Image)是指将图像上的每一个像素只有两种可能的取值或灰度等级状态,人们经常用黑白、B&W、单色图像表示二值图像。
二值图像是指在图像中,灰度等级只有两种,也就是说,图像中的任何像素不是0就是1,再无其他过渡的灰度值。
结构元素就是核模块。
上图中间这个模块称为结构元素(专业名词)
集合是指具有某种特定性质的具体的或抽象的对象汇总成的集体,这些对象称为该集合的元素。
例如全中国人的集合,它的元素就是每一个中国人。
我们通常用大写字母如A,B,S,T,…表示集合,而用小写字母如a,b,x,y,…表示集合的元素。
记为x∈S。
记为y∉S。
有一类特殊的集合,它不包含任何元素,如{x|x∈R x²+1=0} ,我们称之为空集,记为∅。
设S,T是两个集合,如果S的所有元素都属于T
则称S是T的子集,记为
如果两个集合S和T的元素完全相同,则称S与T两个集合相等,记为S=T 。显然我们有
并集定义
并集定义:由所有属于集合A或属于集合B的元素所组成的集合,记作A∪B(或B∪A),读作“A并B”(或“B并A”),即A∪B={x|x∈A,或x∈B}。并集越并越多。
交集定义
由属于A且属于B的相同元素组成的集合,记作A∩B(或B∩A),读作“A交B”(或“B交A”),即A∩B={x|x∈A,且x∈B}。交集越交越少。
若A包含B,则A∩B=B,A∪B=A
击中击不中需要用到。所以,小嗷就写写集合
相对补集定义:由属于A而不属于B的元素组成的集合,称为B关于A的相对补集,记作A-B或A\B,即A-B={x|x∈A,且x∉B’}。
绝对补集定义:A关于全集合U的相对补集称作A的绝对补集,记作A’或∁u(A)或~A。有U’=Φ;Φ’=U
例如:A的补集
意思就是除了A中的元素外的元素所组成的集合
也就是说A里面有的,A的补集一定没有
A里面没有的,A的补集里一定有
所以A的补集和A的交集是空集
定义:设有集合A,由集合A所有子集组成的集合,称为集合A的幂集。
定理:有限集A的幂集的基数等于2的有限集A的基数次幂
形态学运算符根据图像的形状来处理图像。
这些操作符将一个或多个结构化元素应用到输入映像中,以获得输出映像。两个基本的形态学操作是侵蚀和扩张。
这两个操作的组合产生高级形态转换,如打开、关闭或顶帽转换。要了解这些和其他基本的形态学操作的更多信息,请参考以前的教程(第25篇腐蚀和膨胀)和(第27篇更多的形态学转换)。
对于在二值图中查找模式,“Hit-or-Miss”转换非常有用。特别地,它找到了那些邻域与第一个结构元素B1的形状匹配的像素,同时又与第二个结构元素B2的形状不匹配。在数学上,应用于图像A的操作可以表示为:
简单来说:
“Hit-or-Miss”找到那些邻域与B1(核)的形状匹配的像素
“Hit-or-Miss”找到那些邻域与B2(核)的形状不匹配的像素
具体操作:
首先,建立一个比B大的模板W;使用此模板对图像A进行腐蚀,得到图像假设为Process1;
其次,用B减去W,从而得到V模板(W-B);使用V模板对图像A的补集进行腐蚀,得到图像假设为Process2;
然后,Process1与Process2取交集;得到的结果就是B的位置。这里的位置可能不是B的中心位置,要视W-B时对齐的位置而异;
因此,“Hit-or-Miss” 操作包括三个步骤:
第二步例子,第一步和第三步相对简单就不写(如果不懂就公众号或者QQ邮箱call小嗷)
结构元素B1和B2可以组合成单个元素b。我们来看一个例子:
B1为第一个结构元素,B2为第二个结构元素,b为第三个结构元素(B1-B2=b)
结构元素(内核)。左:内核“击中”。中间:内核“不击中”。右:最后结合内核
在这种情况下,我们正在寻找一种模式,其中的中心像素属于背景,而北部、南部、东部和西部像素属于前景。附近的其他像素可以是任何类型的,我们不关心它们。现在,让我们将这个核应用到一个输入图像:
二值图(原图)
输出二值图像
您可以看到模式只在图像中的一个位置找到255
#include
#include
#include
using namespace cv;
int main(){
Mat input_image = (Mat_(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);
Mat kernel = (Mat_(3, 3) <<
0, 1, 0,
1, -1, 1,
0, 1, 0);
Mat output_image;
morphologyEx(input_image, output_image, MORPH_HITMISS, kernel);
const int rate = 50;
kernel = (kernel + 1) * 127;
kernel.convertTo(kernel, CV_8U);
resize(kernel, kernel, Size(), rate, rate, INTER_NEAREST);
imshow("kernel", kernel);
moveWindow("kernel", 0, 0);
resize(input_image, input_image, Size(), rate, rate, INTER_NEAREST);
imshow("Original", input_image);
moveWindow("Original", 0, 200);
//rate就是用来或大尺寸
resize(output_image, output_image, Size(), rate, rate, INTER_NEAREST);
imshow("Hit or Miss", output_image);
moveWindow("Hit or Miss", 500, 200);
waitKey(0);
return 0;
}
效果图
看第27篇,ths
网址:
https://docs.opencv.org/master/d4/d86/group__imgproc__filter.html#gga7be549266bad7b2e6a04db49827f9f32acf55ff766595ec0174ba42852f0ac264
“hit or miss” .- 只支持CV_8UC1二进制图像。
saturate_cast(value):(value)确保值大小范围为0~255之间
void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
参数:
(在第5篇线性混合addWeighted谈到alpha、beta)
函数将源矩阵中的像素值转换为目标类型。最后会使用溢出保护函数saturate_cast<> ,以避免转换过程中可能出现的溢出。函数执行如下运算:
convertTo:就是转换类型
改变指定窗口的位置和大小。
任务:
简单调用API函数就OK(估计以后实战中,经常使用形态学图像处理问题)
代码如下:
#include
#include
#include
using namespace cv;
int main() {
Mat input_image = imread("D://9.jpg",2);
imshow("Hit or Miss原图", input_image);
Mat kernel = (Mat_(3, 3) <<
0, 1, 0,
1, -1, 1,
0, 1, 0);
Mat output_image, output_image1;
Mat element = getStructuringElement(0, Size(3, 3),Point(-1,-1));
erode(input_image, output_image1, element);
imshow("腐蚀图", output_image1);
morphologyEx(input_image, output_image, MORPH_HITMISS, kernel);
imshow("Hit or Miss", output_image);
waitKey(0);
return 0;
}
原图:
效果图:
效果有点像内部和外部梯度的效果图,当然日后轮廓相关边缘检测,分水岭要用到
分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载。
推荐文章:
8.更正曝光不足的图像(图像的对比度和亮度及轨迹条) — OpenCV从零开始到图像(人脸 + 物体)识别系列 【没有排版好】
(公众号底下的文章分类 -> 编程 -> 查看第四篇文章)【已经排版好,建议PC电脑看】
25.消除不相关的细节/裂缝桥接(形态学 –膨胀与腐蚀详解 )— OpenCV从零开始到图像(人脸 + 物体)识别系列
27.形态学图像运算(形态学梯度计算/开运算/闭运算/顶帽运算/黑帽)– OpenCV从零开始到图像(人脸 + 物体)识别系列
很多书上都用集合论来讲这一变换,对应用者来说似乎没这必要。简单来说击中-击不中运算常用于二值图像,它用于基于结构元素的配置,从图像中寻找具有某种像素排列特征的目标,如单个像素、颗粒中交叉或纵向的特征、直角边缘或其他用户自定义的特征等。计算时,只有当结构元素与其覆盖的图像区域完全相同时,中心像素的值才会被置为1,否则为0。下图给出了一个例子。
和简单的腐蚀操作不一样。击中或击不中变换,只有当结构元素与其覆盖的图像区域完全相同(包括物体前景点还含有背景点,也就是补集也要一样)时,所对应的区域输出图象。
书上有这么一句话:“当不需要背景时,击中或击不中变换退化为腐蚀操作”