检查C#中的图像是否为空

时间:2012-10-02 05:14:51

标签: c# image pixel

我到处寻找,但似乎没有一个标准(我可以看到)如何检查图像是否为空白。在C#

我有办法做到这一点,但很想知道检查图像是否为空白的正确方法是什么,所以每个人都可以在将来知道。

我不会复制粘贴一堆代码,如果你想要我,这将是我的荣幸,但我首先想解释一下如何检查图像是否为空白。< / p>

你拍摄.jpg图像,获取它的宽度。例如500像素 然后你把它除以2 给你250

然后你检查每个像素的颜色在(250宽度和高度)的位置(迭代的地方是想象图像的高度。

这样做只是垂直检查图像的中间像素线。它通过所有像素检查,看看颜色是否是白色除外。我已经这样做了,所以你不必搜索所有500 *像素的高度,因为你几乎总是会在页面中间遇到一种颜色。

它的工作......有点慢......必须有更好的方法来做到这一点?您可以将其更改为垂直搜索2/3/4行,以增加发现非空白页面的机会,但这需要更长的时间。

(另请注意,使用图像的大小来检查它是否包含某些东西在这种情况下不起作用,因为打开两个句子的页面和空白页面的大小彼此太靠近)

添加解决方案后

帮助实施和理解解决方案的资源。

(请注意,在第一个网站上,所声明的Pizelformat实际上是Pixelformat) - 我知道的小错误,只是提到,可能会引起一些混淆。

在我实施加速像素搜寻的方法之后,速度没有增加那么多。所以我认为我做错了什么。

40张图片的旧时间= 15.63。

40张图片的新时间= 15.43

我在伟大的文章DocMax quoted中看到,代码“锁定”在一组像素中。 (或者多数民众赞成我是如何理解的) 所以我所做的就是锁定每页的中间像素行。这是正确的举动吗?

private int testPixels(String sourceDir)
    {
         //iterate through images
        string[] fileEntries = Directory.GetFiles(sourceDir).Where(x => x.Contains("JPG")).ToArray();

        var q = from string x in Directory.GetFiles(sourceDir)
                where x.ToLower().EndsWith(".jpg")
                select new FileInfo(x);

        int holder = 1;
        foreach (var z in q)
        {
            Bitmap mybm= Bitmap.FromFile(z.FullName) as Bitmap;
            int blank = getPixelData2(mybm);

            if (blank == 0)
            {
                holder = 0;
                break;
            }
        }
        return holder;
    }

然后是班级

private unsafe int getPixelData2(Bitmap bm)
        {
            BitmapData bmd = bm.LockBits(new System.Drawing.Rectangle((bm.Width / 2), 0, 1, bm.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, bm.PixelFormat);

            int blue;
            int green;
            int red;

            int width = bmd.Width / 2;
            for (int y = 0; y < bmd.Height; y++)
            {
                byte* row = (byte*)bmd.Scan0 + (y * bmd.Stride);

                blue = row[width * 3];
                green = row[width * 2];
                red = row[width * 1];

                // Console.WriteLine("Blue= " + blue + " Green= " + green + " Red= " + red);
                //Check to see if there is some form of color
                if ((blue != 255) || (green != 255) || (red != 255))
                {
                    bm.Dispose();
                    return 1;
                }
            }
            bm.Dispose();
            return 0;
        }

3 个答案:

答案 0 :(得分:8)

如果你能容忍错误的机会,那么这种方法似乎很好;在我的案例中,我做了一些非常相似的事情,尽管我总是有一个视觉确认来处理错误。

对于性能,关键的问题是你如何获得要测试的像素。如果您使用Bitmap.GetPixel,则必然会出现性能问题。 (在Google中搜索&#34; Bitmap.GetPixel slow&#34;以查看大量讨论。)

更好的性能来自于一次获取所有像素然后循环它们。我个人喜欢Bob Powell's LockBits discussion的清晰度和完整性。使用这种方法,根据您的性能需求,检查所有像素可能是合理的。

答案 1 :(得分:2)

如果你正在使用System.Drawing.Bitmap,你可以通过以下方式加快速度:

  1. 不使用GetPixel访问像素,使用LockBits和UnlockBits将图像位图复制到常规内存。请参阅MSDN documentation上的示例以了解用法。
  2. 不在for循环中调用Width,Height或Size属性。调用大小一次,将值存储在局部变量中并使用循环中的值。
  3. 注意:

    1. 使用System.Drawing.Bitmap时,您的图像可能位于设备内存中,访问它可能非常耗时。
    2. 我不记得是否将图像加载到Bitmap中已经将其转换为RGB格式,因为其他格式更难以使用,但如果不是这样,您可以创建与您的相同大小的RGB位图原始图像,获取它的图形对象(Graphics.FromImage)并使用DrawImage在RGB位图中绘制原始图像。
    3. 编辑:由DocMax击败。

      在任何情况下,你也可以尝试使用替代库,例如包含C#包装器的优秀FreeImage

答案 2 :(得分:0)

将图像缩放为1x1,然后检查一个像素

新的Bitmap(previousImage,new Size(1,1));