【问题标题】:How to detect if an image is a photo, clip art or a line drawing?如何检测图像是照片、剪贴画还是线条图?
【发布时间】:2012-03-10 10:00:02
【问题描述】:

识别图片类型的最佳方法是什么? rwong's answer on this question 建议 Google 将图像分为以下几组:

  • 照片 - 连续色调
  • 剪贴画 - 平滑阴影
  • 线条图 - 双色

将图像分类到这些组之一的最佳策略是什么?我目前正在使用 Java,但欢迎使用任何通用方法。

谢谢!


更新:

我尝试了tyjkenn 在评论中提到的独特颜色计数方法,它似乎适用于我尝试过的大约 90% 的案例。特别是黑白照片很难单独使用独特的颜色计数来正确检测。

获取图像直方图并单独计算偷看次数似乎不是一个可行的选择。例如这张图片只有两个峰:

以下是我查看的另外两张图片:

【问题讨论】:

  • 这是一个有趣的问题。也许您可以根据不同颜色的数量来确定它。我假设线条图只有两个,剪贴画会有更多,而一张照片会有数百万。然后你可以循环遍历像素,计算独特的颜色,并以此方式对其进行分类。
  • @tyjkenn 这是一个有趣的策略,我可能会回归。不幸的是,我需要处理的一些数据只有 256 种颜色,很容易被剪贴画渐变用完。
  • 可能属于理论 CS StackExchange:cstheory.stackexchange.com
  • dsp.stackexchange 看起来更适合我

标签: java image-processing computer-vision


【解决方案1】:

区分图纸和照片的方法相当简单但有效。结合使用它们以获得最佳精度:

1) Mime 类型或文件扩展名

PNG 通常是剪贴画或图画,而 JPEG 主要是照片。

2) 透明度

如果图像具有 Alpha 通道,则它很可能是一幅图画。如果存在 Alpha 通道,您还可以遍历所有像素以检查是否确实使用了透明度。这里有一个 Python 示例代码:

from PIL import Image
img = Image.open('test.png')
transparency = False
if img.mode in ('RGBA', 'RGBa', 'LA') or (img.mode == 'P' and 'transparency' in img.info):
    if img.mode != 'RGBA': img = img.convert('RGBA')
    transparency = any(px for px in img.getdata() if px[3] < 220)

print 'Transparency:', transparency

3) 颜色分布

剪贴画通常具有相同颜色的区域。如果几种颜色构成了图像的重要部分,那么它更像是一幅图画而不是一张照片。此代码输出由十种最常用的颜色组成的图像区域的百分比(Python 示例):

from PIL import Image
img = Image.open('test.jpg')
img.thumbnail((200, 200), Image.ANTIALIAS)
w, h = img.size
print sum(x[0] for x in sorted(img.convert('RGB').getcolors(w*h), key=lambda x: x[0], reverse=True)[:10])/float((w*h))

您需要调整和优化这些价值观。十种颜色足够您的数据吗?什么百分比最适合您。通过测试大量样本图像来找出它。 30% 或更多通常是剪贴画。不过,不适用于天空照片或类似的东西。因此,我们需要另一种方法——下一种。

4) 通过 FFT 进行锐边检测

锋利的边缘会导致傅里叶频谱中出现高频。通常这些特征更常见于图纸中(另一个 Python sn-p):

from PIL import Image
import numpy as np
img = Image.open('test.jpg').convert('L')
values = abs(numpy.fft.fft2(numpy.asarray(img.convert('L')))).flatten().tolist()
high_values = [x for x in values if x > 10000]
high_values_ratio = 100*(float(len(high_values))/len(values))
print high_values_ratio

此代码为您提供每个区域超过一百万的频率数量。同样:根据您的示例图像优化这些数字。

针对您的图像集组合和优化这些方法。让我知道你是否可以改进这个 - 或者只是编辑这个答案,拜托。我想自己改进它:-)

【讨论】:

    【解决方案2】:

    除了颜色直方图,还要考虑边缘信息和整个图像的线宽一致性。

    照片 - 自然边缘具有多种边缘强度,不太可能出现许多平行边缘。

    剪贴画 - 分水岭算法可以帮助识别亮度一致的大面积连接区域。在为高可见度而设计的剪贴画和合成图像中,更有可能是完美的直线和平行线。边缘强度的直方图可能有几个非常强的峰值。

    线条图 - 合成线条可能具有非常一致的宽度。笔画宽度变换可以帮助您识别笔画。 (其中一个基本原则是找到“指向”彼此的边缘梯度。)边缘强度的直方图可能只有一个强峰值。

    【讨论】:

      【解决方案3】:

      这个问题可以通过图像分类来解决,这可能是谷歌的解决方案。基本上,您要做的是 (i) 将一组图像标记为 3 类:照片、剪贴画和线条图; (ii) 从这些图像中提取特征; (iii) 使用图像的特征和标签来训练分类器。

      特征提取:

      在此步骤中,您必须提取可能对分类器区分 3 类图像有用的视觉信息:

      • 一个非常基本但有用的视觉特征是图像直方图及其变体。例如,照片的gray level histogram 可能比剪贴画的直方图更平滑,在直方图中,您的区域可能都具有相同的颜色值。
      • 可以使用的另一个功能是将图像转换为频域(例如使用FFTDCT)并测量高频分量的能量。因为线条图可能会有颜色的急剧过渡,所以它的高频分量往往会积累更多的能量。

      还有许多其他feature extraction algorithms 可以使用。

      训练分类器:

      在特征提取阶段之后,我们将为每张图像提供一个数值向量(我们称之为图像特征向量)及其元组。这是训练分类器的合适输入。至于分类器,可以考虑Neural NetworksSVMothers

      分类:

      现在我们有一个经过训练的分类器,要对图像进行分类(即检测图像类别),我们只需提取其特征并将其输入到分类器中,它就会返回其预测类别

      【讨论】:

        【解决方案4】:

        直方图将是执行此操作的第一种方法。
        将彩色图像转换为灰度并计算直方图。 一个非常双峰的直方图,在黑色(或深色)和白色(或右侧)中有 2 个尖峰,可能有更多的白色,是画线的一个很好的指示。
        如果您只有几个峰,那么它很可能是剪贴画类型的图像。
        否则就是照片。

        【讨论】:

          猜你喜欢
          • 2012-10-18
          • 1970-01-01
          • 2016-01-03
          • 2017-07-13
          • 2021-02-09
          • 2014-02-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多