OpenCV中文网站

 找回密码
 立即注册
搜索
热搜: 安装 配置
查看: 4817|回复: 3

C#中图像的细化问题

[复制链接]
发表于 2014-8-14 05:51:46 | 显示全部楼层 |阅读模式
本帖最后由 sunsky 于 2014-8-14 06:02 编辑

Opencv和EMguCV中没有用于图像细化的算法,网上有在opencv下写的图像细化算法,C#下写的图像细化算法都是用纯C#的方式写成的,用的提取像素的方式实现,速度很慢,所以今天我用指针的方式在C#中将图像细化算法写了一下。代码如下:

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



注意:ToThinner(Bitmap srcImg)输入参数srcImg为Bitmap格式的,灰度值为0和255的二值图像。细化算法适用于想细化的线条是黑色,背景是白色的情况,如下面这种图;


01.jpg
如果细化的是线条为白色,背景黑色的,将代码        int step = dstData.Stride;


            for (int i = 0; i < dstData.Height; i++)
            {
                for (int j = 0; j < dstData.Width; j++)
                {
                    if (data[i * step + j] > 128)
                        data[i * step + j] = 0;
                    else
                        data[i * step + j] = 1;
                }
            }
改为:
            int step = dstData.Stride;
            for (int i = 0; i < dstData.Height; i++)
            {
                for (int j = 0; j < dstData.Width; j++)
                {
                    if (data[i * step + j] > 128)
                        data[i * step + j] = 1;
                    else
                        data[i * step + j] = 0;
                }
            }
就可以了。
下面是一幅网格图像:
02.jpg
然后细化后的效果如下:
03.jpg



回复

使用道具 举报

发表于 2015-1-4 09:25:02 | 显示全部楼层

楼主您好!您代码能换成C#的标准行的状态吗?这样不好分辨开始和结束,谢谢!

点评

你把代码复制下来贴入VS中,执行一次格式化操作,即可看到格式化好后的代码了。  发表于 2015-3-14 09:52
回复 支持 反对

使用道具 举报

发表于 2015-3-14 09:49:04 | 显示全部楼层
不错! 使用unsafe code   指针遍历了一副图像并做了像素级的灰度比较后,生成了一副黑白图。这是所谓细化的过程。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|OpenCV中文网站

GMT+8, 2024-4-19 09:45 , Processed in 0.012611 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表