28.击中击不中变换(二值图像/结构元素/集合/convertTo/saturate_cast/moveWindow)


本文作者:小嗷

微信公众号:aoxiaoji

吹比QQ群:736854977

微信链接:https://mp.weixin.qq.com/s?__biz=MzU1MTgxNjQyMg==&mid=2247483871&idx=1&sn=d291fddb429e335ca801f7cffb017878&chksm=fb8adc56ccfd554082cb87416d3f95f308302981bcd570161815a70e8ddb47dcf8fa1c8684b3#rd


image
image
image

在本篇中,您将学习如何通过使用“Hit-or-Miss”转换(也称为“Hit-or-Miss”转换)在二进制映像中找到给定的配置或模式。(命中/错过)

这种变换也是更高级的形态学操作的基础,如细化或修剪。

我们将使用OpenCV函数morphologyEx()。

本文你会找到以下问题的答案:

  1. 二值图像

  2. 结构元素

  3. 集合

  4. 击中击不中变换(Hit-or-Miss)

  5. convertTo

  6. saturate_cast

  7. moveWindow


2.1 二值图像

二值图像(Binary Image)是指将图像上的每一个像素只有两种可能的取值或灰度等级状态,人们经常用黑白、B&W、单色图像表示二值图像。

image.gif

二值图像是指在图像中,灰度等级只有两种,也就是说,图像中的任何像素不是0就是1,再无其他过渡的灰度值。

2.2 结构元素

结构元素就是核模块。

image.gif

上图中间这个模块称为结构元素(专业名词)

image.gif

2.3 集合

集合是指具有某种特定性质的具体的或抽象的对象汇总成的集体,这些对象称为该集合的元素。

例如全中国人的集合,它的元素就是每一个中国人。

我们通常用大写字母如A,B,S,T,...表示集合,而用小写字母如a,b,x,y,...表示集合的元素。

2.3.1 若x是集合S的元素,则称x属于S,

记为x∈S。

2.3.2 若y不是集合S的元素,则称y不属于S,

记为y∉S。

2.3.3 空集

有一类特殊的集合,它不包含任何元素,如{x|x∈R x²+1=0} ,我们称之为空集,记为∅。

2.3.4 子集

设S,T是两个集合,如果S的所有元素都属于T

image

则称S是T的子集,记为
image

2.3.5 相等

如果两个集合S和T的元素完全相同,则称S与T两个集合相等,记为S=T 。显然我们有
image

2.3.6 并交集

并集定义

并集定义:由所有属于集合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

2.3.7 补集(重点)

击中击不中需要用到。所以,小嗷就写写集合

相对补集定义:由属于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的交集是空集

2.3.8 幂集

定义:设有集合A,由集合A所有子集组成的集合,称为集合A的幂集。 定理:有限集A的幂集的基数等于2的有限集A的基数次幂

2.4 击中击不中变换(Hit-or-Miss)理论

形态学运算符根据图像的形状来处理图像。

这些操作符将一个或多个结构化元素应用到输入映像中,以获得输出映像。两个基本的形态学操作是侵蚀和扩张。

这两个操作的组合产生高级形态转换,如打开、关闭或顶帽转换。要了解这些和其他基本的形态学操作的更多信息,请参考以前的教程(第25篇腐蚀和膨胀)和(第27篇更多的形态学转换)。

对于在二值图中查找模式,“Hit-or-Miss”转换非常有用。特别地,它找到了那些邻域与第一个结构元素B1的形状匹配的像素,同时又与第二个结构元素B2的形状不匹配。在数学上,应用于图像A的操作可以表示为:

image

简单来说:

“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” 操作包括三个步骤:

  • 用结构元素B1腐蚀图像A(B1等于W)。

  • 用结构元素B2腐蚀图像A (Ac)的补集(B2=B1-B)。

  • 第一步的结果和第二步的结果的交集。

第二步例子,第一步和第三步相对简单就不写(如果不懂就公众号或者QQ邮箱call小嗷)

结构元素B1和B2可以组合成单个元素b。我们来看一个例子:

image.gif

B1为第一个结构元素,B2为第二个结构元素,b为第三个结构元素(B1-B2=b)

结构元素(内核)。左:内核“击中”。中间:内核“不击中”。右:最后结合内核

在这种情况下,我们正在寻找一种模式,其中的中心像素属于背景,而北部、南部、东部和西部像素属于前景。附近的其他像素可以是任何类型的,我们不关心它们。现在,让我们将这个核应用到一个输入图像:

image.gif

二值图(原图)

image

输出二值图像

您可以看到模式只在图像中的一个位置找到255

前面示例对应的代码如下所示。

 1#include <opencv2/core.hpp> 2#include <opencv2/imgproc.hpp> 3#include <opencv2/highgui.hpp> 4using namespace cv; 5int main(){ 6    Mat input_image = (Mat_<uchar>(8, 8) << 7        0, 0, 0, 0, 0, 0, 0, 0, 8        0, 255, 255, 255, 0, 0, 0, 255, 9        0, 255, 255, 255, 0, 0, 0, 0,10        0, 255, 255, 255, 0, 255, 0, 0,11        0, 0, 255, 0, 0, 0, 0, 0,12        0, 0, 255, 0, 0, 255, 255, 0,13        0, 255, 0, 255, 0, 0, 255, 0,14        0, 255, 255, 255, 0, 0, 0, 0);15    Mat kernel = (Mat_<int>(3, 3) <<16        0, 1, 0,17        1, -1, 1,18        0, 1, 0);19    Mat output_image;20    morphologyEx(input_image, output_image, MORPH_HITMISS, kernel);21    const int rate = 50;22    kernel = (kernel + 1) * 127;23    kernel.convertTo(kernel, CV_8U);24    resize(kernel, kernel, Size(), rate, rate, INTER_NEAREST);25    imshow("kernel", kernel);26    moveWindow("kernel", 0, 0);27    resize(input_image, input_image, Size(), rate, rate, INTER_NEAREST);28    imshow("Original", input_image);29    moveWindow("Original", 0, 200);30    //rate就是用来或大尺寸31    resize(output_image, output_image, Size(), rate, rate, INTER_NEAREST);32    imshow("Hit or Miss", output_image);33    moveWindow("Hit or Miss", 500, 200);34    waitKey(0);35    return 0;36}

效果图

image.gif
image.gif

3.1 MorphTypes

看第27篇,ths

image

网址:

https://docs.opencv.org/master/d4/d86/groupimgprocfilter.html#gga7be549266bad7b2e6a04db49827f9f32acf55ff766595ec0174ba42852f0ac264

"hit or miss" .- 只支持CV_8UC1二进制图像。

3.2 saturate_cast的用法

saturate_cast<uchar>(value):(value)确保值大小范围为0~255之间</uchar>

3.3 convertTo的用法

1void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;  

参数:

  • m:目标矩阵。如果m在运算前没有合适的尺寸或类型,将被重新分配。

  • rtype:目标矩阵的类型。因为目标矩阵的通道数与源矩阵一样,所以rtype也可以看做是目标矩阵的位深度。如果rtype为负值,目标矩阵和源矩阵将使用同样的类型。

  • alpha:尺度变换因子(可选)。【比例因子】

  • beta:附加到尺度变换后的值上的偏移量(可选)【将输入数组元素按比例缩放后添加的值】。

(在第5篇线性混合addWeighted谈到alpha、beta)

函数将源矩阵中的像素值转换为目标类型。最后会使用溢出保护函数saturate_cast<> ,以避免转换过程中可能出现的溢出。函数执行如下运算:

image

convertTo:就是转换类型

3.4 MoveWindow

改变指定窗口的位置和大小。

image

任务:

简单调用API函数就OK(估计以后实战中,经常使用形态学图像处理问题)

代码如下:

 1#include <opencv2/core.hpp> 2#include <opencv2/imgproc.hpp> 3#include <opencv2/highgui.hpp> 4using namespace cv; 5int main() { 6    Mat input_image = imread("D://9.jpg",2); 7 8    imshow("Hit or Miss原图", input_image); 9    Mat kernel = (Mat_<int>(3, 3) <<10        0, 1, 0,11        1, -1, 1,12        0, 1, 0);13    Mat output_image, output_image1;14    Mat element = getStructuringElement(0, Size(3, 3),Point(-1,-1)); 15    erode(input_image, output_image1, element);16    imshow("腐蚀图", output_image1);1718    morphologyEx(input_image, output_image, MORPH_HITMISS, kernel);1920    imshow("Hit or Miss", output_image);2122    waitKey(0);23    return 0;24}

原图:

image.gif

效果图:

image

效果有点像内部和外部梯度的效果图,当然日后轮廓相关边缘检测,分水岭要用到

image
  1. 本人是抱着玩一玩的心态,学习opencv(其实深度学习没有外界说的这么高深,小嗷是白板,而且有工作在身并且于代码无关)

  2. 大家可以把我的数学水平想象成初中水平,毕竟小嗷既不是代码靠吃饭又不是靠数学吃饭,毕业N年

  3. 写文章主要是为了后人少走点弯路,多交点朋友,一起学习

  4. 如果有好的图像识别群拉我进去QQ:631821577

  5. 就我一个白板,最后还是成的,你们别怕,慢慢来把

image

分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载。

  • 邮箱:631821577@qq.com

  • QQ群:736854977

  • 有什么疑问公众号提问,下班或者周六日回答,ths

推荐文章:

8.更正曝光不足的图像(图像的对比度和亮度及轨迹条) --- OpenCV从零开始到图像(人脸 + 物体)识别系列 【没有排版好】

(公众号底下的文章分类 -> 编程 -> 查看第四篇文章)【已经排版好,建议PC电脑看】

25.消除不相关的细节/裂缝桥接(形态学 --膨胀与腐蚀详解 )--- OpenCV从零开始到图像(人脸 + 物体)识别系列

27.形态学图像运算(形态学梯度计算/开运算/闭运算/顶帽运算/黑帽)-- OpenCV从零开始到图像(人脸 + 物体)识别系列

感言

很多书上都用集合论来讲这一变换,对应用者来说似乎没这必要。简单来说击中-击不中运算常用于二值图像,它用于基于结构元素的配置,从图像中寻找具有某种像素排列特征的目标,如单个像素、颗粒中交叉或纵向的特征、直角边缘或其他用户自定义的特征等。计算时,只有当结构元素与其覆盖的图像区域完全相同时,中心像素的值才会被置为1,否则为0。下图给出了一个例子。

image

和简单的腐蚀操作不一样。击中或击不中变换,只有当结构元素与其覆盖的图像区域完全相同(包括物体前景点还含有背景点,也就是补集也要一样)时,所对应的区域输出图象。

书上有这么一句话:“当不需要背景时,击中或击不中变换退化为腐蚀操作”

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,384评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,845评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,148评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,640评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,731评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,712评论 1 294
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,703评论 3 415
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,473评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,915评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,227评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,384评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,063评论 5 340
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,706评论 3 324
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,302评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,531评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,321评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,248评论 2 352

推荐阅读更多精彩内容