如何区分图形和照片?

时间:2011-08-09 10:39:17

标签: php image-processing

我有一个图像,照片,网页图形,徽标等目录...这些都是从网上提取的。有.jpg,.gif和.png文件。

我想提取真实的图像(保留照片和删除图形)。我不是想要获得实际/原始照片,只是现实生活中的图片与计算机制作的图片(我不确定如何更清楚地说出来)。几乎所有这些图像都被操纵,exif信息将无法使用。

可以接受很大(甚至非常大)的误差范围。

我已经:

  • 使用imagecolorstotal()
  • 删除了颜色数较少的图像
  • 删除了具有较大高宽比的图像,反之亦然(3+的比例效果非常好)。
  • 删除小于某个尺寸的图像(50-75px是好的)

我正在考虑使用集中在某些颜色周围的直方图值来移除图像,而不是平滑或分布的曲线。我还没有尝试过这个。

我还能如何改进图像过滤以提取(大部分)真实照片?我更喜欢使用PHP,但这不是必需的。

更新:事实证明,对于我的应用程序,我已经尝试的前三件事是坚实的80%解决方案。可以使用下面的一些答案进一步过滤。

4 个答案:

答案 0 :(得分:7)

函数exif_read_data可以提供有关所用摄像机的信息,每个摄像机的差异很大。这不是一个完美的解决方案,但它应该增加你已经使用的东西。

答案 1 :(得分:6)

Entropy是区分“真实”照片和计算机图形的好指标。它实际上只是您直方图想法的结构化版本。

给出了熵
H(X) = -sum(p[i] * log2(p[i]))

其中p [i]是第i种颜色的概率。 p[i]几乎是每种颜色的直方图值(像素的百分比(0.0-> 1.0),颜色i)。颜色分布越多,H(X)越高。如果像素仅分布在少数几种颜色中,则H(X)将很小。

请注意,压缩文件大小与熵(更高的熵,更高的文件大小)直接相关,因此在另一个使用文件大小的答案中的建议可能是间接的方法。

答案 2 :(得分:2)

下面是我使用的代码以及我应用每个过滤器的原因。我已经对这些功能和设置进行了大量测试,但您仍然需要运行一些测试来针对您的图像集优化这些设置。

我在计算以下图像属性时使用IMagickImageMagick的PHP包装器)来完成工作:

$Image      = new Imagick( $image_path );
$height     = $Image->getImageHeight();
$width      = $Image->getImageWidth();
$histogram  = $Image->getImageHistogram();              
$num_colors = $image->getImageColors();

高宽比

按高宽比过滤图像可以消除大部分垃圾。越接近将滤镜设置为1:1,此滤镜效果越好,但您也将开始过滤大量优质图像。这是我应用的最有价值的过滤器之一:

// max height to width ratio we allow on images before we junk them
$max_size_ratio = 3;
if( $size_ratio > $max_size_ratio )
    throw new Exception( "image height to width ratio exceeded max of $max_size_ratio" );

颜色数

过滤32种颜色以下的图像通常只会删除垃圾图像,但是,我也丢失了大量的黑白图表和图纸。

// min number of colors allowed before junking
$min_colors = 32;
if( $num_colors < $min_colors )
    throw new Exception( "image had less than $min_colors colors" );

最小高度和宽度

根据两个尺寸必须通过的绝对最小高度和宽度过滤图像,以及至少一个尺寸必须通过的略大的值有助于过滤掉一些垃圾。

// min height and width in pixels both dimensions must meet
$min_height_single = 50;
$min_width_single  = 50;
if(
    $width < $min_width_single
    OR $height < $min_height_single
)
    throw new Exception( "height or width were smaller than absolute minimum" );

// min height and width in pixels at least one dimension must meet
$min_height = 75;
$min_width  = 75;
if(
    $width < $min_width
    && $height < $min_height
)
    throw new Exception( "height and width were both smaller than minimum combo" );

使用图像直方图的图像颜色熵

最后,我计算了系统中每个图像的图像颜色熵(由@Jason在他的回答中提出)。当我选择要显示的图像时,我通常会按照这个熵按降序排序。熵越高,图像成为真实照片的可能性就越大,而不是图形。这种方法有三个主要问题:

  1. 由于色彩深度和色彩变化很大,高度风格化的图形往往会有更高的熵。

  2. 由于具有鲜明的纯色,拍摄过的照片具有稳固的背景和工作室背景往往会有较低的熵。

  3. 由于我的设置中的图像,文件类型,颜色深度等之间的差异很大,因此这不能很好地用作绝对过滤器。然而,它在选择最佳图像方面非常有用在我的整个集合中的一个小子集。一个例子是选择在一个网页上找到的所有图像中显示哪个图像作为主图像。

  4. 这是我用来计算图像熵的函数:

    function set_image_entropy()
    {
    
        // create Imagick object and get image data
        $Image = new Imagick( $this->path );
        $histogram = $Image->getImageHistogram();               
        $height = $Image->getImageHeight();
        $width = $Image->getImageWidth();
        $num_pixels = $height * $width;
    
        // calculate entropy for each color in the image
        foreach( $histogram as $color )
        {
            $color_count = $color->getColorCount();
            $color_percentage = $color_count / $num_pixels;
            $entropies[] = $color_percentage * log( $color_percentage, 2 );
        }
    
        // calculate total image color entropy
        $entropy = ( -1 ) * array_sum( $entropies );
    
        return $entropy;
    
    }
    

答案 3 :(得分:1)

图形和线条图存储为png时通常较小,而存储为jpg时图片较小。以每种格式存储每个图像,并根据文件大小进行有根据的猜测。