2011-08-09 21 views
12

Tengo un directorio de imágenes, fotos, gráficos web, logotipos, etc ... todo esto se extrae de la web. Hay archivos .jpg, .gif y .png.¿Cómo puedo distinguir entre gráficos y fotografías?

Me gustaría extraer imágenes que son reales (guardar fotos y eliminar gráficos). No estoy tratando de obtener fotografías reales/originales, solo imágenes de cosas de la vida real versus gráficos hechos por computadora (no estoy seguro de cómo decir esto más claramente). Casi todas estas imágenes han sido manipuladas y la información exif no estará disponible.

Se acepta un margen de error grande (incluso muy grande).

ya he:

  • imágenes eliminadas con recuentos bajos de color utilizando imagecolorstotal()
  • imágenes retirados que tienen gran altura a las relaciones de anchura, y viceversa (una proporción de 3+ funciona sorprendentemente bien).
  • eliminado las imágenes que son más pequeños que una cierta dimensión (50-75px es bueno)

estoy pensando en la eliminación de las imágenes con los valores del histograma se concentraron en torno a ciertos colores, en lugar de una curva suave o distribuido. No he intentado esto todavía.

¿De qué otro modo puedo mejorar este filtrado de imágenes para extraer (en su mayoría) fotos reales? Prefiero usar PHP, pero eso no es obligatorio.

ACTUALIZACIÓN: Resulta que para mi aplicación, las tres primeras cosas que ya había probado era una solución sólida del 80%. Se puede hacer un mayor filtrado usando algunas de las respuestas a continuación.

+0

podría utilizar la biblioteca GD para poder procesar los datos de imágenes en bruto, y comprobar si hay cosas como bordes, similitud de imagen y otras cosas. Publicaría algo más preciso, pero php.net parece estar mal para mí en este momento. He utilizado GD antes para insertar marcas de agua y similares, es un poco complejo, pero también se puede hacer mucho con él. –

+0

¿qué hay de la comprobación de 'exif'? - http://php.net/manual/en/book.exif.php – ajreal

Respuesta

2

A continuación se muestra el código que he utilizado y el razonamiento detrás de por qué he aplicado cada filtro. He realizado muchas pruebas sobre estas funciones y configuraciones, pero aún querrás ejecutar algunas pruebas para optimizar estas configuraciones para tu conjunto de imágenes.

He usado IMagick (la envoltura de PHP para ImageMagick) para hacer el trabajo en el cálculo de la siguiente imagen atributos:

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

de altura a anchura

imágenes Filtrado por una relación altura/ancho elimina un gran porcentaje de basura. Cuanto más cerca esté de configurar su filtro a 1: 1, mejor funcionará este filtro, pero también comenzará a filtrar muchas buenas imágenes. Este es uno de los filtros más valiosas que he aplicado:

// 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"); 

Número de colores

imágenes Filtrado por debajo de 32 colores por lo general sólo elimina las imágenes de la chatarra, sin embargo, también perdido mucho diagramas y dibujos en blanco y negro.

// 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"); 

Altura Min y ancho de

imágenes Filtrado basado en una altura mínima absoluta y anchura que ambas dimensiones deben pasar, así como un valor ligeramente mayor que al menos una dimensión debe pasar ayudado filtra algo de basura

// 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"); 

Color entropía utilizando el histograma de la imagen

Por último, calculo entropía imagen en color (según lo sugerido por @ Jason en su respuesta) para cada imagen en mi sistema. Cuando elijo imágenes para mostrar, generalmente las ordeno ordenadas por esta entropía en orden descendente. Cuanto mayor sea la entropía, más probable es que una imagen sea una fotografía de una cosa real, en comparación con un gráfico. Hay tres grandes problemas con este método:

  1. gráficos muy estilizadas tienden a tener mayores entropías debido a la gran variación de la profundidad de color y el color.

  2. Las fotografías que han sido retocadas con fondos sólidos y fondos de estudio tienden a tener entropías más bajas debido al color sólido dominante.

  3. Esto no funcionó bien como un filtro absoluto debido a la gran variación entre las imágenes en mi conjunto, sus tipos de archivos, profundidades de color, etc. Sin embargo, es sumamente útil para elegir la mejor imagen de un pequeño subconjunto dentro de todo mi conjunto. Un ejemplo sería elegir qué imagen mostrar como la imagen principal de todas las imágenes encontradas en una página web.

Aquí es la función que utilizo para calcular la entropía imagen:

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; 

} 
7

La función exif_read_data puede proporcionar información sobre las cámaras utilizadas, es muy diferente para cada cámara. Esta no será la solución perfecta, pero debería agregarse a lo que ya está utilizando.

+0

esta es una gran sugerencia, pero la mayoría de estas imágenes han sido manipuladas y la información exif no está disponible. son imágenes web y no fotos originales. –

1

Los gráficos y los dibujos lineales suelen ser más pequeños cuando se almacenan como png, mientras que las fotografías son más pequeñas cuando se almacenan como jpg. Almacene cada imagen en cada formato y haga una conjetura basada en el tamaño del archivo.

6

Entropy sería una buena medida para diferenciar las fotos "reales" de los gráficos de computadora. Realmente es solo una versión más estructurada de su idea de histograma. La entropía está dada por

H(X) = -sum(p[i] * log2(p[i])) 

donde p [i] es la probabilidad del i-ésimo color. p[i] es más o menos el valor del histograma en cada color (porcentaje (0.0-> 1.0) de píxeles a color i). Cuanto más distribuidos estén los colores, mayor será el H(X). Si los píxeles solo se distribuyen entre algunos colores, H(X) será pequeño.

Tenga en cuenta que el tamaño del archivo comprimido está directamente relacionado con la entropía (mayor entropía, mayor tamaño del archivo), por lo que la sugerencia en otra respuesta para usar el tamaño del archivo podría ser una manera indirecta de conseguir esto.

+0

alguna sugerencia sobre cómo calcular p [i] con php? –

+1

p [i] es simplemente el histograma de la imagen, por lo que debería poder encontrar algún código php para calcularlo. Solo asegúrese de que el histograma se da en porcentajes (0.0-> 1.0), no en los recuentos brutos de cada color. Además, asegúrese de definir el caso especial de log2 (0) = 0 que generalmente no está definido. –

Cuestiones relacionadas