C#数字图像处理(十四)击中击不中变换 (Hit-miss)
击中击不中变换定义
击中击不中变换(HMT)需要两个结构元素B1和B2,合成一个结构元素对B=(B1,B2)
一个用于探测图像内部,作为击中部分;另一个用于探测图像外部,作为击不中部分。显然,B1和B2是不应该相连接的,即B1∩B2=Φ。击中击不中变换的数学表达式为:
g(x, y)=hitmiss[f(x, y), B]=erode[f(x, y), B1]AND erode[fc(x, y), B2]
其中,fc(x,y)表示的是f(x,y)的补集。
Hit-miss算法步骤:
击中击不中变换是形态学中用来检测特定形状所处位置的一个基本工具。它的原理就是使用腐蚀;如果要在一幅图像A上找到B形状的目标,我们要做的是:
首先,建立一个比B大的模板W;使用此模板对图像A进行腐蚀,得到图像假设为Process1;
其次,用B减去W,从而得到V模板(W-B);使用V模板对图像A的补集进行腐蚀,得到图像假设为Process2;
然后,Process1与Process2取交集;得到的结果就是B的位置。这里的位置可能不是B的中心位置,要视W-B时对齐的位置而异;
其实很简单,两次腐蚀,然后交集,结果就出来了。
Hit-miss原理:
基于腐蚀运算的一个特性:腐蚀的过程相当于对可以填入结构元素的位置作标记的过程。
腐蚀中,虽然标记点取决于原点在结构元素中的相对位置,但输出图像的形状与此无关,改变原点的位置,只会导致输出结果发生平移。
既然腐蚀的过程相当于对可以填入结构元素的位置作标记的过程,可以利用腐蚀来确定目标的位置。进行目标检测,既要检测到目标的内部,也要检测到外部,即在一次运算中可以同时捕获内外标记。
由于以上两点,采用两个结构基元H、M,作为一个结构元素对B=(H,M),一个探测目标内部,一个探测目标外部。当且仅当H平移到某一点可填入X的内部,M平移到该点可填入X的外部时,该点才在击中击不中变换的输出中。
Hit-miss示意图:
在A图中寻找B图所示的图像目标的位置。
解:
1、确定结构元素
既然是寻找图B所示形状,选取H为图B所示的形状。再选一个小窗口W,W包含H,M=W-H。如下图所示:
2、求
3、求
4、求
/// <summary>
/// 击中击不中:只能处理位深度为8的512*512图像
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void hitMiss_Click(object sender, EventArgs e)
{
if (curBitmap != null)
{
hitmiss hitAndMiss = new hitmiss();
if (hitAndMiss.ShowDialog() == DialogResult.OK)
{
Rectangle rect = new Rectangle(, , curBitmap.Width, curBitmap.Height);
BitmapData bmpData = curBitmap.LockBits(rect, ImageLockMode.ReadWrite, curBitmap.PixelFormat);
IntPtr ptr = bmpData.Scan0;
int bytes = curBitmap.Width * curBitmap.Height;
byte[] grayValues = new byte[bytes];
Marshal.Copy(ptr, grayValues, , bytes); //得到击中结构元素
bool[] hitStru = hitAndMiss.GetHitStruction;
//得到击不中结构元素
bool[] missStru = hitAndMiss.GetMissStruction; byte[] tempArray = new byte[bytes];
byte[] temp1Array = new byte[bytes];
byte[] temp2Array = new byte[bytes];
for (int i = ; i < bytes; i++)
{
//原图补集
tempArray[i] = (byte)( - grayValues[i]);
temp1Array[i] = ;
temp2Array[i] = ;
} //应用击中结构元素进行腐蚀运算
for (int i = ; i < curBitmap.Height - ; i++)
{
for (int j = ; j < curBitmap.Width - ; j++)
{
//当前位置是黑色或者是击中结构元素的这一位置没有选中
if ((grayValues[(i - ) * curBitmap.Width + j - ] == || hitStru[] == false) &&
(grayValues[(i - ) * curBitmap.Width + j] == || hitStru[] == false) &&
(grayValues[(i - ) * curBitmap.Width + j + ] == || hitStru[] == false) &&
(grayValues[i * curBitmap.Width + j - ] == || hitStru[] == false) &&
(grayValues[i * curBitmap.Width + j] == || hitStru[] == false) &&
(grayValues[i * curBitmap.Width + j + ] == || hitStru[] == false) &&
(grayValues[(i + ) * curBitmap.Width + j - ] == || hitStru[] == false) &&
(grayValues[(i + ) * curBitmap.Width + j] == || hitStru[] == false) &&
(grayValues[(i + ) * curBitmap.Width + j + ] == || hitStru[] == false))
{
temp1Array[i * curBitmap.Width + j] = ;
} }
} //应用击不中结构元素进行腐蚀运算
for (int i = ; i < curBitmap.Height - ; i++)
{
for (int j = ; j < curBitmap.Width - ; j++)
{
////当前位置是黑色或者是击不中结构元素的这一位置没有选中
if ((tempArray[(i - ) * curBitmap.Width + j - ] == || missStru[] == false) &&
(tempArray[(i - ) * curBitmap.Width + j] == || missStru[] == false) &&
(tempArray[(i - ) * curBitmap.Width + j + ] == || missStru[] == false) &&
(tempArray[i * curBitmap.Width + j - ] == || missStru[] == false) &&
(tempArray[i * curBitmap.Width + j] == || missStru[] == false) &&
(tempArray[i * curBitmap.Width + j + ] == || missStru[] == false) &&
(tempArray[(i + ) * curBitmap.Width + j - ] == || missStru[] == false) &&
(tempArray[(i + ) * curBitmap.Width + j] == || missStru[] == false) &&
(tempArray[(i + ) * curBitmap.Width + j + ] == || missStru[] == false))
{
temp2Array[i * curBitmap.Width + j] = ;
} }
} //两个腐蚀运算结果再进行“与”操作
for (int i = ; i < bytes; i++)
{
if (temp1Array[i] == && temp2Array[i] == )
{
tempArray[i] = ;
}
else
{
tempArray[i] = ;
}
} grayValues = (byte[])tempArray.Clone(); Marshal.Copy(grayValues, , ptr, bytes);
curBitmap.UnlockBits(bmpData);
} Invalidate();
}
}
C#数字图像处理(十四)击中击不中变换 (Hit-miss)的更多相关文章
- OpenCV击中击不中HMTxingt变换最容易理解的解释
OpenCV击中击不中变换是几个形态变换中相对比较拗口.不容易理解的,给初学者理解带来了很多困难,虽然网上也有许多的公开资料,原理和算法基本上介绍比较清晰,但是是要OpenCV进行形态变换大多还是说得 ...
- c#数字图像处理(四)线性点运算
灰度图像的点运算可分为线性点运算和非线性点运算两种.4.1线性点运算定义线性点运算就是输出灰度级与输入灰度级呈线性关系的点运算.在这种情况下,灰度变换函数的形式为: g(x, y)=pf(x,y)+L ...
- c语言数字图像处理(四):灰度变换
灰度变换 灰度变换函数 s = T(r) 其中r为输入图像在(x, y)点处的灰度值,s为输出图像在(x, y)点处的灰度值 灰度变换的作用 上图所示的两幅T(s)函数的图像曲线,第一幅图可以增强 ...
- 数字图像处理 第四章 P157 小错误
问题 我认为P157中部的卷积公式是错的,f(x)h(x-m)应当写为f(m)h(x-m) 解决方法 为了证明,我就用我蹩脚的python实现一下图4.28左列 源代码如下 import numpy ...
- C++数字图像处理(1)-伽马变换
https://blog.csdn.net/huqiang_823/article/details/80767019 1.算法原理 伽马变换(幂律变换)是常用的灰度变换,是一种简单的图像增强算法 ...
- 【数字图像处理】六.MFC空间几何变换之图像平移、镜像、旋转、缩放具体解释
本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程<数字图像处理>及课件进行解说,主要通过MFC单文档视图实现显示BMP图片空间几何变换.包含图像平移.图形 ...
- 【数字图像处理】五.MFC图像点运算之灰度线性变化、灰度非线性变化、阈值化和均衡化处理具体解释
本文主要讲述基于VC++6.0 MFC图像处理的应用知识,主要结合自己大三所学课程<数字图像处理>及课件进行解说.主要通过MFC单文档视图实现显示BMP图片点运算处理.包含图像灰度线性变换 ...
- 《C++游戏开发》笔记十四 平滑过渡的战争迷雾(二) 实现:真正的迷雾来了
本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9712321 作者:七十一雾央 新浪微博:http:/ ...
- Linux学习总结(十四)—— 查看CPU信息
文章首发于[博客园-陈树义],点击跳转到原文Linux学习总结(十四)-- 查看CPU信息. Linux学习总结(十四)-- 查看CPU信息 商用服务器CPU最常用的是 Intel Xeon 系列,该 ...
随机推荐
- LeetCode3_无重复字符的最长子串(数组&字符串问题)
题目: 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度. 示例 1: 输入: "abcabcbb" 输出: 3 解释: 因为无重复字符的最长子串是 "ab ...
- Hibernate管理Session
Hibernate自身提供了三种管理Session对象的方法 Session对象的生命周期与本地线程绑定 Session对象的生命周期与JTA事务绑定 Hibernate委托程序管理Session对象 ...
- K:缓存数据库双写数据一致性方案
对于缓存和数据库双写,其存在着数据一致性的问题.对于数据一致性要求较高的业务场景,我们通常会选择使用分布式事务(2pc.paxos等)来保证缓存与数据库之间的数据强一致性,但分布式事务的复杂性与对资源 ...
- 2019 ICPC南昌网络赛 B题
英雄灭火问题忽略了一点丫 一个超级源点的事情,需要考虑周全丫 2 #include<cstdio> #include<cstring> #include<queue> ...
- 洛谷$P4001\ [ICPC-Beijing 2006]$狼抓兔子 网络流+对偶图
正解:网络流+对偶图 解题报告: 传送门! $umm$日常看不懂题系列了$kk$.其实就是说,给定一个$n\cdot n$的网格图,求最小割$QwQ$ 然后网格图的话显然是个平面图,又看到数据范围$n ...
- SpringBoot基础架构篇1(SpringBoot、MyBatis-Plus与Thymeleaf)
show me the code and talk to me,做的出来更要说的明白 我是布尔bl,你的支持是我分享的动力! 1 引入 使用 MyBatis-Plus 以及 thymeleaf 实现增 ...
- 漏洞挖掘 | 远程WWW服务支持TRACE请求
允许TRACE方法 漏洞描述 目标WEB服务器启用了TRACE方法.TRACE方法是HTTP(超文本传输)协议定义的一种协议调试方法,该方法使得服务器原样返回任何客户端请求的内容(可能会附加路由中间的 ...
- Linux下离线安装gdb及常用命令汇总
以redhat6.5虚拟机作为例子,由于工作性质,大部分情况linux的软件安装,是采用离线方式的. 1.离线安装gdb 像gcc.g++或者gdb这种常用的工具软件,一般虚拟机都会安装的,如未安装, ...
- 快速开发架构Spring Boot 从入门到精通 附源码
导读 篇幅较长,干货十足,阅读需花费点时间.珍惜原创,转载请注明出处,谢谢! Spring Boot基础 Spring Boot简介 Spring Boot是由Pivotal团队提供的全新框架,其设计 ...
- 微信小程序订阅消息,我踩过的坑都在这里了!
旧的模板消息将在 2020 年 1 月 10 号全面下架,也就是今天,不过貌似现在还可以用!!!我已经改好了,只不过还没有上线,准备坚持到最后一天! 0.订阅消息 简单介绍一下订阅消息的特点: 用户授 ...