zoukankan      html  css  js  c++  java
  • 黑白二值图像周长测量--C#实现

    假设是单像素线白色用1(对应RGB(255,0,0))表示,背景用0(对应RBG(0,0,0))表示。

    考虑3种类型的边界 水平方向  0->1  1->0   类似垂直方向也是0->1  1->0

    如果是单像素,如果水平检测时 发现 0->1 或1->0变动,那么都将 mapX[i,j] 设置成1,注意是白色像素对应的位置

    类似的处理也针对垂直方向mapY[i,j]

    如果以个mapY[i,j] 与mapX[i,j] 同时标记成了1,那么意味着这个像素是斜方向,那么按sqrt(2)来记录。

    注意一:以直角三角型为例,构成边的线段粗细大于1个像素,那么求出的结果是翻倍的,因为边界出现了2次。

    注意二:以直角三角型为例,如果直角三角型内部是填充成白色的(前景色1),那么求出的结果是一样的,因为边界只出现一次。

    完整代码如下,需要传入二值图片。

         /// <summary>
            /// 二值图片前景是白背景是黑
            /// 测试白像素的边长
            /// 正负 pi/4   ,3pi/4 计1.414
            /// 其余按1计
            /// </summary>
            /// <param name="bm"></param>
            public static double? SegmentLen(Bitmap bm)
            {
    
                var map = new byte[bm.Width, bm.Height];
                var mapX = new byte[bm.Width, bm.Height];
                var mapY = new byte[bm.Width, bm.Height];
    
                for (int i = 0; i < bm.Width; i++)
                {
                    for (int j = 0; j < bm.Height; j++)
                    {
                        var c = bm.GetPixel(i, j);
                        if (c.R == 255)
                        {
                            map[i, j] = 1;
           
                        }
                        else
                        {
                            map[i, j] = 0;
    
                        }
                        mapX[i, j] = 0;
                        mapY[i, j] = 0;
                    }
                }
                //水平边界检测
                for (int i = 1; i < bm.Width - 1; i++)
                {
    
                    for (int j = 1; j < bm.Height - 1; j++)
                    {
                        if (map[i, j] == 1 && map[i, j - 1] == 0) mapX[i, j] = 1;
                        if (map[i, j] == 0 && map[i, j - 1] == 1) mapX[i, j - 1] = 1;
    
                    }
                }
                //垂直边界检测
                for (int i = 1; i < bm.Width - 1; i++)
                {
    
                    for (int j = 1; j < bm.Height - 1; j++)
                    {
                        if (map[i, j] == 1 && map[i - 1, j] == 0) mapY[i, j] = 1;
                        if (map[i, j] == 0 && map[i - 1, j] == 1) mapY[i - 1, j] = 1;
    
                    }
                }
                var len = 0.0d;
                for (int i = 0; i < bm.Width; i++)
                {
    
                    for (int j = 0; j < bm.Height; j++)
                    {
    
                        if (mapY[i, j] == 1 && mapX[i, j] == 1)
                        {
                            len +=  1.414;
                        }
                        else if (mapX[i, j] == 1 || mapY[i, j] == 1)
                        {
                            len += 1;
                        }
                    }
                }
                return len;
    
            }
    View Code

     类似的调用代码

    var filename = @"C: 2z4_3.jpg";
    pictureBox1.ImageLocation = filename;
    var tImg = new Bitmap(filename);

    tImg = GenBinaryImgByThreshold(tImg, 80);
    tImg = BorderCheck.FullScanBoundrExtract(tImg);
    var len = BorderCheck.SegmentLen(tImg);
    Console.WriteLine(len);
    ShowImg(tImg);

            public Bitmap GenBinaryImgByThreshold(Bitmap bm, int threshold)
            {
                Color white = Color.FromArgb(255, 255, 255);
                Color black = Color.FromArgb(0, 0, 0);
                Color c = new Color();
                int r;
                Bitmap box1 = new Bitmap(bm.Width, bm.Height);
                for (int i = 0; i < bm.Width; i++)
                {
                    for (int j = 0; j < bm.Height; j++)
                    {
                        c = bm.GetPixel(i, j);
                        r = (c.R + c.G + c.B) / 3 ;
                        if (r > threshold)
                        {
                            box1.SetPixel(i, j, black);
                        }
                        else
                        {
                            box1.SetPixel(i, j, white);
                        }
                    }
                }
              return box1;
            }
    View Code

     上文涉及到的边界抽取函数:

            /// <summary>
            /// 黑白图片全图检测边界抽取
            /// </summary>
            public static Bitmap FullScanBoundrExtract(Bitmap bm)
            {
                var box1 = new Bitmap(bm);//输入使用bm.Width,bm.Height,保留的点是透明的。
                var b = Color.FromArgb(255,0, 0, 0);
                var w = Color.FromArgb(255,255, 255, 255);
                var map = new Int16[bm.Width, bm.Height];
                var map2 = new Int16[bm.Width, bm.Height];
                for (int i = 0; i < bm.Width; i++)
                {
    
                    for (int j = 0; j < bm.Height; j++)
                    {
                        var c = bm.GetPixel(i, j);
                        if (c.R == 255)
                        {
                            map[i, j] = 1;
                        }
                        else
                        {
                            map[i, j] = 0;
                            box1.SetPixel(i, j, b);
                        }
                        //map2[i, j] = 0;
                    }
                }
    
                for (int i = 1; i < bm.Width - 1; i++)
                {
    
                    for (int j = 1; j < bm.Height - 1; j++)
                    {
                        if (map[i, j] == 1 && map[i, j - 1] == 0) map2[i, j] = 1;
                        if (map[i, j] == 0 && map[i, j - 1] == 1) map2[i, j - 1] = 1;
    
                    }
                }
                for (int i = 1; i < bm.Width - 1; i++)
                {
    
                    for (int j = 1; j < bm.Height - 1; j++)
                    {
                        if (map[i, j] == 1 && map[i - 1, j] == 0) map2[i, j] = 1;
                        if (map[i, j] == 0 && map[i - 1, j] == 1) map2[i - 1, j] = 1;
    
                    }
                }
                for (int i = 0; i < bm.Width; i++)
                {
    
                    for (int j = 0; j < bm.Height; j++)
                    {
                        if (map2[i, j] == 0)
                        {
    
                            box1.SetPixel(i, j, b);
                        }
                    }
                }
                return box1;
            }
    View Code
  • 相关阅读:
    看板娘相关源码介绍
    Spring框架实体bean转json返回前端报错:Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)
    Spring Data JPA介绍以及dao层(持久层)标准接口或自定义方法规则
    BeanNotOfRequiredTypeException:Bean named 'XXXX' is expected to be of type 'XXX' but was actually of type 'com.sun.proxy.$Proxy211'
    RedisDesktopManager的编译
    Spring-Boot中@Scheduled注解不生效
    @Async 注解不生效
    使用MongoTemplate,启动时候报错:org.springframework.beans.factory.BeanCreationException
    【个人经验之谈】计算机相关的就业、培训等问题解疑答惑
    简单java mail demo收发邮件例子,各种邮件类型
  • 原文地址:https://www.cnblogs.com/wdfrog/p/9370178.html
Copyright © 2011-2022 走看看