/// <summary>
/// 图形细化
/// </summary>
/// <param name="srcImg"></param>
/// <returns></returns>
public unsafe Bitmap ToThinner(Bitmap srcImg)
{
int iw = srcImg.Width;
int ih = srcImg.Height;
bool bModified; //二值图像修改标志
bool bCondition1; //细化条件1标志
bool bCondition2; //细化条件2标志
bool bCondition3; //细化条件3标志
bool bCondition4; //细化条件4标志
int nCount;
//5X5像素块
byte[,] neighbour = new byte[, ];
//新建临时存储图像
Bitmap NImg = new Bitmap(iw, ih, srcImg.PixelFormat);
bModified = true;
//细化修改标志, 用作循环条件
BitmapData dstData = srcImg.LockBits(new Rectangle(, , iw, ih), ImageLockMode.ReadWrite, srcImg.PixelFormat);
byte* data = (byte*)(dstData.Scan0);
//将图像转换为0,1二值得图像;
int step = dstData.Stride;
for (int i = ; i < dstData.Height; i++)
{
for (int j = ; j < dstData.Width * ; j += )
{
if (data[i * step + j] > )
//如果是白线条,只要将0改成1,将1改成0
data[i * step + j]
= data[i * step + j + ]
= data[i * step + j + ]
= ;
else
data[i * step + j]
= data[i * step + j + ]
= data[i * step + j + ]
= ;
}
} BitmapData dstData1 = NImg.LockBits(new Rectangle(, , iw, ih), ImageLockMode.ReadWrite, NImg.PixelFormat);
byte* data1 = (byte*)(dstData1.Scan0);
int step1 = dstData1.Stride;
//细化循环开始
while (bModified)
{
bModified = false;
//初始化临时二值图像NImg
for (int i = ; i < dstData1.Height; i++)
{
for (int j = ; j < dstData1.Width * ; j++)
{
data1[i * step1 + j] = ;
}
}
for (int i = ; i < ih - ; i++)
{
for (int j = ; j < iw * - ; j += )
{
bCondition1 = false;
bCondition2 = false;
bCondition3 = false;
bCondition4 = false;
if (data[i * step + j] == )
//若图像的当前点为白色,则跳过
continue;
for (int k = ; k < ; k++)
{
//取以当前点为中心的5X5块
for (int l = ; l < ; l++)
{
//1代表黑色, 0代表白色
//neighbour[k, l] = bw[i + k - 2, j + l - 2];
//neighbour[k, l] = data[(i + k - 2) * step + (j + l - 2)];
neighbour[k, l] = data[(i + k - ) * step + (j + l * - )];
}
}
//(1)判断条件2<=n(p)<=6
nCount = neighbour[, ] + neighbour[, ] + neighbour[, ] + neighbour[, ] + neighbour[, ] + neighbour[, ] + neighbour[, ] + neighbour[, ];
if (nCount >= && nCount <= )
bCondition1 = true;
else
{
data1[i * step1 + j] = ;
continue;
//跳过, 加快速度
}
//(2)判断s(p)=1
nCount = ;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (nCount == )
bCondition2 = true;
else
{
data1[i * step1 + j] = ;
continue;
}
//(3)判断p0*p2*p4=0 or s(p2)!=1
if (neighbour[, ] * neighbour[, ] * neighbour[, ] == )
bCondition3 = true;
else
{
nCount = ;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (nCount != )
//s(p2)!=1
bCondition3 = true;
else
{
data1[i * step1 + j] = ;
continue;
}
}
//(4)判断p2*p4*p6=0 or s(p4)!=1
if (neighbour[, ] * neighbour[, ] * neighbour[, ] == )
bCondition4 = true;
else
{
nCount = ;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (neighbour[, ] == && neighbour[, ] == )
nCount++;
if (nCount != )//s(p4)!=1
bCondition4 = true;
}
if (bCondition1 && bCondition2 && bCondition3 && bCondition4)
{
data1[i * step1 + j] = ;
bModified = true;
}
else
{
data1[i * step1 + j] = ;
}
}
}
// 将细化了的临时图像bw_tem[w,h]copy到bw[w,h],完成一次细化
for (int i = ; i < ih - ; i++)
for (int j = ; j < iw * - ; j++)
data[i * step + j] = data1[i * step1 + j];
}
for (int i = ; i < ih - ; i++)
{
for (int j = ; j < iw * - ; j += )
{
if (data[i * step + j] == ) data[i * step + j]
= data[i * step + j + ]
= data[i * step + j + ]
= ; else data[i * step + j]
= data[i * step + j + ]
= data[i * step + j + ]
= ; }
}
srcImg.UnlockBits(dstData);
NImg.UnlockBits(dstData1);
return (srcImg);
}

C# 指针操作图像 细化处理的更多相关文章

  1. C# 指针操作图像 二值化处理

    /// <summary> /// 二值化图像 /// </summary> /// <param name="bmp"></param& ...

  2. 【opencv】图像细化

    [原文:http://blog.csdn.net/qianchenglenger/article/details/19332011] 在我们进行图像处理的时候,有可能需要对图像进行细化,提取出图像的骨 ...

  3. 【OpenCV】三种方式操作图像像素

    OpenCV中,有3种访问每个像素的方法:使用at方法.使用迭代器方法.使用指针 运行如下程序后可以发现使用at方法速度最快. 代码如下: //操作图像像素 #include <opencv2/ ...

  4. OpenCV图像细化的一个例子

    转自:http://blog.csdn.net/zfdxx369/article/details/9091953?utm_source=tuicool 本文是zhang的一篇经典图像细化论文,效果很好 ...

  5. C#指针操作Marshal实例

    static void Main(string[] args) { ,,,}; ,,,}; IntPtr pt = Marshal.AllocHGlobal(a.Length); //从source数 ...

  6. C语言指针操作

    欢迎访问我的新博客:http://www.milkcu.com/blog/ 原文地址:http://www.milkcu.com/blog/archives/pointer-manipulation. ...

  7. Day4:T1小技巧(类似于指针操作)T2搜索+小细节

    Day4:其中有很多小技巧get T1 一直没有听到过像这样的小技巧的略专业名词,有点类似于指针操作,之前有碰到过很多这样的题目 每次都是以不同的形式出现,但是感觉思想还是有点接近的吧(就比如某天有一 ...

  8. C语言数组操作和指针操作谁更高效

    在上一篇博文  代码优化小技巧(持续更新......) 第三条关于数组和指针谁更高效, 意犹未尽, 决定单独拉出一篇来讲 1. 数组和指针操作对比 #include <stdio.h> i ...

  9. Python 编程快速上手 第十七章 操作图像

    前言 在这一章节,讲了关于图像的三个方面的内容: 获得图像的相关信息:例如 RGBA 值,尺寸... 对图像进行编辑操作:例如 旋转,缩放... 在图像上绘制形状:例如 矩形,圆形... [Image ...

随机推荐

  1. Android 的 AlarmManager 和 wakeLock联合使用

    http://stackoverflow.com/questions/6864712/android-alarmmanager-not-waking-phone-up 主要说的是,对于android ...

  2. linux琐碎知识点

    1.awk的使用方式,pattern支持正则表达式 awk 'pattern{action}' {filenames} 其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找 ...

  3. 多字段 java对象排序

    public class ReflexUtil { static Logger logger = LoggerFactory.getLogger(ReflexUtil.class); //getMet ...

  4. effective OC2.0 52阅读笔记(一 熟悉Objective-C)

    第一章:熟悉Objective-C 1 了解objective-c语言的起源 总结:OC为C语言添加了面向对象的特性,是其超集.采用动态绑定的消息结构而非函数调用,也就是说,要在运行时才检查对象类型及 ...

  5. linux 共享内存实现

    说起共享内存,一般来说会让人想起下面一些方法:1.多线程.线程之间的内存都是共享的.更确切的说,属于同一进程的线程使用的是同一个地址空间,而不是在不同地址空间之间进行内存共享:2.父子进程间的内存共享 ...

  6. jquery.validate ajax提交

    页面引入jquery.validate.min.js <style> //引入错误格式     label.error {        display: block;        ma ...

  7. ios调用c#后台接口报文格式

    - NSString *soapMessage = - [NSString stringWithFormat: - @"<?xml version=\"1.0\" ...

  8. 【编程题目】有 n 个长为 m+1 的字符串,如果某个字符串的最后 m 个字符与某个字符串的前 m 个字符匹配...

    37.(字符串)有 n 个长为 m+1 的字符串,如果某个字符串的最后 m 个字符与某个字符串的前 m 个字符匹配,则两个字符串可以联接,问这 n 个字符串最多可以连成一个多长的字符串,如果出现循环, ...

  9. 安装oracleASM

    问题:oracleasm status不能启动 解决方案: [root@localhost ~]# oracleasm statusChecking if ASM is loaded: noCheck ...

  10. iOS MD5加密

    1.MD5加密 Message Digest Algorithm MD5(中文名为消息摘要算法第五版)为计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护.该算法的文件号为RFC 1321 ...