Cómo cambiar el tamaño de una imagen con OpenCV2.0 y Python2.6

163

Quiero usar OpenCV2.0 y Python2.6 para mostrar imágenes redimensionadas. Usé y adopté el ejemplo en http://opencv.willowgarage.com/documentation/python/cookbook.html pero desafortunadamente este código es para OpenCV2.1 y parece que no funciona en 2.0. Aquí mi código:

import os, glob
import cv

ulpath = "exampleshq/"

for infile in glob.glob( os.path.join(ulpath, "*.jpg") ):
    im = cv.LoadImage(infile)
    thumbnail = cv.CreateMat(im.rows/10, im.cols/10, cv.CV_8UC3)
    cv.Resize(im, thumbnail)
    cv.NamedWindow(infile)
    cv.ShowImage(infile, thumbnail)
    cv.WaitKey(0)
    cv.DestroyWindow(name)

Como no puedo usar

cv.LoadImageM

solía

cv.LoadImage

en cambio, lo que no fue un problema en otras aplicaciones. Sin embargo, cv.iplimage no tiene filas de atributos, cols o tamaño. ¿Alguien puede darme una pista, cómo resolver este problema? Gracias.

Bastian
fuente
44
Si alguna de las respuestas fue correcta, márquela ya que ayudará a otros.
Michał

Respuestas:

342

Si desea usar CV2, debe usar la resizefunción.

Por ejemplo, esto redimensionará ambos ejes a la mitad:

small = cv2.resize(image, (0,0), fx=0.5, fy=0.5) 

y esto redimensionará la imagen para que tenga 100 cols (ancho) y 50 filas (alto):

resized_image = cv2.resize(image, (100, 50)) 

Otra opción es usar el scipymódulo, usando:

small = scipy.misc.imresize(image, 0.5)

Obviamente, hay más opciones que puede leer en la documentación de esas funciones ( cv2.resize , scipy.misc.imresize ).


Actualización: de
acuerdo con la documentación de SciPy :

imresizeestá en desuso en SciPy 1.0.0 y se eliminará en 1.2.0.
Usar en su skimage.transform.resizelugar.

Tenga en cuenta que si está buscando cambiar el tamaño por un factor , es posible que desee skimage.transform.rescale.

emem
fuente
1
¿La función resize () no hace que la imagen pierda información sobre sí misma?
8
Sí, no puede reducir el tamaño de la imagen sin perder información.
Rafael_Espericueta
1
La implementación de opencv (0.05ms por imagen) parece ser mucho más rápida que la implementación scipy (imagen de 0.33ms). Cambié el tamaño de las imágenes de 210x160x1 a 84x84x1 con interpolación bilineal.
gizzmole
@gizzmole Información interesante. No probé la eficiencia de las implementaciones ni comparé los resultados, por lo que el resultado final también puede diferir ligeramente. ¿Probaste para ver que las imágenes redimensionadas coinciden bit a bit?
emem
Gracias por señalar que la función de cambio de tamaño toma (W * H) mientras que cv2 se imprime como (H * W)
Shivam Kotwalia
59

Ejemplo duplicando el tamaño de la imagen

Hay dos formas de cambiar el tamaño de una imagen. Se puede especificar el nuevo tamaño:

  1. A mano;

    height, width = src.shape[:2]

    dst = cv2.resize(src, (2*width, 2*height), interpolation = cv2.INTER_CUBIC)

  2. Por un factor de escala.

    dst = cv2.resize(src, None, fx = 2, fy = 2, interpolation = cv2.INTER_CUBIC), donde fx es el factor de escala a lo largo del eje horizontal y fy a lo largo del eje vertical.

Para reducir una imagen, generalmente se verá mejor con la interpolación INTER_AREA, mientras que para agrandar una imagen, generalmente se verá mejor con INTER_CUBIC (lento) o INTER_LINEAR (más rápido pero aún se ve bien).

Ejemplo de reducción de imagen para ajustarse a una altura / anchura máxima (manteniendo la relación de aspecto)

import cv2

img = cv2.imread('YOUR_PATH_TO_IMG')

height, width = img.shape[:2]
max_height = 300
max_width = 300

# only shrink if img is bigger than required
if max_height < height or max_width < width:
    # get scaling factor
    scaling_factor = max_height / float(height)
    if max_width/float(width) < scaling_factor:
        scaling_factor = max_width / float(width)
    # resize image
    img = cv2.resize(img, None, fx=scaling_factor, fy=scaling_factor, interpolation=cv2.INTER_AREA)

cv2.imshow("Shrinked image", img)
key = cv2.waitKey()

Usando su código con cv2

import cv2 as cv

im = cv.imread(path)

height, width = im.shape[:2]

thumbnail = cv.resize(im, (round(width / 10), round(height / 10)), interpolation=cv.INTER_AREA)

cv.imshow('exampleshq', thumbnail)
cv.waitKey(0)
cv.destroyAllWindows()
João Cartucho
fuente
su solución usando los factores de escala devuelve un error en cv2.resize () diciendo 'src no es una matriz numpy, ni un escalar'. ¿por favor avise?
BenP
hiciste: src = cv2.imread('YOUR_PATH_TO_IMG')y editaste 'YOUR_PATH_TO_IMG' en la ruta de tu propia imagen?
João Cartucho el
lo hace cv2.resizede forma automática utiliza el relleno? ¿Cuál es el tamaño de la ventana que se crea usando el tamaño de salida deseado (width/10, height/10)?
seralouk
@makaros obtienes una imagen que es 10 veces más pequeña tanto en ancho como en altura
João Cartucho
@ JoãoCartucho sí, entiendo esto. Sin embargo, cuando se utiliza el vecino más cercano, se debe aplicar una ventana detrás de escena. Esto es lo que pido ..
seralouk
8

Puede usar la función GetSize para obtener esa información, cv.GetSize (im) devolvería una tupla con el ancho y la altura de la imagen. También puede usar im.depth e img.nChan para obtener más información.

Y para cambiar el tamaño de una imagen, usaría un proceso ligeramente diferente, con otra imagen en lugar de una matriz. Es mejor intentar trabajar con el mismo tipo de datos:

size = cv.GetSize(im)
thumbnail = cv.CreateImage( ( size[0] / 10, size[1] / 10), im.depth, im.nChannels)
cv.Resize(im, thumbnail)

Espero que esto ayude ;)

Julien

jlengrand
fuente
6
def rescale_by_height(image, target_height, method=cv2.INTER_LANCZOS4):
    """Rescale `image` to `target_height` (preserving aspect ratio)."""
    w = int(round(target_height * image.shape[1] / image.shape[0]))
    return cv2.resize(image, (w, target_height), interpolation=method)

def rescale_by_width(image, target_width, method=cv2.INTER_LANCZOS4):
    """Rescale `image` to `target_width` (preserving aspect ratio)."""
    h = int(round(target_width * image.shape[0] / image.shape[1]))
    return cv2.resize(image, (target_width, h), interpolation=method)
AndyP
fuente
lo hace cv2.resizede forma automática utiliza el relleno? ¿Cuál es el tamaño de la ventana que se crea utilizando (w, target_height)argumentos?
seralouk
4

Aquí hay una función para aumentar o disminuir la escala de una imagen según el ancho o la altura deseados mientras se mantiene la relación de aspecto

# Resizes a image and maintains aspect ratio
def maintain_aspect_ratio_resize(image, width=None, height=None, inter=cv2.INTER_AREA):
    # Grab the image size and initialize dimensions
    dim = None
    (h, w) = image.shape[:2]

    # Return original image if no need to resize
    if width is None and height is None:
        return image

    # We are resizing height if width is none
    if width is None:
        # Calculate the ratio of the height and construct the dimensions
        r = height / float(h)
        dim = (int(w * r), height)
    # We are resizing width if height is none
    else:
        # Calculate the ratio of the width and construct the dimensions
        r = width / float(w)
        dim = (width, int(h * r))

    # Return the resized image
    return cv2.resize(image, dim, interpolation=inter)

Uso

import cv2

image = cv2.imread('1.png')
cv2.imshow('width_100', maintain_aspect_ratio_resize(image, width=100))
cv2.imshow('width_300', maintain_aspect_ratio_resize(image, width=300))
cv2.waitKey()

Usando esta imagen de ejemplo

ingrese la descripción de la imagen aquí

Simplemente reducir a width=100(izquierda) o aumentar a width=300(derecha)

ingrese la descripción de la imagen aquí ingrese la descripción de la imagen aquí

nathancy
fuente