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 系列,该 ...
随机推荐
- ImportError: No module named 'cx_Oracle'问题处理过程记录,安装python cx_Oracle库
错误如下: E:\pargram>python Python 3.5.2 |Anaconda 4.2.0 (64-bit)| (default, Jul 5 2016, 11:41:13) [M ...
- CUP计算资源争抢通过IIS启用处理器关联解决
由于业务的复杂性,我们在客户环境部署的时候,采用的是预装好在一台机器然后再把机器安装到客户环境,所以为了简单方便,我们把所有的服务都安装到一台机器上面了. 在正常的使用过程中是没有任何问题的.但是当有 ...
- HDU 1969 Pie [二分]
1.题意:一项分圆饼的任务,一堆圆饼共有N个,半径不同,厚度一样,要分给F+1个人.要求每个人分的一样多,圆饼允许切但是不允许拼接,也就是每个人拿到的最多是一个完整饼,或者一个被切掉一部分的饼,要求你 ...
- TestStand 界面重置【小技巧】
有几种情况可能会使用到这个功能: (1)当界面调整的很乱的时候 (2)当界面突然消失的时候(但是软件进程还在)--快捷键 Alt+V 会弹出菜单,再点击Reset UI Configuration即可 ...
- 基于 HTML5 + WebGL 的无人机 3D 可视化系统
前言 近年来,无人机的发展越发迅速,既可民用于航拍,又可军用于侦察,涉及行业广泛,也被称为“会飞的照相机”.但作为军事使用,无人机的各项性能要求更加严格.重要.本系统则是通过 Hightopo 的 ...
- HolidayFileDisPersonViewList.js中的一些基础
1,CSS display 属性 使段落生出行内框: p.inline { display:inline; } none 此元素不会被显示 详细介绍: http://www.w3school.com ...
- IntelliJ Idea中的 Facets 与 Artifacts
在公司和家用电脑上不同版本的idea做实验发现过程中会有些不同,遇到过一些问题,也正是这些问题使得自己能更进一步了解项目构建过程中的细节,特别记录一下. 这个是[温故知新] Java web 开发 ...
- linux 更新jdk
1.上传jdk版本的包 下载JDK地址:http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.h ...
- $vjudge\ CSP-S$专题专练题解
照例先放个链接$QwQ$ $A$ $QwQ$之前写过题解辣. 重新说下趴,就给横坐标纵坐标也开点,然后每个点连向对应横纵坐标边权为$0$,相邻横坐标点之间连边,相邻纵坐标点之间连边,跑个最短路就完事$ ...
- [Abp vNext 源码分析] - 14. EntityFramework Core 的集成
一.简要介绍 在以前的文章里面,我们介绍了 ABP vNext 在 DDD 模块定义了仓储的接口定义和基本实现.本章将会介绍,ABP vNext 是如何将 EntityFramework Core 框 ...