• 图像轮廓的提取


    对图像边缘提取,常见的方式是先对图片进行灰度处理,然后再利用图像梯度算法提取出边框。我们先来看效果图

     

    经过处理后的前后对比,可以看到,图形的轮廓已经大致提取了。现在来看实现的代码

    using System;
    using System.Collections.Generic;
    using System.Drawing;
    using System.IO;
    using System.Linq;
    using System.Text;
    
    namespace BitmapOutlineSimulate
    {
        public class BitmapOutline
        {
            #region 内部变量
            private Bitmap _bitmap = null;
            #endregion
    
            public BitmapOutline(Bitmap bitmap)
            {
                _bitmap = bitmap;
            }
    
            #region Calculate
            public Bitmap Calculate(GradientTypeEnum gradientType, int threshold)
            {
                Bitmap grayBitmap = new Bitmap(_bitmap.Width, _bitmap.Height);
                for (int i = 0; i < _bitmap.Width; i++)
                {
                    for (int j = 0; j < _bitmap.Height; j++)
                    {
                        //得到像素的原始色彩        
                        var oColor = _bitmap.GetPixel(i, j);
                        //得到该色彩的亮度
                        var brightness = oColor.GetBrightness();
                        //用该亮度计算灰度
                        var gRGB = (int)(brightness * 255);
                        //组成灰度色彩
                        var gColor = Color.FromArgb(gRGB, gRGB, gRGB);
                        //最后将该灰度色彩赋予该像素
                        grayBitmap.SetPixel(i, j, gColor);
                    }
                }
    
                var gradientTemplate = Gradient.GetGradientTemplate(gradientType);
    
    
                var destBitmap = EdgeDectect(grayBitmap, gradientTemplate, threshold);
                return destBitmap;
            }
    
            //template为模板,nThreshold是一个阈值,
            //用来将模板游历的结果(也就是梯度)进行划分。
            //大于阈值的和小于阈值的分别赋予两种颜色,白或黑来标志边界和背景
            private Bitmap EdgeDectect(Bitmap grayBitmap, int[,] template, int nThreshold)
            {
                var destBitmap = new Bitmap(grayBitmap.Width, grayBitmap.Height);
                //取出和模板等大的原图中的区域
                int[,] gRGB = new int[3, 3];
                //模板值结果,梯度
                int templateValue = 0;
                //遍历灰度图中每个像素            
                for (int i = 1; i < grayBitmap.Width - 1; i++)
                {
                    for (int j = 1; j < grayBitmap.Height - 1; j++)
                    {
                        //取得模板下区域的颜色,即灰度
                        gRGB[0, 0] = grayBitmap.GetPixel(i - 1, j - 1).R;
                        gRGB[0, 1] = grayBitmap.GetPixel(i - 1, j).R;
                        gRGB[0, 2] = grayBitmap.GetPixel(i - 1, j + 1).R;
                        gRGB[1, 0] = grayBitmap.GetPixel(i, j - 1).R;
                        gRGB[1, 1] = grayBitmap.GetPixel(i, j).R;
                        gRGB[1, 2] = grayBitmap.GetPixel(i, j + 1).R;
                        gRGB[2, 0] = grayBitmap.GetPixel(i + 1, j - 1).R;
                        gRGB[2, 1] = grayBitmap.GetPixel(i + 1, j).R;
                        gRGB[2, 2] = grayBitmap.GetPixel(i + 1, j + 1).R;
                        //按模板计算
                        for (int m = 0; m < 3; m++)
                        {
                            for (int n = 0; n < 3; n++)
                            {
                                templateValue += template[m, n] * gRGB[m, n];
                            }
                        }
                        //将梯度之按阈值分类,并赋予不同的颜色
                        if (templateValue > nThreshold)
                        {
                            destBitmap.SetPixel(i, j, Color.FromArgb(255, 255, 255)); //白
                        }
                        else
                        {
                            destBitmap.SetPixel(i, j, Color.FromArgb(0, 0, 0)); //黑
                        }
                        templateValue = 0;
                    }
                }
                return destBitmap;
            }
            #endregion
        }
    }
    
    在Calculate函数中,先对图片进行了灰度处理,其原理就是获取图片的亮度然后与RGB色运算得到。

    在灰度处理后,使用图像梯度和阈值对图像进行处理。选择不同的梯度和阈值会处理出不同的结果,上图是使用Lapacian梯度和阈值125计算的结果。下面梯度的代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace BitmapOutlineSimulate
    {
        /// <summary>
        /// 梯度
        /// </summary>
        public class Gradient
        {
            #region 常量
            public static int[,] Lapacian =
            {
                { 1,1,1},
                { 1,-8,1},
                { 1,1,1}
            };
    
            /// <summary>
            /// Sobel算子-水平
            /// </summary>
            public static int[,] Sobel_Horizontal =
            {
                 { -1,-2,-1},
                { 0,0,0},
                { 1,2,1}
            };
    
            /// <summary>
            /// Sobel算子-垂直
            /// </summary>
            public static int[,] Sobel_Vertical =
           {
                 { -1,0,1},
                { -2,0,2},
                { -1,0,1}
            };
    
            /// <summary>
            /// Sobel算子-对角线1
            /// </summary>
            public static int[,] Sobel_Diagonal1 =
            {
                 { 0,1,2},
                { -1,0,1},
                { -2,-1,0}
            };
    
            /// <summary>
            /// Sobel算子-对角线2
            /// </summary>
            public static int[,] Sobel_Diagonal2 =
            {
                { -2,-1,0},
                { -1,0,1},
                { 0,1,2}
            };
    
            /// <summary>
            /// Prewitt算子-水平
            /// </summary>
            public static int[,] Prewitt_Horizontal =
            {
                { -1,-1,-1},
                { 0,0,0},
                { 1,1,1}
            };
    
            /// <summary>
            /// Prewitt算子-垂直
            /// </summary>
            public static int[,] Prewitt_Vertical =
            {
                { -1,0,1},
                { -1,0,1},
                { -1,0,1}
            };
    
    
            /// <summary>
            /// Prewitt算子-对角线1
            /// </summary>
            public static int[,] Prewitt_Diagonal1 =
            {
                { 0,1,1},
                { -1,0,1},
                { -1,-1,0}
            };
    
            /// <summary>
            /// Prewitt算子-对角线2
            /// </summary>
            public static int[,] Prewitt_Diagonal2 =
            {
                { -1,-1,0},
                { -1,0,1},
                { 0,1,1}
            };
            #endregion
    
            public static int[,] GetGradientTemplate(GradientTypeEnum gradientType)
            {
                int[,] gradientTemplate = null;
                switch (gradientType)
                {
                    case GradientTypeEnum.Lapacian:
                        {
                            gradientTemplate = Lapacian;
                            break;
                        }
                    case GradientTypeEnum.Sobel_Horizontal:
                        {
                            gradientTemplate = Sobel_Horizontal;
                            break;
                        }
                    case GradientTypeEnum.Sobel_Vertical:
                        {
                            gradientTemplate = Sobel_Vertical;
                            break;
                        }
                    case GradientTypeEnum.Sobel_Diagonal1:
                        {
                            gradientTemplate = Sobel_Diagonal1;
                            break;
                        }
                    case GradientTypeEnum.Sobel_Diagonal2:
                        {
                            gradientTemplate = Sobel_Diagonal2;
                            break;
                        }
                    case GradientTypeEnum.Prewitt_Horizontal:
                        {
                            gradientTemplate = Prewitt_Horizontal;
                            break;
                        }
                    case GradientTypeEnum.Prewitt_Vertical:
                        {
                            gradientTemplate = Prewitt_Vertical;
                            break;
                        }
                    case GradientTypeEnum.Prewitt_Diagonal1:
                        {
                            gradientTemplate = Prewitt_Diagonal1;
                            break;
                        }
                    case GradientTypeEnum.Prewitt_Diagonal2:
                        {
                            gradientTemplate = Prewitt_Diagonal2;
                            break;
                        }
                    default:
                        break;
                }
                return gradientTemplate;
            }
        }
    }
    

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace BitmapOutlineSimulate
    {
        public enum GradientTypeEnum
        {
            Lapacian,
    
            /// <summary>
            /// Sobel算子-水平
            /// </summary>
            Sobel_Horizontal,
    
            /// <summary>
            /// Sobel算子-垂直
            /// </summary>
            Sobel_Vertical,
    
            /// <summary>
            /// Sobel算子-对角线1
            /// </summary>
            Sobel_Diagonal1,
    
            /// <summary>
            /// Sobel算子-对角线2
            /// </summary>
            Sobel_Diagonal2,
    
            /// <summary>
            /// Prewitt算子-水平
            /// </summary>
            Prewitt_Horizontal,
    
            /// <summary>
            /// Prewitt算子-垂直
            /// </summary>
            Prewitt_Vertical,
    
            /// <summary>
            /// Prewitt算子-对角线1
            /// </summary>
            Prewitt_Diagonal1,
    
            /// <summary>
            /// Prewitt算子-对角线2
            /// </summary>
            Prewitt_Diagonal2
        }
    }
    
    灰度算法参考文章http://blog.csdn.net/chinaxhb/article/details/4038050
    图像梯度参考文章http://blog.csdn.net/swj110119/article/details/51777422

    转载请注明出处。

  • 相关阅读:
    Linux系统NBD驱动安装拓展篇
    关于测试策略,测试方针,测试计划,测试方案的理解
    IE9 以下版本浏览器兼容HTML5的方法,使用的静态资源的html5shiv包:
    数组实现队列
    Python中的文件夹、包、模块、类、函数
    python单元测试框架pytest 和unittest
    Python语法学习笔记
    Appium遇到的问题
    测试质量体系建设
    运营需求测试点
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7604877.html
Copyright © 2020-2023  润新知