Como redimensionar uma imagem com OpenCV2.0 e Python2.6

163

Eu quero usar o OpenCV2.0 e o Python2.6 para mostrar imagens redimensionadas. Usei e adotei o exemplo em http://opencv.willowgarage.com/documentation/python/cookbook.html, mas infelizmente esse código é para o OpenCV2.1 e parece não estar funcionando no 2.0. Aqui meu 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)

Desde que eu não posso usar

cv.LoadImageM

eu usei

cv.LoadImage

em vez disso, o que não era problema em outros aplicativos. No entanto, o cv.iplimage não possui linhas, colunas ou tamanho de atributo. Alguém pode me dar uma dica, como resolver esse problema? Obrigado.

Bastian
fonte
4
Se alguma das respostas estiver correta, marque-a para ajudar outras pessoas.
Michał

Respostas:

342

Se você deseja usar o CV2, você precisa usar a resizefunção.

Por exemplo, isso redimensionará os dois eixos pela metade:

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

e isso redimensionará a imagem para ter 100 colunas (largura) e 50 linhas (altura):

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

Outra opção é usar o scipymódulo, usando:

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

Obviamente, há mais opções que você pode ler na documentação dessas funções ( cv2.resize , scipy.misc.imresize ).


Atualização: de
acordo com a documentação SciPy :

imresizefoi descontinuado no SciPy 1.0.0 e será removido no 1.2.0.
Usarskimage.transform.resize vez disso.

Observe que, se você deseja redimensionar por um fator , pode realmente querer skimage.transform.rescale.

emem
fonte
1
a função redimensionar () não faz com que a imagem perca informações sobre si mesma?
8
Sim, você não pode reduzir o tamanho da imagem sem perder informações.
Rafael_Espericueta
1
A implementação opencv (0,05 ms por imagem) parece ser muito mais rápida que a implementação scipy (imagem de 0,33 ms). Redimensionei as imagens de 210x160x1 a 84x84x1 com interpolação bilinear.
Gizzmole
@gizzmole Introspecção interessante. Não testei a eficiência das implementações, nem comparei os resultados - portanto, o resultado final também pode ser um pouco diferente. Você testou para ver as imagens redimensionadas correspondendo aos bits?
Emem 15/05
Thaks para apontar que a função de redimensionamento tomada (W * H) ao passo que de impressão como CV2 (W * H)
Shivam Kotwalia
59

Exemplo dobrando o tamanho da imagem

Existem duas maneiras de redimensionar uma imagem. O novo tamanho pode ser especificado:

  1. Manualmente;

    height, width = src.shape[:2]

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

  2. Por um fator de escala.

    dst = cv2.resize(src, None, fx = 2, fy = 2, interpolation = cv2.INTER_CUBIC), em que fx é o fator de escala no eixo horizontal e fy no eixo vertical.

Para reduzir uma imagem, ela geralmente fica melhor com a interpolação INTER_AREA, enquanto que para ampliar uma imagem geralmente fica melhor com INTER_CUBIC (lenta) ou INTER_LINEAR (mais rápida, mas ainda parece OK).

Exemplo de imagem reduzida para ajustar-se a uma altura / largura máxima (mantendo a proporção)

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 seu código com 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
fonte
sua solução usando os fatores de escala retorna um erro em cv2.resize () dizendo 'src não é um array numpy nem um escalar'. Por favor informar?
BenP 29/01/19
você fez: src = cv2.imread('YOUR_PATH_TO_IMG')e editou o 'YOUR_PATH_TO_IMG' no caminho da sua própria imagem?
João Cartucho
faz cv2.resizeautomaticamente usa preenchimento? qual é o tamanho da janela criada usando o tamanho de saída desejado como (width/10, height/10)?
Seralouk 28/05/19
@makaros você obter uma imagem que é 10x menor, tanto em largura e altura
João Cartucho
@ JoãoCartucho sim, eu entendo isso. Mas quando o closest_neighbors mais próximo é usado, uma janela deve ser aplicada nos bastidores. Isto é o que eu estou pedindo ..
seralouk
8

Você poderia usar a função GetSize para obter essas informações, cv.GetSize (im) retornaria uma tupla com a largura e a altura da imagem. Você também pode usar im.depth e img.nChan para obter mais informações.

E para redimensionar uma imagem, eu usaria um processo ligeiramente diferente, com outra imagem em vez de uma matriz. É melhor tentar trabalhar com o mesmo tipo de dados:

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

Espero que isto ajude ;)

Julien

jlengrand
fonte
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
fonte
faz cv2.resizeautomaticamente usa preenchimento? qual é o tamanho da janela criada usando (w, target_height)argumentos?
seralouk 28/05/19
4

Aqui está uma função para aumentar ou diminuir a escala da imagem pela largura ou altura desejada, mantendo a proporção

# 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 imagem de exemplo

insira a descrição da imagem aqui

Simplesmente reduza a escala para width=100(esquerda) ou faça o upscale para width=300(direita)

insira a descrição da imagem aqui insira a descrição da imagem aqui

nathancy
fonte