C#图像细化:Hilditch细化算法

上理论:

Hilditch 细化算法的步骤为:

对图像从左向右从上向下迭代每个像素,是为一个迭代周期。在每个迭代周期中,对于每一个像素p,如果它同时满足6个条件,则标记它。在当前迭代周期结束时,则把所有标记的像素的值设为背景值。如果某次迭代周期中不存在标记点(即满足6个条件的像素),则算法结束。假设背景值为0,前景值为1,则:

6个条件为:

(I):p 为1,即p不是背景;

(2):x1,x3,x5,x7不全部为1(否则把p标记删除,图像空心了);

(3):x1~x8 中,至少有2个为1(若只有1个为1,则是线段的端点。若没有为1的,则为孤立点);

(4):p的8连通联结数为1;

联结数指在像素p的3*3邻域中,和p连接的图形分量的个数:

(5)假设x3已经标记删除,那么当x3为0时,p的8联通联结数为1;

(6)假设x5已经标记删除,那么当x5为0时,p的8联通联结数为1。

以上的理论选择网络博客:http://www.cnblogs.com/xiaotie/archive/2010/08/12/1797760.html(此博客上有C#版本的Hilditch细化算法,但是使用unsafe的代码不是太好理解的。

我上一个自己写的代码

/// <summary>
        /// Hilditch细化算法
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private int[,] ThinnerHilditch(int[,] input)
        {
            int lWidth = input.GetLength(0);
            int lHeight = input.GetLength(1);

            bool IsModified = true;
            int Counter = 1;
            int[] nnb = new int[9];
            //去掉边框像素
            for (int i = 0; i < lWidth; i++)
            {
                input[i, 0] = 0;
                input[i, lHeight - 1] = 0;
            }
            for (int j = 0; j < lHeight; j++)
            {
                input[0, j] = 0;
                input[lWidth - 1, j] = 0;
            }
            do
            {
                Counter++;
                IsModified = false;
                int[,] nb = new int[3, 3];
                for (int i = 1; i < lWidth; i++)
                {
                    for (int j = 1; j < lHeight; j++)
                    {
                        //条件1必须为黑点
                        if (input[i, j] != 1)
                        {
                            continue;
                        }

                        //取3*3领域
                        for (int m = 0; m < 3; m++)
                        {
                            for (int n = 0; n < 3; n++)
                            {
                                nb[m, n] = input[i - 1 + m, j - 1 + n];
                            }
                        }
                        //复制
                        nnb[0] = nb[2, 1]==1?0:1;
                        nnb[1] = nb[2, 0]==1?0:1;
                        nnb[2] = nb[1, 0]==1?0:1;
                        nnb[3] = nb[0, 0]==1?0:1;
                        nnb[4] = nb[0, 1]==1?0:1;
                        nnb[5] = nb[0, 2]==1?0:1;
                        nnb[6] = nb[1, 2]==1?0:1;
                        nnb[7] = nb[2, 2]==1?0:1;

                        // 条件2:p0,p2,p4,p6 不皆为前景点 
                        if (nnb[0] == 0 && nnb[2] == 0 && nnb[4] == 0 && nnb[6] == 0)
                        {
                            continue;
                        }
                        // 条件3: p0~p7至少两个是前景点 
                        int iCount = 0;
                        for (int ii = 0; ii < 8; ii++)
                        {
                            iCount += nnb[ii];
                        }
                        if (iCount > 6) continue; 
                        
                        // 条件4:联结数等于1 
                        if (DetectConnectivity(nnb) != 1)
                        {
                            continue;
                        }
                        // 条件5: 假设p2已标记删除,则令p2为背景,不改变p的联结数 
                        if (input[i, j - 1] == -1)
                        {
                            nnb[2] = 1;
                            if (DetectConnectivity(nnb) != 1)
                                continue;
                            nnb[2] = 0;
                        }
                        // 条件6: 假设p4已标记删除,则令p4为背景,不改变p的联结数 
                        if (input[i, j + 1] == -1)
                        {
                            nnb[6] = 1;
                            if (DetectConnectivity(nnb) != 1)
                                continue;
                            nnb[6] = 0;
                        }

                        input[i, j] = -1;
                        IsModified = true;
                    }
                }
                for (int i = 0; i < lWidth; i++)
                {
                    for (int j = 0; j < lHeight; j++)
                    {
                        if (input[i, j] == -1)
                        {
                            input[i, j] = 0;
                        }
                    }
                }

            } while (IsModified);

            return input;
        }

希望对大家有用。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值