Me gustaría tomar una imagen y cambiar la escala de la imagen, mientras que es una matriz numpy.
Por ejemplo, tengo esta imagen de una botella de coca-cola: botella-1
Lo que se traduce en una gran variedad de formas (528, 203, 3)
y quiero cambiar el tamaño para decir el tamaño de esta segunda imagen:
botella-2
Que tiene forma de (140, 54, 3)
.
¿Cómo cambio el tamaño de la imagen a una determinada forma mientras sigo manteniendo la imagen original? Otras respuestas sugieren eliminar cada dos o tres filas, pero lo que quiero hacer es básicamente reducir la imagen como lo haría a través de un editor de imágenes pero en código Python. ¿Hay bibliotecas para hacer esto en numpy / SciPy?
Respuestas:
Sí, puede instalar
opencv
(esta es una biblioteca utilizada para procesamiento de imágenes y visión por computadora) y usar lacv2.resize
función. Y por ejemplo usa:import cv2 import numpy as np img = cv2.imread('your_image.jpg') res = cv2.resize(img, dsize=(54, 140), interpolation=cv2.INTER_CUBIC)
img
Por lo tanto, aquí hay una matriz numpy que contiene la imagen original, mientras queres
hay una matriz numpy que contiene la imagen redimensionada . Un aspecto importante es elinterpolation
parámetro: hay varias formas de cambiar el tamaño de una imagen. Especialmente porque reduce la imagen y el tamaño de la imagen original no es un múltiplo del tamaño de la imagen redimensionada. Los posibles esquemas de interpolación son:Como ocurre con la mayoría de las opciones, no existe la "mejor" opción en el sentido de que para cada esquema de cambio de tamaño, hay escenarios en los que se puede preferir una estrategia a otra.
fuente
dsize
debería serdsize=(54, 140)
como toma x luego y, donde una matriz numérica muestra la forma como y luego x (y es el número de filas yx es el número de columnas)skimage.io.imread('image.jpg')
yskimage.transform.resize(img)
. scikit-image.org/docs/dev/install.htmlSi bien es posible usar numpy solo para hacer esto, la operación no está integrada. Dicho esto, puede usar
scikit-image
(que se basa en numpy) para hacer este tipo de manipulación de imágenes.La documentación de cambio de escala de Scikit-Image está aquí .
Por ejemplo, puede hacer lo siguiente con su imagen:
from skimage.transform import resize bottle_resized = resize(bottle, (140, 54))
Esto se ocupará de cosas como la interpolación, el suavizado, etc.
fuente
anti_aliasing
bandera, parece que se ha eliminado de la versión más reciente de 0.13.1Para las personas que vienen aquí desde Google y buscan una manera rápida de reducir la resolución de imágenes en
numpy
matrices para usarlas en aplicaciones de aprendizaje automático, aquí hay un método súper rápido (adaptado de aquí ). Este método solo funciona cuando las dimensiones de entrada son un múltiplo de las dimensiones de salida.Los siguientes ejemplos reducen la resolución de 128x128 a 64x64 (esto se puede cambiar fácilmente).
Último pedido de canales
# large image is shape (128, 128, 3) # small image is shape (64, 64, 3) input_size = 128 output_size = 64 bin_size = input_size // output_size small_image = large_image.reshape((output_size, bin_size, output_size, bin_size, 3)).max(3).max(1)
Primer pedido de canales
# large image is shape (3, 128, 128) # small image is shape (3, 64, 64) input_size = 128 output_size = 64 bin_size = input_size // output_size small_image = large_image.reshape((3, output_size, bin_size, output_size, bin_size)).max(4).max(2)
Para imágenes en escala de grises, simplemente cambie el
3
a algo1
así:Primer pedido de canales
# large image is shape (1, 128, 128) # small image is shape (1, 64, 64) input_size = 128 output_size = 64 bin_size = input_size // output_size small_image = large_image.reshape((1, output_size, bin_size, output_size, bin_size)).max(4).max(2)
Este método utiliza el equivalente a la agrupación máxima. Es la forma más rápida de hacer esto que he encontrado.
fuente
np.repeat(np.repeat(a, 2, axis=0), 2, axis=1)
Si alguien vino aquí buscando un método simple para escalar / cambiar el tamaño de una imagen en Python, sin usar bibliotecas adicionales, aquí hay una función de cambio de tamaño de imagen muy simple:
#simple image scaling to (nR x nC) size def scale(im, nR, nC): nR0 = len(im) # source number of rows nC0 = len(im[0]) # source number of columns return [[ im[int(nR0 * r / nR)][int(nC0 * c / nC)] for c in range(nC)] for r in range(nR)]
Ejemplo de uso: cambiar el tamaño de una imagen (30 x 30) a (100 x 200):
import matplotlib.pyplot as plt def sqr(x): return x*x def f(r, c, nR, nC): return 1.0 if sqr(c - nC/2) + sqr(r - nR/2) < sqr(nC/4) else 0.0 # a red circle on a canvas of size (nR x nC) def circ(nR, nC): return [[ [f(r, c, nR, nC), 0, 0] for c in range(nC)] for r in range(nR)] plt.imshow(scale(circ(30, 30), 100, 200))
Salida:
Esto funciona para encoger / escalar imágenes y funciona bien con matrices numpy.
fuente
El
imresize()
método de SciPy fue otro método de cambio de tamaño, pero se eliminará a partir de SciPy v 1.3.0. SciPy se refiere al método de cambio de tamaño de la imagen PIL :Image.resize(size, resample=0)
tamaño : el tamaño solicitado en píxeles, como 2 tuplas: (ancho, alto).
remuestrear : un filtro de remuestreo opcional. Puede ser PIL.Image.NEAREST (utilice el vecino más cercano), PIL.Image.BILINEAR (interpolación lineal), PIL.Image.BICUBIC (interpolación spline cúbica) o PIL.Image.LANCZOS (un filtro de submuestreo de alta calidad ). Si se omite, o si la imagen tiene modo “1” o “P”, se establece PIL.Image.NEAREST.
Enlace aquí: https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize
fuente
Por supuesto. Puede hacer esto sin OpenCV, scikit-image o PIL.
El cambio de tamaño de la imagen consiste básicamente en mapear las coordenadas de cada píxel desde la imagen original a su posición redimensionada.
Dado que las coordenadas de una imagen deben ser números enteros (piénselo como una matriz), si la coordenada mapeada tiene valores decimales, debe interpolar el valor del píxel para aproximarlo a la posición del número entero (por ejemplo, se conoce cómo obtener el píxel más cercano a esa posición como interpolación del vecino más cercano ).
Todo lo que necesita es una función que haga esta interpolación por usted. SciPy tiene
interpolate.interp2d
.Puede usarlo para cambiar el tamaño de una imagen en una matriz numpy, digamos
arr
, de la siguiente manera:W, H = arr.shape[:2] new_W, new_H = (600,300) xrange = lambda x: np.linspace(0, 1, x) f = interp2d(xrange(W), xrange(H), arr, kind="linear") new_arr = f(xrange(new_W), xrange(new_H))
Por supuesto, si su imagen es RGB, debe realizar la interpolación para cada canal.
Si desea comprender más, le sugiero que vea Cambiar el tamaño de las imágenes - Computerphile .
fuente
import cv2 import numpy as np image_read = cv2.imread('filename.jpg',0) original_image = np.asarray(image_read) width , height = 452,452 resize_image = np.zeros(shape=(width,height)) for W in range(width): for H in range(height): new_width = int( W * original_image.shape[0] / width ) new_height = int( H * original_image.shape[1] / height ) resize_image[W][H] = original_image[new_width][new_height] print("Resized image size : " , resize_image.shape) cv2.imshow(resize_image) cv2.waitKey(0)
fuente
cv2
y usa una función de cambio de tamaño adecuada en lugar de volver a implementar una función de cambio de tamaño "subóptima" que funciona peor que la interpolación del vecino más cercano.