代码之家  ›  专栏  ›  技术社区  ›  Elijah Glover

c#GDI边缘空白检测算法

  •  7
  • Elijah Glover  · 技术社区  · 16 年前

    我正在寻找解决问题的办法 检测边缘空白 从c#managed GDI+库中获取的c#bitmap。

    图像可能是 白色 ,大多数400x图片是8000x8000px,边缘有大约2000px的空白。

    x、 y、高度和宽度坐标 ? 我试着一个像素一个像素地去做,但发现速度很慢。

    --添加了左/右/上/下边界

    图像细节中心图像的问题,现在裁剪任何透明(0%)或白色(#FFFFFF)像素。

    var top = bitmap.Height;
    var left = bitmap.Width;
    var right = 0;
    var bottom = 0;
    

    ...

    var pData = pData0 + (y * data.Stride) + (x * 4);
    var xyAlpha = pData[3];
    var xyBlue = pData[0];
    var xyGreen = pData[1];
    var xyRed = pData[2];
    if ((xyAlpha > 0) || (xyRed != 255 && xyGreen != 255 && xyBlue != 255)) {
        if (y < top)
            top = y;
        if (y > bottom)
            bottom = y;
        if (x < left)
            left = x;
        if (x > right)
            right = x;
    }
    

    var cropWidth = right - left;
    var cropHeight = bottom - top;
    var cropX = top;
    var cropY = left;
    
    var cacheBitmap = new Bitmap(cropWidth, cropHeight, PixelFormat.Format32bppArgb);
    using (var cacheGraphics = Graphics.FromImage(cacheBitmap)) {
        cacheGraphics.DrawImage(context.Image, new Rectangle(0, 0, cropWidth, cropHeight), cropX, cropY, cropWidth, cropHeight, GraphicsUnit.Pixel);
    }
    
    2 回复  |  直到 15 年前
        1
  •  9
  •   Andrew Morton    4 年前

    一个伟大的GDI+资源是 Bob Powell's GDI+ FAQ !

    您没有说明如何访问图像中的像素,因此我假设您使用了慢速GetPixel方法。您可以使用指针和锁位以更快的方式访问像素: see Bob Powells explanation of LockBits

    下面的代码使用锁位方法(对于PixelFormat.Format32bppArgb),并将使用发现图像中第一个和最后一个像素的值填充起点和终点,这些像素不具有参数颜色中描述的颜色。该方法还忽略了完全透明的像素,如果要检测图像中可见“内容”开始的区域,这一点非常有用。

        Point start = Point.Empty;
        Point end = Point.Empty;
        
        int bitmapWidth = bmp.Width;
        int bitmapHeight = bmp.Height;
        
        #region find start and end point
        BitmapData data = bmp.LockBits(new Rectangle(0, 0, bitmapWidth, bitmapHeight), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
        try
        {
            unsafe
            {
                byte* pData0 = (byte*)data.Scan0;
                for (int y = 0; y < bitmapHeight; y++)
                {
                    for (int x = 0; x < bitmapWidth; x++)
                    {
                        byte* pData = pData0 + (y * data.Stride) + (x * 4);
        
                        byte xyBlue = pData[0];
                        byte xyGreen = pData[1];
                        byte xyRed = pData[2];
                        byte xyAlpha = pData[3];
        
        
                        if (color.A != xyAlpha
                                || color.B != xyBlue
                                || color.R != xyRed
                                || color.G != xyGreen)
                        {
                            //ignore transparent pixels
                            if (xyAlpha == 0)
                                continue;
                            if (start.IsEmpty)
                            {
                                start = new Point(x, y);
                            }
                            else if (start.Y > y)
                            {
                                start.Y = y;
                            }
                            if (end.IsEmpty)
                            {
                                end = new Point(x, y);
                            }
                            else if (end.X < x)
                            {
                                end.X = x;
                            }
                            else if (end.Y < y)
                            {
                                end.Y = y;
                            }
                        }
                    }
                }
            }
        }
        finally
        {
            bmp.UnlockBits(data);
        }
        #endregion
    
        2
  •  2
  •   Ray Hidayat    16 年前