una recorrer por para manipulacion imagenes imagen filtros crear con comparar como cargar analisis python imagemagick python-imaging-library

recorrer - manipulacion de imagenes en python



¿Cuál es la forma más rápida de generar miniaturas de imágenes en Python? (7)

Python 2.7, Windows, x64 usuarios

Además de @JakobBowyer & @Audionautics , PIL es bastante antiguo y puedes encontrarte con la solución de problemas y buscar la versión correcta ... en su lugar, usa Pillow desde here ( source )

El fragmento actualizado se verá así:

im = Image.open(full_path) im.thumbnail(thumbnail_size) im.save(new_path, "JPEG")

Script de enumeración completo para la creación de miniaturas:

import os from PIL import Image output_dir = ''.//output'' thumbnail_size = (200,200) if not os.path.exists(output_dir): os.makedirs(output_dir) for dirpath, dnames, fnames in os.walk(".//input"): for f in fnames: full_path = os.path.join(dirpath, f) if f.endswith(".jpg"): filename = ''thubmnail_{0}''.format(f) new_path = os.path.join(output_dir, filename) if os.path.exists(new_path): os.remove(new_path) im = Image.open(full_path) im.thumbnail(thumbnail_size) im.save(new_path, "JPEG")

Estoy construyendo una galería de fotos en Python y quiero poder generar rápidamente miniaturas para las imágenes de alta resolución.

¿Cuál es la forma más rápida de generar miniaturas de alta calidad para una variedad de fuentes de imagen?

¿Debo utilizar una biblioteca externa como imagemagick o hay una forma interna eficiente de hacerlo?

Las dimensiones de las imágenes redimensionadas serán (tamaño máximo):

120x120 720x720 1600x1600

La calidad es un problema, ya que deseo preservar la mayor cantidad de colores originales posible y minimizar los artefactos de compresión.

Gracias.


Me gustó algo de diversión, así que hice una evaluación comparativa de los diversos métodos sugeridos anteriormente y algunas ideas propias.

Recolecté 1000 imágenes de alta resolución de 12MP para iPhone 6s, cada una de 4032x3024 píxeles y uso un iMac de 8 núcleos.

Aquí están las técnicas y los resultados, cada uno en su propia sección.

Método 1 - ImageMagick secuencial

Este es un código simplista, no optimizado. Cada imagen se lee y se produce una miniatura. Luego se lee de nuevo y se produce una miniatura de diferente tamaño.

#!/bin/bash start=$SECONDS # Loop over all files for f in image*.jpg; do # Loop over all sizes for s in 1600 720 120; do echo Reducing $f to ${s}x${s} convert "$f" -resize ${s}x${s} t-$f-$s.jpg done done echo Time: $((SECONDS-start))

Resultado: 170 segundos.

Método 2: ImageMagick secuencial con carga única y cambio de tamaño sucesivo

Esto sigue siendo secuencial pero un poco más inteligente. Cada imagen solo se lee una vez y la imagen cargada se redimensiona a tres y se guarda en tres resoluciones. La mejora es que cada imagen se lee solo una vez, no 3 veces.

#!/bin/bash start=$SECONDS # Loop over all files N=1 for f in image*.jpg; do echo Resizing $f # Load once and successively scale down convert "$f" / -resize 1600x1600 -write t-$N-1600.jpg / -resize 720x720 -write t-$N-720.jpg / -resize 120x120 t-$N-120.jpg ((N=N+1)) done echo Time: $((SECONDS-start))

Resultado: 76 segundos.

Método 3 - GNU Parallel + ImageMagick

Esto se basa en el método anterior, al usar GNU Parallel para procesar N imágenes en paralelo, donde N es el número de núcleos de CPU en su máquina.

#!/bin/bash start=$SECONDS doit() { file=$1 index=$2 convert "$file" / -resize 1600x1600 -write t-$index-1600.jpg / -resize 720x720 -write t-$index-720.jpg / -resize 120x120 t-$index-120.jpg } # Export doit() to subshells for GNU Parallel export -f doit # Use GNU Parallel to do them all in parallel parallel doit {} {#} ::: *.jpg echo Time: $((SECONDS-start))

Resultado: 18 segundos.

Método 4 - GNU paralelo + vips

Este es el mismo que el método anterior, pero usa vips en la línea de comandos en lugar de ImageMagick .

#!/bin/bash start=$SECONDS doit() { file=$1 index=$2 r0=t-$index-1600.jpg r1=t-$index-720.jpg r2=t-$index-120.jpg vipsthumbnail "$file" -s 1600 -o "$r0" vipsthumbnail "$r0" -s 720 -o "$r1" vipsthumbnail "$r1" -s 120 -o "$r2" } # Export doit() to subshells for GNU Parallel export -f doit # Use GNU Parallel to do them all in parallel parallel doit {} {#} ::: *.jpg echo Time: $((SECONDS-start))

Resultado: 8 segundos

Método 5 - PIL secuencial

Esto está destinado a corresponder a la respuesta de Jakob.

#!/usr/local/bin/python3 import glob from PIL import Image sizes = [(120,120), (720,720), (1600,1600)] files = glob.glob(''image*.jpg'') N=0 for image in files: for size in sizes: im=Image.open(image) im.thumbnail(size) im.save("t-%d-%s.jpg" % (N,size[0])) N=N+1

Resultado: 38 segundos.

Método 6: PIL secuencial con carga única y cambio de tamaño sucesivo

Esto pretende ser una mejora de la respuesta de Jakob, en donde la imagen se carga solo una vez y luego se redimensiona tres veces en lugar de volver a cargarla cada vez para producir cada nueva resolución.

#!/usr/local/bin/python3 import glob from PIL import Image sizes = [(120,120), (720,720), (1600,1600)] files = glob.glob(''image*.jpg'') N=0 for image in files: # Load just once, then successively scale down im=Image.open(image) im.thumbnail((1600,1600)) im.save("t-%d-1600.jpg" % (N)) im.thumbnail((720,720)) im.save("t-%d-720.jpg" % (N)) im.thumbnail((120,120)) im.save("t-%d-120.jpg" % (N)) N=N+1

Resultado: 27 segundos.

Método 7 - PIL paralelo

Se pretende que esto corresponda con la respuesta de Audionautics, en la medida en que utiliza el multiprocesamiento de Python. También evita la necesidad de volver a cargar la imagen para cada tamaño de miniatura.

#!/usr/local/bin/python3 import glob from PIL import Image from multiprocessing import Pool def thumbnail(params): filename, N = params try: # Load just once, then successively scale down im=Image.open(filename) im.thumbnail((1600,1600)) im.save("t-%d-1600.jpg" % (N)) im.thumbnail((720,720)) im.save("t-%d-720.jpg" % (N)) im.thumbnail((120,120)) im.save("t-%d-120.jpg" % (N)) return ''OK'' except Exception as e: return e files = glob.glob(''image*.jpg'') pool = Pool(8) results = pool.map(thumbnail, zip(files,range((len(files)))))

Resultado: 6 segundos.

Método 8 - OpenCV paralelo

Se pretende que sea una mejora en la respuesta de bcattle, en la medida en que utiliza OpenCV, pero también evita la necesidad de volver a cargar la imagen para generar cada salida de resolución nueva.

#!/usr/local/bin/python3 import cv2 import glob from multiprocessing import Pool def thumbnail(params): filename, N = params try: # Load just once, then successively scale down im = cv2.imread(filename) im = cv2.resize(im, (1600,1600)) cv2.imwrite("t-%d-1600.jpg" % N, im) im = cv2.resize(im, (720,720)) cv2.imwrite("t-%d-720.jpg" % N, im) im = cv2.resize(im, (120,120)) cv2.imwrite("t-%d-120.jpg" % N, im) return ''OK'' except Exception as e: return e files = glob.glob(''image*.jpg'') pool = Pool(8) results = pool.map(thumbnail, zip(files,range((len(files)))))

Resultado: 5 segundos



Otra opción es usar los enlaces de python para OpenCV . Esto puede ser más rápido que PIL o Imagemagick.

import cv2 sizes = [(120, 120), (720, 720), (1600, 1600)] image = cv2.imread("input.jpg") for size in sizes: resized_image = cv2.resize(image, size) cv2.imwrite("thumbnail_%d.jpg" % size[0], resized_image)

Hay un tutorial más completo here .

Si desea ejecutarlo en paralelo, use concurrent.futures en Py3 o el paquete de futures en Py2.7:

import concurrent.futures import cv2 def resize(input_filename, size): image = cv2.imread(input_filename) resized_image = cv2.resize(image, size) cv2.imwrite("thumbnail_%s%d.jpg" % (input_filename.split(''.'')[0], size[0]), resized_image) executor = concurrent.futures.ThreadPoolExecutor(max_workers=3) sizes = [(120, 120), (720, 720), (1600, 1600)] for size in sizes: executor.submit(resize, "input.jpg", size)


Quieres PIL lo hace con facilidad.

from PIL import Image sizes = [(120,120), (720,720), (1600,1600)] files = [''a.jpg'',''b.jpg'',''c.jpg''] for image in files: for size in sizes: im = Image.open(image) im.thumbnail(size) im.save("thumbnail_%s_%s" % (image, "_".join(size)))

Si necesitas desesperadamente velocidad. Luego pásalo, multiprocesalo u obtén otro idioma.


Si ya está familiarizado con imagemagick, ¿por qué no atenerse a los enlaces de python?

PythonMagick


Un poco tarde para la pregunta (¡solo un año!), Pero voy a ir con la parte de "multiprocesamiento" de la respuesta de @ JakobBowyer.

Este es un buen ejemplo de un problema vergonzosamente paralelo , ya que el bit principal del código no muta ningún estado externo a sí mismo. Simplemente lee una entrada, realiza su cálculo y guarda el resultado.

Python es bastante bueno en este tipo de problemas gracias a la función de mapa proporcionada por multiprocessing.Pool .

from PIL import Image from multiprocessing import Pool def thumbnail(image_details): size, filename = image_details try: im = Image.open(filename) im.thumbnail(size) im.save("thumbnail_%s" % filename) return ''OK'' except Exception as e: return e sizes = [(120,120), (720,720), (1600,1600)] files = [''a.jpg'',''b.jpg'',''c.jpg''] pool = Pool(number_of_cores_to_use) results = pool.map(thumbnail, zip(sizes, files))

El núcleo del código es exactamente el mismo que @JakobBowyer, pero en lugar de ejecutarlo en un bucle en un solo hilo, lo envolvimos en una función distribuida en varios núcleos a través de la función de mapa de multiprocesamiento.