C#GDI边缘空白检测算法 [英] c# GDI Edge Whitespace Detection Algorithm

查看:480
本文介绍了C#GDI边缘空白检测算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要寻找适用于C 检测边缘空白#位图的解决方案,从C#托管GDI +库。

该图像是无论是透明,大部分400X图片是8000x8000px与周围的边缘约2000px空白。

什么是找出边缘的最有效的方式, X,Y,高度和宽度坐标?我试图通过像素一展身手像素但发现它很慢。

更新,以解决方案 --Added左/右/上/下边界

与图像细节中心图像有关的问题,现在庄稼任何透明(0%)或白色(#FFFFFF)像素。

  VAR顶部= bitmap.Height;
VAR左= bitmap.Width;
无功权= 0;
变种底部= 0;
 

...

  VAR的pData = pData0 +(Y * data.Stride)+(X * 4);
变种xyAlpha = pData中[3];
变种xyBlue =的pData [0];
变种xyGreen = pData中[1];
变种xyRed = pData中[2];
如果((xyAlpha大于0)||(xyRed = 255&安培;!&安培;!xyGr​​een = 255&安培;&安培;!xyBlue = 255)){
    如果(Y<顶)
        顶部= Y;
    如果(Y>底部)
        底部= Y;
    如果(X<左)
        左= X;
    如果(X>右)
        右= X;
}
 

...

  VAR cropWidth =右 - 左;
VAR cropHeight =底 - 顶;
VAR cropX =顶部;
VAR cropY =左;

VAR cacheBitmap =新位图(cropWidth,cropHeight,PixelFormat.Format32bppArgb);
使用(VAR cacheGraphics = Graphics.FromImage(cacheBitmap)){
    cacheGraphics.DrawImage(context.Image,新的Rectangle(0,0,cropWidth,cropHeight),cropX,cropY,cropWidth,cropHeight,GraphicsUnit.Pixel);
}
 

解决方案

一个伟大的GDI +资源鲍勃·鲍威尔的GDI +常见问题解答

您没有说你怎么访问图像中的像素,所以我会假设你使用的慢GetPixel方法。您可以使用指针和LockBits访问像素,更快的方法:看到LockBits 的鲍勃鲍威尔解释   - 这需要一个不安全的code块 - 如果你不想这样,或者你没有FullTrust的可以使用的伎俩在这里解释:的由J.邓拉普在.NET Pointerless图像处理

的下面code使用LockBits方法(用于PixelFormat.Format32bppArgb)和将填充开始和结束点与在图像中的第一和最后像素被发现,不具有在所描述的颜色值争论的颜色。该方法也忽略完全透明的像素,如果要检测的图像的区域是有用的,其中所述可见内容启动。

 点开始= Point.Empty;
    点结束= Point.Empty;

    INT bitmapWidth = bmp.Width;
    INT bitmapHeight = bmp.Height;

    #地区发现的开始和结束点
    的BitmapData数据= bmp.LockBits(新的Rectangle(0,0,bitmapWidth,bitmapHeight),ImageLockMode.ReadOnly,PixelFormat.Format32bppArgb);
    尝试
    {
        不安全
        {
            字节* pData0 =(BYTE *)data.Scan0;
            对于(INT Y = 0; Y< bitmapHeight; Y ++)
            {
                为(中间体X = 0 X  - 其中; bitmapWidth; X ++)
                {
                    BYTE * pData所= pData0 +(Y * data.Stride)+(X * 4);

                    字节xyBlue =的pData [0];
                    字节xyGreen = pData中[1];
                    字节xyRed = pData中[2];
                    字节xyAlpha = pData中[3];


                    如果(color.A!= xyAlpha
                            || color.B!= xyBlue
                            || color.R!= xyRed
                            || color.G!= xyGreen)
                    {
                        //忽略透明像素
                        如果(xyAlpha == 0)
                            继续;
                        如果(start.IsEmpty)
                        {
                            开始=新点(X,Y);
                        }
                        否则,如果(start.Y> Y)
                        {
                            start.Y = Y;
                        }
                        如果(end.IsEmpty)
                        {
                            结束=新的点(X,Y);
                        }
                        否则,如果(end.X< X)
                        {
                            end.X = X;
                        }
                        否则,如果(end.Y< Y)
                        {
                            end.Y = Y;
                        }
                    }
                }
            }
        }
    }
    最后
    {
        bmp.UnlockBits(数据);
    }
    #endregion
 

I am looking for a solution for detecting edge whitespace of c# bitmap, from the c# managed GDI+ library.

The images would be either transparent or white, most of the 400x pictures are 8000x8000px with about 2000px whitespace around the edges.

What would be the most efficient way of finding out the edges, x, y, height and width coordinates? I tried a go pixel by pixel but was finding it very slow.

Update to solution --Added left/right/top/bottom bounds

Problems with images detail center images, now crops any transparent (0%) or white (#FFFFFF) pixels.

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);
}

解决方案

A great GDI+ resource is Bob Powells GDI+ FAQ!

You didn't say how you accessed the pixels in the image so I will assume that you used the slow GetPixel methods. You can use pointers and LockBits to access pixels in a faster way: see Bob Powells explanation of LockBits - This will require an unsafe code block - if you don't want this or you do not have FullTrust you can use the trick explained here: Pointerless Image Processing in .NET by J. Dunlap

The below code uses the LockBits approach (for the PixelFormat.Format32bppArgb) and will fill the start and end Points with the value where the first and last pixels in an image are discovered that do not have the color described in the argument color. The method also ignores completely transparent pixels which is useful if you want to detect the area of an image where the visible 'content' starts.

    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

这篇关于C#GDI边缘空白检测算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆