图像处理工具箱

还只是个菜鸟,不过想开个博客,记录一下自己的学习过程!

最近在一家医疗软件公司实习,负责的是OCR(光学字符识别)部分!进行OCR之前难免会碰到图像处理,因此写了一个图像处理工具箱(ImageProcessUtilities),看网上有人讲过在进行OCR之前,进行图像二值化,图像锐化,中值滤波,线性灰度变化,转换为黑白灰度图完全就足够了!

这个工具箱大概也是实现这些功能,首先类视图,

 

下面给出代码,希望大家多批评指下,之后会后续发布OCR检索其他方面的工具,诸如文字后处理的正则表达等!

 public class ImageProcessUtility
    {

        //暂时只对24位图和8位图进行处理

        #region 图像扩边函数
        /// <summary>
        /// 图像扩边函数
        /// </summary>
        /// <param name="width">扩边后图像的宽度</param>
        /// <param name="height">扩边后图像的高度</param>
        /// <param name="inputBitmap">需要扩边的图像</param>
        /// <returns>完成扩边后的图像</returns>
        public static Bitmap ImageExpand(int width, int height, Bitmap inputBitmap)
        {
            try
            {
                Bitmap bitmap = new Bitmap(width, height);
                Graphics g = Graphics.FromImage(bitmap);
                g.Clear(Color.Black);
                int start_X = (width - inputBitmap.Width) / 2;
                int start_Y = (height - inputBitmap.Height) / 2;

                g.DrawImage(inputBitmap, new Point(start_X, start_Y));
                g.Dispose();
                return bitmap;
            }
            catch
            {
                return null;
            }
        }
        #endregion

        #region 图像缩放函数
        /// <summary>
        /// 图像缩放函数
        /// </summary>
        /// <param name="scale">缩放因子</param>
        /// <param name="inputBitmap">需要缩放的图像</param>
        /// <returns>缩放后的图像</returns>
        public static Bitmap ImageResize(double scale, Bitmap inputBitmap)
        {
            try
            {
                int newWidth = Convert.ToInt32(inputBitmap.Width * scale);
                int newHeight = Convert.ToInt32(inputBitmap.Height * scale);
                Bitmap bitmap = new Bitmap(newWidth, newHeight);

                Graphics g = Graphics.FromImage(bitmap);
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

                g.DrawImage(inputBitmap, new Rectangle(0, 0, newWidth, newHeight),
                    new Rectangle(0,0,inputBitmap.Width, inputBitmap.Height), GraphicsUnit.Pixel);                

                g.Dispose();
                return bitmap;
            }
            catch 
            {
                return null;
            }

        }
        #endregion

        #region 转换为8位灰度图像
        /// <summary>
        /// 将图像转换成8位Bitmap图像函数
        /// </summary>
        /// <param name="inputBitmap">要转换的图像</param>
        /// <returns>转换后的图像</returns>
        public static Bitmap ToGray(Bitmap inputBitmap)
        {
            Bitmap bmp = new Bitmap(inputBitmap.Width, inputBitmap.Height, PixelFormat.Format8bppIndexed);

            //设定实例BitmapData相关信息  
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);

            BitmapData data = inputBitmap.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
            //锁定bmp到系统内存中  
            BitmapData data2 = bmp.LockBits(rect, ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

            //获取位图中第一个像素数据的地址  
            IntPtr ptr = data.Scan0;
            IntPtr ptr2 = data2.Scan0;

            int numBytes = data.Stride * data.Height;
            int numBytes2 = data2.Stride * data2.Height;

            int n2 = data2.Stride - bmp.Width;  显示宽度与扫描线宽度的间隙  

            byte[] rgbValues = new byte[numBytes];
            byte[] rgbValues2 = new byte[numBytes2];
            //将bmp数据Copy到申明的数组中  
            Marshal.Copy(ptr, rgbValues, 0, numBytes);
            Marshal.Copy(ptr2, rgbValues2, 0, numBytes2);

            int n = 0;

            for (int y = 0; y < bmp.Height; y++)
            {
                for (int x = 0; x < bmp.Width * 3; x += 3)
                {
                    int i = data.Stride * y + x;

                    double value = rgbValues[i + 2] * 0.299 + rgbValues[i + 1] * 0.587 + rgbValues[i] * 0.114; //计算灰度  

                    rgbValues2[n] = (byte)value;

                    n++;
                }
                n += n2; //跳过差值  
            }

            //将数据Copy到内存指针  
            Marshal.Copy(rgbValues, 0, ptr, numBytes);
            Marshal.Copy(rgbValues2, 0, ptr2, numBytes2);

             下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度  
            ColorPalette tempPalette;
            using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))
            {
                tempPalette = tempBmp.Palette;
            }
            for (int i = 0; i < 256; i++)
            {
                tempPalette.Entries[i] = Color.FromArgb(i, i, i);
            }

            bmp.Palette = tempPalette;


            //从系统内存解锁bmp  
            inputBitmap.UnlockBits(data);
            bmp.UnlockBits(data2);

            return bmp;
        }
        #endregion

        #region 转换为二值图像
        /// <summary>
        /// 图像二值化函数
        /// </summary>
        /// <param name="grayValue">需要二值化的图像</param>
        /// <param name="inputBitmap">阈值</param>
        /// <returns>完成二值化后的图像</returns>
        public static Bitmap ToBinary(int grayValue, Bitmap inputBitmap)
        {
            //获取图像长宽
            int w = inputBitmap.Width;
            int h = inputBitmap.Height;
            //锁定位图信息
            Bitmap dstBitmap = new Bitmap(inputBitmap.Width, inputBitmap.Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            System.Drawing.Imaging.BitmapData srcData = inputBitmap.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            System.Drawing.Imaging.BitmapData dstData = dstBitmap.LockBits(new Rectangle(0, 0, w, h), System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            unsafe
            {

                byte* pIn = (byte*)srcData.Scan0.ToPointer();
                byte* pOut = (byte*)dstData.Scan0.ToPointer();
                byte* p;
                int stride = srcData.Stride;
                int r, g, b;
                //二值化过程
                for (int y = 0; y < h; y++)
                {
                    for (int x = 0; x < w; x++)
                    {
                        p = pIn;
                        r = p[2];
                        g = p[1];
                        b = p[0];
                        //灰度值等于V的为黑色,反之为白色
                        pOut[0] = pOut[1] = pOut[2] = (byte)(((byte)(r << 16 | g << 8 | b) == grayValue)
                        ? 255 : 0);
                        pIn += 3;
                        pOut += 3;
                    }
                    pIn += srcData.Stride - w * 3;
                    pOut += srcData.Stride - w * 3;
                }
                //解除锁定
                inputBitmap.UnlockBits(srcData);
                dstBitmap.UnlockBits(dstData);
                //返回处理后的图像
                return dstBitmap;
            }
        }
        #endregion

        #region 中值滤波
        /// <summary>
        /// 图像中值滤波,在进行滤波前,
        /// 若是RGB图,需要将其转换为灰度图
        /// </summary>
        /// <param name="mode">窗口模式:
        /// 0:3*3窗口
        /// 1:5*5窗口
        /// </param>
        /// <param name="inputBitmap"></param>
        /// <returns></returns>
        public static Bitmap ImageMedianFilter(int mode, Bitmap inputBitmap)
        {
            try
            {
                if (inputBitmap.PixelFormat == PixelFormat.Format24bppRgb)
                    inputBitmap = ToGray(inputBitmap);
                Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
                BitmapData bmpData = inputBitmap.LockBits(rect,
                    ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

                IntPtr ptr = bmpData.Scan0;
                int bytes = bmpData.Stride * bmpData.Height;
                byte[] grayValues = new byte[bytes];
                Marshal.Copy(ptr, grayValues, 0, bytes);

                byte[] tempArray = new byte[bytes];
                for (int i = 0; i < bytes; i++)
                {
                    tempArray[i] = 0;
                }

                switch (mode)
                {
                    case 0:
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                List<byte> sortArray = new List<byte>();
                                sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j - 1]);
                                sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j]);
                                sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j + 1]);
                                sortArray.Add(grayValues[i * bmpData.Stride + j - 1]);
                                sortArray.Add(grayValues[i * bmpData.Stride + j]);
                                sortArray.Add(grayValues[i * bmpData.Stride + j + 1]);
                                sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j - 1]);
                                sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j]);
                                sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j + 1]);

                                sortArray.Sort();
                                tempArray[i * bmpData.Stride + j] = sortArray[4];
                            }
                        }
                        break;
                    case 1:
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                List<byte> sortArray = new List<byte>();
                                sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j - 2]);
                                sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j - 1]);
                                sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j]);
                                sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j + 1]);
                                sortArray.Add(grayValues[(i - 2) * bmpData.Stride + j + 2]);
                                sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j - 2]);
                                sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j - 1]);
                                sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j]);
                                sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j + 1]);
                                sortArray.Add(grayValues[(i - 1) * bmpData.Stride + j + 2]);
                                sortArray.Add(grayValues[i * bmpData.Stride + j - 2]);
                                sortArray.Add(grayValues[i * bmpData.Stride + j - 1]);
                                sortArray.Add(grayValues[i * bmpData.Stride + j]);
                                sortArray.Add(grayValues[i * bmpData.Stride + j + 1]);
                                sortArray.Add(grayValues[i * bmpData.Stride + j + 2]);
                                sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j - 2]);
                                sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j - 1]);
                                sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j]);
                                sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j + 1]);
                                sortArray.Add(grayValues[(i + 1) * bmpData.Stride + j + 2]);
                                sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j - 2]);
                                sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j - 1]);
                                sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j]);
                                sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j + 1]);
                                sortArray.Add(grayValues[(i + 2) * bmpData.Stride + j + 2]);

                                sortArray.Sort();
                                tempArray[i * bmpData.Stride + j] = sortArray[4];
                            }
                        }
                        break;
                    default:
                        break;
                }

                grayValues = (byte[])tempArray.Clone();
                Marshal.Copy(grayValues, 0, ptr, bytes);
                inputBitmap.UnlockBits(bmpData);
                return inputBitmap;
            }
            catch
            {
                return null;
            }
        }
        #endregion

        #region 图像锐化
        /// <summary>
        /// 图像锐化
        /// </summary>
        /// <param name="depth">
        /// 锐化的程序,分布在[0,1],值越大锐化程序越高      
        /// </param>
        /// <param name="inputBitmap">需要锐化的图像</param>
        /// <returns>锐化的结果图</returns>
        public static Bitmap ImageSharpen(double depth, Bitmap inputBitmap)
        {
            if (inputBitmap == null)
                return null;

            if (depth < 0.0)
                depth = 0.0;
            else if (depth > 1.0)
                depth = 1.0;

            if (inputBitmap.PixelFormat == PixelFormat.Format24bppRgb)
                inputBitmap = ToGray(inputBitmap);

            BitmapData srcData = inputBitmap.LockBits(new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height),
                ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);

            IntPtr ptr = srcData.Scan0;
            int bytes = srcData.Stride * srcData.Height;
            byte[] grayValues = new byte[bytes];
            Marshal.Copy(ptr, grayValues, 0, bytes);
            //存储周边边缘的差值
            double temp;

            for (int i = 1; i < srcData.Height - 1; i++)
            {
                for (int j = 1; j < srcData.Width - 1; j++)
                {
                    temp = grayValues[i * srcData.Stride + j] -
                        ((grayValues[(i - 1) * srcData.Stride + j - 1] +
                        grayValues[(i - 1) * srcData.Stride + j] +
                        grayValues[(i - 1) * srcData.Stride + j + 1] +
                        grayValues[i * srcData.Stride + j - 1] +
                        grayValues[i * srcData.Stride + j + 1] +
                        grayValues[(i + 1) * srcData.Stride + j - 1] +
                        grayValues[(i + 1) * srcData.Stride + j] +
                        grayValues[(i + 1) * srcData.Stride + j + 1])) / 8;
                    if (temp < 0.0)
                        temp = 0.0;
                    grayValues[i * srcData.Stride + j] -= Convert.ToByte(temp * depth);

                }
            }

            Marshal.Copy(grayValues, 0, ptr, bytes);
            inputBitmap.UnlockBits(srcData);
            return inputBitmap;

        }
        #endregion

        #region 图像膨胀函数
        /// <summary>
        /// 图像膨胀函数
        /// </summary>
        /// <param name="mode">结构元素
        /// 0:3位水平方向的结构元素
        /// 1:5位水平方向的结构元素
        /// 2:3位垂直方向的结构元素
        /// 3:5位垂直方向的结构元素
        /// 4:3位十字状结构元素
        /// 5:5位十字状结构元素
        /// 6:3位方形结构元素
        /// 7:5位方形结构元素
        /// </param>       
        /// <param name="inputBitmap">需要膨胀的图像</param>
        /// <returns>返回膨胀后的图像</returns>
        public static Bitmap ImageDilate(int mode, Bitmap inputBitmap)
        {
            try
            {
                //先以255作为阈值分割点           
                inputBitmap = ToGray(inputBitmap);
                inputBitmap = ToBinary(255, inputBitmap);


                Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
                //以读写的方式锁定全部位图像素
                System.Drawing.Imaging.BitmapData bmpData = inputBitmap.LockBits(rect,
                    System.Drawing.Imaging.ImageLockMode.ReadWrite,
                    PixelFormat.Format8bppIndexed);
                IntPtr ptr = bmpData.Scan0;

                //将图像数据复制到数组中,用于膨胀操作
                int bytes = bmpData.Stride * bmpData.Height;
                byte[] grayValues = new byte[bytes];
                Marshal.Copy(ptr, grayValues, 0, bytes);

                //设置临时数组,用来存储膨胀操作的结果
                byte[] tempArray = new byte[bytes];
                for (int i = 0; i < bytes; i++)
                    tempArray[i] = 0;

                switch (mode)
                {
                        //3位水平方向的结构元素
                    case 0:
                        for (int i = 0; i < bmpData.Height; i++)
                        {
                            for (int j = 1; j < bmpData.Width-1; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255)
                                    tempArray[i * bmpData.Stride + j] = 255;
                            }
                        }
                        break;

                        //5位水平方向的结构元素
                    case 1:
                        for (int i = 0; i < bmpData.Height; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 2] == 255)
                                    tempArray[i * bmpData.Stride + j] = 255;
                            }
                        }
                        break;

                        //3位垂直方向的结构元素
                    case 2:
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255)
                                    tempArray[i * bmpData.Stride + j] = 255;
                            }
                        }
                        break;

                        //5位垂直方向的结构元素
                    case 3:
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j] == 255)
                                    tempArray[i * bmpData.Stride + j] = 255;
                            }
                        }
                        break;

                        //3位十字形状结构元素
                    case 4:
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255)
                                    tempArray[i * bmpData.Stride + j] = 255;
                            }
                        }
                        break;

                        //5位十字形状结构元素
                    case 5:
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 2] == 255)
                                    tempArray[i * bmpData.Stride + j] = 255;
                            }
                        }
                        break;

                        //3位方形结构元素
                    case 6:
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j + 1] == 255)
                                    tempArray[i * bmpData.Stride + j] = 255;
                            }
                        }
                        break;

                        //5位方形结构元素
                    case 7:
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (grayValues[(i - 2) * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j + 2] == 255)
                                    tempArray[i * bmpData.Stride + j] = 255;
                            }
                        }
                        break;

                    default:
                        break;

                }

                grayValues = (byte[])tempArray.Clone();
                Marshal.Copy(grayValues, 0, ptr, bytes);
                inputBitmap.UnlockBits(bmpData);
                return inputBitmap;
            }
            catch
            {
                return null;
            }
            
        }
        #endregion      

        #region 图像开运算
        /// <summary>
        /// 图像开运算
        /// </summary>
        /// <param name="mode">结构元素
        /// 0:3位水平方向的结构元素
        /// 1:5位水平方向的结构元素
        /// 2:3位垂直方向的结构元素
        /// 3:5位垂直方向的结构元素
        /// 4:3位十字状结构元素
        /// 5:5位十字状结构元素
        /// 6:3位方形结构元素
        /// 7:5位方形结构元素
        /// </param>
        /// <param name="inputBitmap">需要开运算的图像</param>
        /// <returns>开运算后的图像</returns>
        public static Bitmap ImageOpening(int mode, Bitmap inputBitmap)
        {
            try
            {
                //先以255作为阈值分割点
                inputBitmap = ToGray(inputBitmap);
                inputBitmap = ToBinary(255, inputBitmap);

                Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
                System.Drawing.Imaging.BitmapData bmpData = inputBitmap.LockBits(rect,
                    System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
                IntPtr ptr = bmpData.Scan0;
                int bytes = bmpData.Stride * bmpData.Height;
                byte[] grayValues = new byte[bytes];
                System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);


                byte[] temp1Array = new byte[bytes];
                byte[] tempArray = new byte[bytes];
                for (int i = 0; i < bytes; i++)
                {
                    tempArray[i] = temp1Array[i] = 0;
                }

                switch (mode)
                {
                    case 0:
                        //3位水平结构元素
                        //腐蚀运算
                        for (int i = 0; i < bmpData.Height; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 &&
                                    grayValues[i * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[i * bmpData.Stride + j - 1] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //膨胀运算
                        for (int i = 0; i < bmpData.Stride; i++)
                        {
                            for (int j = 1; j < bmpData.Stride - 1; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 ||
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[i * bmpData.Stride + j - 1] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 1:
                        //5位水平结构元素
                        //腐蚀运算
                        for (int i = 0; i < bmpData.Height; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 &&
                                    grayValues[i * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[i * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[i * bmpData.Stride + j + 2] == 255 &&
                                    grayValues[i * bmpData.Stride + j - 2] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //膨胀运算
                        for (int i = 0; i < bmpData.Height; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 ||
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[i * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[i * bmpData.Stride + j + 2] == 255 ||
                                    temp1Array[i * bmpData.Stride + j - 2] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 2:
                        //3位垂直结构元素
                        //腐蚀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //膨胀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 3:
                        //5位垂直结构元素
                        //腐蚀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i - 2) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 2) * bmpData.Stride + j] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //膨胀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i - 2) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i + 2) * bmpData.Stride + j] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 4:
                        //3位十字形结构元素
                        //腐蚀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[i * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[i * bmpData.Stride + j - 1] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //膨胀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[i * bmpData.Stride + j - 1] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 5:
                        //5位十字形结构元素
                        //腐蚀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i - 2) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 2) * bmpData.Stride + j] == 255 &&
                                    grayValues[i * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[i * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[i * bmpData.Stride + j + 2] == 255 &&
                                    grayValues[i * bmpData.Stride + j - 2] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //膨胀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i - 2) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i + 2) * bmpData.Stride + j] == 255 ||
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[i * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[i * bmpData.Stride + j + 2] == 255 ||
                                    temp1Array[i * bmpData.Stride + j - 2] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 6:
                        //3位方形结构元素
                        //腐蚀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[i * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[i * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j + 1] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //膨胀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[i * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j + 1] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 7:
                        //5位方形结构元素
                        //腐蚀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (grayValues[(i - 2) * bmpData.Stride + j - 2] == 255 &&
                                    grayValues[(i - 2) * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[(i - 2) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i - 2) * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[(i - 2) * bmpData.Stride + j + 2] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j - 2] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[(i - 1) * bmpData.Stride + j + 2] == 255 &&
                                    grayValues[i * bmpData.Stride + j - 2] == 255 &&
                                    grayValues[i * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[i * bmpData.Stride + j] == 255 &&
                                    grayValues[i * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[i * bmpData.Stride + j + 2] == 255 &&
                                    grayValues[(i + 2) * bmpData.Stride + j - 2] == 255 &&
                                    grayValues[(i + 2) * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[(i + 2) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 2) * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[(i + 2) * bmpData.Stride + j + 2] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j - 2] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j + 1] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j + 2] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //膨胀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (temp1Array[(i - 2) * bmpData.Stride + j - 2] == 255 ||
                                    temp1Array[(i - 2) * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[(i - 2) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i - 2) * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[(i - 2) * bmpData.Stride + j + 2] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j - 2] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[(i - 1) * bmpData.Stride + j + 2] == 255 ||
                                    temp1Array[i * bmpData.Stride + j - 2] == 255 ||
                                    temp1Array[i * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[i * bmpData.Stride + j] == 255 ||
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[i * bmpData.Stride + j + 2] == 255 ||
                                    temp1Array[(i + 2) * bmpData.Stride + j - 2] == 255 ||
                                    temp1Array[(i + 2) * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[(i + 2) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i + 2) * bmpData.Stride + j + 1] == 25 ||
                                    temp1Array[(i + 2) * bmpData.Stride + j + 2] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j - 2] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j - 1] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j + 1] == 255 ||
                                    temp1Array[(i + 1) * bmpData.Stride + j + 2] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    default:
                        break;
                }


                grayValues = (byte[])tempArray.Clone();

                System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
                inputBitmap.UnlockBits(bmpData);
                return inputBitmap;

            }
            catch
            {
                return null;
            }
            
        }
        #endregion

        #region 图像闭运算
        /// <summary>
        /// 图像闭运算
        /// </summary>
        /// <param name="mode">结构元素
        /// 0:3位水平方向的结构元素
        /// 1:5位水平方向的结构元素
        /// 2:3位垂直方向的结构元素
        /// 3:5位垂直方向的结构元素
        /// 4:3位十字状结构元素
        /// 5:5位十字状结构元素
        /// 6:3位方形结构元素
        /// 7:5位方形结构元素
        /// </param>
        /// <param name="inputBitmap">需要闭运算的图像</param>
        /// <returns>闭运算后的结果</returns>
        public static Bitmap ImageClosing(int mode, Bitmap inputBitmap)
        {
            try
            {
                //先以255作为阈值分割点
                inputBitmap = ToGray(inputBitmap);
                inputBitmap = ToBinary(255, inputBitmap);

                Rectangle rect = new Rectangle(0, 0, inputBitmap.Width, inputBitmap.Height);
                System.Drawing.Imaging.BitmapData bmpData = inputBitmap.LockBits(rect,
                    System.Drawing.Imaging.ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
                IntPtr ptr = bmpData.Scan0;
                int bytes = bmpData.Stride * bmpData.Height;
                byte[] grayValues = new byte[bytes];
                System.Runtime.InteropServices.Marshal.Copy(ptr, grayValues, 0, bytes);


                byte[] temp1Array = new byte[bytes];
                byte[] tempArray = new byte[bytes];
                for (int i = 0; i < bytes; i++)
                {
                    tempArray[i] = temp1Array[i] = 0;
                }

                switch (mode)
                {
                    case 0:
                        //3位水平结构元素
                        //膨胀运算
                        for (int i = 0; i < bmpData.Height; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //腐蚀运算
                        for (int i = 0; i < bmpData.Stride; i++)
                        {
                            for (int j = 1; j < bmpData.Stride - 1; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 &&
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[i * bmpData.Stride + j - 1] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 1:
                        //5位水平结构元素
                        //膨胀运算
                        for (int i = 0; i < bmpData.Height; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 2] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //腐蚀运算
                        for (int i = 0; i < bmpData.Height; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 &&
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[i * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[i * bmpData.Stride + j + 2] == 255 &&
                                    temp1Array[i * bmpData.Stride + j - 2] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 2:
                        //3位垂直结构元素
                        //膨胀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //腐蚀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 3:
                        //5位垂直结构元素
                        //膨胀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //腐蚀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 0; j < bmpData.Width; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i - 2) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i + 2) * bmpData.Stride + j] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 4:
                        //3位十字形结构元素
                        //膨胀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //腐蚀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[i * bmpData.Stride + j - 1] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 5:
                        //5位十字形结构元素
                        //膨胀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 2] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //腐蚀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i - 2) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i + 2) * bmpData.Stride + j] == 255 &&
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[i * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[i * bmpData.Stride + j + 2] == 255 &&
                                    temp1Array[i * bmpData.Stride + j - 2] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 6:
                        //3位方形结构元素
                        //膨胀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j + 1] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //腐蚀运算
                        for (int i = 1; i < bmpData.Height - 1; i++)
                        {
                            for (int j = 1; j < bmpData.Width - 1; j++)
                            {
                                if (temp1Array[i * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[i * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j + 1] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    case 7:
                        //5位方形结构元素
                        //膨胀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (grayValues[(i - 2) * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i - 2) * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i - 1) * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[i * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[i * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i + 2) * bmpData.Stride + j + 2] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j - 2] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j - 1] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j] == 255 &&
                                    grayValues[(i + 1) * bmpData.Stride + j + 1] == 255 ||
                                    grayValues[(i + 1) * bmpData.Stride + j + 2] == 255)
                                {
                                    temp1Array[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        //腐蚀运算
                        for (int i = 2; i < bmpData.Height - 2; i++)
                        {
                            for (int j = 2; j < bmpData.Width - 2; j++)
                            {
                                if (temp1Array[(i - 2) * bmpData.Stride + j - 2] == 255 &&
                                    temp1Array[(i - 2) * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[(i - 2) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i - 2) * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[(i - 2) * bmpData.Stride + j + 2] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j - 2] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[(i - 1) * bmpData.Stride + j + 2] == 255 &&
                                    temp1Array[i * bmpData.Stride + j - 2] == 255 &&
                                    temp1Array[i * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[i * bmpData.Stride + j] == 255 &&
                                    temp1Array[i * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[i * bmpData.Stride + j + 2] == 255 &&
                                    temp1Array[(i + 2) * bmpData.Stride + j - 2] == 255 &&
                                    temp1Array[(i + 2) * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[(i + 2) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i + 2) * bmpData.Stride + j + 1] == 25 &&
                                    temp1Array[(i + 2) * bmpData.Stride + j + 2] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j - 2] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j - 1] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j + 1] == 255 &&
                                    temp1Array[(i + 1) * bmpData.Stride + j + 2] == 255)
                                {
                                    tempArray[i * bmpData.Stride + j] = 255;
                                }

                            }
                        }
                        break;
                    default:
                        break;
                }

                grayValues = (byte[])tempArray.Clone();

                System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
                inputBitmap.UnlockBits(bmpData);
                return inputBitmap;

            }
            catch
            {
                return null;
            }
        }
        #endregion

        


    }

 

转载于:https://www.cnblogs.com/yuchao/archive/2010/10/29/1864457.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值