2012-10-02 45 views
6

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

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

我不会复制粘贴一堆代码,如果你想要我,这将是我的荣幸,但我只是首先想解释我如何去检查以查看图像是否为空。

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

然后,你检查什么每个像素的颜色是在的位置(250宽度,以及i高度)(其中,你迭代想到了的HIGHT图像

这样做只是检查图像像素的中间线,垂直。检查所有像素检查颜色是否是任何东西除了白色我已经这样做了,所以你不会有搜索所有500 *像素的高度,因为你几乎总是会遇到页面中间的颜色。

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

(另请注意,使用图像的大小,以检查其中是否包含一些不会在这种情况下工作,因为有两个句子和一个空白页面的大小在页面过于接近彼此)

解决方案添加完成后。

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

(注意,第一个网站上,所陈述的Pizelformat实际上是像素格式) - 小的错误,我知道,只是提的是,可能对一些人造成一些混淆。

在我实现了加速像素搜索的方法后,速度没有那么大。所以我会认为我做错了什么。

40个图像的旧时间= 15.63。

新时间= 15.43的40张图片

我与伟大的文章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; 
     } 
+0

你计时了多长时间?如果是这样,什么时候,图像的高度是多少? – 3aw5TZetdf

+1

你的执行过程中你必须做错某些事情,因为你的算法对我来说听起来很合理。应该不花时间扫描一列位图。 –

+0

32个图像的总时间= 00:00:12.9187389 高度= 6552 宽度= 4580 – Ruan

回答

7

如果你能容忍犯错的机会,这种方法似乎罚款;在我的情况下,我做了一些非常类似的事情,尽管我总是通过视觉确认来处理错误。

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

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

+0

你实际上是点,我使用Bitmap.GetPixel。 谢谢,生病请检查解决方案,并在此发布我的发现,以便有一个完整的解决方案和“敢说我”如何检查图像的标准。 – Ruan

+0

所以我实现了解决方案。唯一的一点是,时间几乎相同旧时间= 40.6图像的15.63。 40个图像的新时间= 15.43。我解释为我的问题上面的额外信息,我做了什么。 – Ruan

+0

它加速了一小部分。我认为很难看到数据量的增加。 谢谢 – Ruan

2

如果您使用System.Drawing.Bitmap可以加快东西(基本上)由:

  1. 不使用GetPixel访问像素,使用LockBits和UnlockBits的位图图像复制到定期记忆。有关使用情况,请参阅MSDN documentation上的示例。
  2. 不调用for循环中的Width,Height或Size属性。调用大小一次,将这些值存储在局部变量中并将其用于循环中。

注:

  1. 当使用System.Drawing.Bitmap您的图像可以是在装置存储器和访问它可能是耗时的。
  2. 我不记得是否将图像加载到位图中已将其转换为RGB格式,因为其他格式更难以处理,但如果不是这种情况,您可以创建与您的图像大小相同的RGB位图原始图像,得到它的Graphic对象(Graphics.FromImage)并使用DrawImage在RGB位图中绘制原始图像。

编辑:由DocMax击败一拳。

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

0

缩放图像以1x1的再检查一个像素

新位图(previousImage,新尺寸(1,1));

+0

这太棒了,不幸的是它不适用于我试过的大多数图像(一组具有argb颜色值的64x56拼贴)。即使源包含一些图像数据,单个像素也经常是0,0,0,0。 – PeteB

+0

我使用2x2进行了进一步测试,并检查了所有四个像素。这是更好的,但仍然报告瓦片中有少量的内容时是空的。 – PeteB