QQ交流群:110826636

Sobel算法

最近看了一些Sobel算法,并试了一下,源码如下:

private void Sobel(Bitmap img) {
            int width = img.Width;
            int height = img.Height;

            int[,] Gx = new int[3, 3]{ {-1, 0, 1 },
                                       {-2, 0, 2 } ,
                                       {-1, 0, 1 } };

            int[,] Gy = new int[3, 3]{ {-1,-2,-1},
                                       { 0, 0, 0 },
                                       { 1, 2, 1}};

            int[,] TotalGx = new int[img.Width, img.Height];
            int[,] TotalGy = new int[img.Width, img.Height];
            int[,] GTotal = new int[img.Width, img.Height];


            Bitmap bitmapTemp = new Bitmap(img.Width, img.Height, PixelFormat.Format24bppRgb);
            
            LockBitmap lockBitmap1 = new LockBitmap(bitmapTemp);
            lockBitmap1.LockBits();


            LockBitmap lockBitmap = new LockBitmap(img);
            lockBitmap.LockBits();
            for (int i = 1; i < img.Width - 1; i++)
            {
                for (int j = 1; j < img.Height - 1; j++)
                {
                    Color a = lockBitmap.GetPixel(i - 1, j - 1);//[0][0]
                    Color b = lockBitmap.GetPixel(i - 1, j);    //[0][1]
                    Color c = lockBitmap.GetPixel(i - 1, j + 1);//[0][2]
                    
                    Color d = lockBitmap.GetPixel(i, j - 1);    //[1][0]
                    Color f = lockBitmap.GetPixel(i, j);        //[1][1]
                    Color g = lockBitmap.GetPixel(i, j + 1);    //[1][2]

                    Color h = lockBitmap.GetPixel(i + 1, j - 1);//[2][0]
                    Color l = lockBitmap.GetPixel(i + 1, j);    //[2][1]
                    Color n = lockBitmap.GetPixel(i + 1, j + 1); //[2][2]


                    TotalGx[i, j] = Gx[0, 0] * Avg(a) + Gx[0, 1] * Avg(b) + Gx[0, 2] * Avg(c)
                                   + Gx[1, 0] * Avg(d) + Gx[1, 1] * Avg(f) + Gx[1, 2] * Avg(g)
                                   + Gx[2, 0] * Avg(h) + Gx[2, 1] * Avg(l) + Gx[2, 2] * Avg(n);




                    //if (TotalGx[i, j] < 0) { TotalGx[i, j] = 0; }
                    //if (TotalGx[i, j] > 255) { TotalGx[i, j] = 255; }

                    TotalGy[i, j] = Gy[0, 0] * Avg(a) + Gy[0, 1] * Avg(b) + Gy[0, 2] * Avg(c)
                                  + Gy[1, 0] * Avg(d) + Gy[1, 1] * Avg(f) + Gy[1, 2] * Avg(g)
                                  + Gy[2, 0] * Avg(h) + Gy[2, 1] * Avg(l) + Gy[2, 2] * Avg(n);


                    //if (TotalGy[i, j] < 0) { TotalGy[i, j] = 0; }
                    //if (TotalGy[i, j] > 255) { TotalGy[i, j] = 255; }



                    //GTotal[i, j] = TotalGx[i, j] + TotalGy[i, j];
                    GTotal[i, j] = (int)Math.Sqrt(TotalGx[i, j] * TotalGx[i, j] + TotalGy[i, j] * TotalGy[i, j]);

                    if (GTotal[i, j] >= 255)
                    { GTotal[i, j] = 255; }

                    if (GTotal[i, j] < 0)
                    { GTotal[i, j] = 0; }
                    //bitmapTemp.SetPixel(i, j, Color.FromArgb(GTotal[i, j], GTotal[i ,j], GTotal[i, j]));
                    lockBitmap1.SetPixel(i, j, Color.FromArgb(GTotal[i, j], GTotal[i, j], GTotal[i, j]));
                }
            }
            lockBitmap1.UnlockBits();
            lockBitmap.UnlockBits();
            pictureBox2.Image = lockBitmap1.GetBitmap();

        }

 

public class LockBitmap
    {
        Bitmap source = null;
        IntPtr Iptr = IntPtr.Zero;
        BitmapData bitmapData = null;

        public byte[] Pixels { get; set; }
        public int Depth { get; private set; }
        public int Width { get; private set; }
        public int Height { get; private set; }

        public LockBitmap(Bitmap source)
        {
            this.source = source;
        }

        public Bitmap GetBitmap() { return this.source; }

        /// <summary>
        /// Lock bitmap data
        /// </summary>
        public void LockBits()
        {
            try
            {
                // Get width and height of bitmap
                Width = source.Width;
                Height = source.Height;

                // get total locked pixels count
                int PixelCount = Width * Height;

                // Create rectangle to lock
                Rectangle rect = new Rectangle(0, 0, Width, Height);

                // get source bitmap pixel format size
                Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat);

                // Check if bpp (Bits Per Pixel) is 8, 24, or 32
                if (Depth != 8 && Depth != 24 && Depth != 32)
                {
                    throw new ArgumentException("Only 8, 24 and 32 bpp images are supported.");
                }

                // Lock bitmap and return bitmap data
                bitmapData = source.LockBits(rect, ImageLockMode.ReadWrite,
                                             source.PixelFormat);

                // create byte array to copy pixel values
                int step = Depth / 8;
                Pixels = new byte[PixelCount * step];
                Iptr = bitmapData.Scan0;

                // Copy data from pointer to array
                Marshal.Copy(Iptr, Pixels, 0, Pixels.Length);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// Unlock bitmap data
        /// </summary>
        public void UnlockBits()
        {
            try
            {
                // Copy data from byte array to pointer
                Marshal.Copy(Pixels, 0, Iptr, Pixels.Length);

                // Unlock bitmap data
                source.UnlockBits(bitmapData);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        /// <summary>
        /// Get the color of the specified pixel
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <returns></returns>
        public Color GetPixel(int x, int y)
        {
            Color clr = Color.Empty;

            // Get color components count
            int cCount = Depth / 8;

            // Get start index of the specified pixel
            int i = ((y * Width) + x) * cCount;

            if (i > Pixels.Length - cCount)
                throw new IndexOutOfRangeException();

            if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha
            {
                byte b = Pixels[i];
                byte g = Pixels[i + 1];
                byte r = Pixels[i + 2];
                byte a = Pixels[i + 3]; // a
                clr = Color.FromArgb(a, r, g, b);
            }
            if (Depth == 24) // For 24 bpp get Red, Green and Blue
            {
                byte b = Pixels[i];
                byte g = Pixels[i + 1];
                byte r = Pixels[i + 2];
                clr = Color.FromArgb(r, g, b);
            }
            if (Depth == 8)
            // For 8 bpp get color value (Red, Green and Blue values are the same)
            {
                byte c = Pixels[i];
                clr = Color.FromArgb(c, c, c);
            }
            return clr;
        }

        /// <summary>
        /// Set the color of the specified pixel
        /// </summary>
        /// <param name="x"></param>
        /// <param name="y"></param>
        /// <param name="color"></param>
        public void SetPixel(int x, int y, Color color)
        {
            // Get color components count
            int cCount = Depth / 8;

            // Get start index of the specified pixel
            int i = ((y * Width) + x) * cCount;

            if (Depth == 32) // For 32 bpp set Red, Green, Blue and Alpha
            {
                Pixels[i] = color.B;
                Pixels[i + 1] = color.G;
                Pixels[i + 2] = color.R;
                Pixels[i + 3] = color.A;
            }
            if (Depth == 24) // For 24 bpp set Red, Green and Blue
            {
                Pixels[i] = color.B;
                Pixels[i + 1] = color.G;
                Pixels[i + 2] = color.R;
            }
            if (Depth == 8)
            // For 8 bpp set color value (Red, Green and Blue values are the same)
            {
                Pixels[i] = color.B;
            }
        }

        //public Color GetPixel(int x, int y)
        //{
        //    unsafe
        //    {
        //        byte* ptr = (byte*)Iptr;
        //        ptr = ptr + bitmapData.Stride * y;
        //        ptr += Depth * x / 8;
        //        Color c = Color.Empty;
        //        if (Depth == 32)
        //        {
        //            int a = ptr[3];
        //            int r = ptr[2];
        //            int g = ptr[1];
        //            int b = ptr[0];
        //            c = Color.FromArgb(a, r, g, b);
        //        }
        //        else if (Depth == 24)
        //        {
        //            int r = ptr[2];
        //            int g = ptr[1];
        //            int b = ptr[0];
        //            c = Color.FromArgb(r, g, b);
        //        }
        //        else if (Depth == 8)
        //        {
        //            int r = ptr[0];
        //            c = Color.FromArgb(r, r, r);
        //        }
        //        return c;
        //    }
        //}

        //public void SetPixel(int x, int y, Color c)
        //{
        //    unsafe
        //    {
        //        byte* ptr = (byte*)Iptr;
        //        ptr = ptr + bitmapData.Stride * y;
        //        ptr += Depth * x / 8;
        //        if (Depth == 32)
        //        {
        //            ptr[3] = c.A;
        //            ptr[2] = c.R;
        //            ptr[1] = c.G;
        //            ptr[0] = c.B;
        //        }
        //        else if (Depth == 24)
        //        {
        //            ptr[2] = c.R;
        //            ptr[1] = c.G;
        //            ptr[0] = c.B;
        //        }
        //        else if (Depth == 8)
        //        {
        //            ptr[2] = c.R;
        //            ptr[1] = c.G;
        //            ptr[0] = c.B;
        //        }
        //    }
        //}



        //return data[((width * y) + x) * 4 + i];
    }

效果如下:

总结:用自带的图片处理性能低下,建议使用指针或者其他图像库处理,比如OpenCV的.NET库。

 

posted @ 2018-04-25 10:17  FourOne  阅读(584)  评论(0编辑  收藏