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
  • 相关阅读:
    Mybatis学习(2)原始dao开发和使用mapper接口代理开发
    Mybatis学习(1)
    Leetcode | Merge Intervals
    GDB打印STL容器内容
    LeetCode | Max Points on a Line
    最长不减子序列【转】
    LeetCode | Evaluate Reverse Polish Notation
    LeetCode | Word Ladder II
    LeetCode | Valid Number
    LeetCode | Set Matrix Zeroes
  • 原文地址:https://www.cnblogs.com/wdfrog/p/9370178.html
Copyright © 2011-2022 走看看