Come ridimensionare un'immagine con OpenCV2.0 e Python2.6


163

Voglio usare OpenCV2.0 e Python2.6 per mostrare immagini ridimensionate. Ho usato e adottato l'esempio su http://opencv.willowgarage.com/documentation/python/cookbook.html ma sfortunatamente questo codice è per OpenCV2.1 e sembra non funzionare su 2.0. Ecco il mio codice:

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)

Dal momento che non posso usare

cv.LoadImageM

ero solito

cv.LoadImage

invece, che non è stato un problema in altre applicazioni. Tuttavia cv.iplimage non ha righe, colonne o dimensioni degli attributi. Qualcuno può darmi un suggerimento, come risolvere questo problema? Grazie.


4
Se una delle risposte era corretta, contrassegnala perché aiuterà gli altri.
Michał,

Risposte:


343

Se si desidera utilizzare CV2, è necessario utilizzare la resizefunzione.

Ad esempio, questo ridimensionerà entrambi gli assi della metà:

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

e questo ridimensionerà l'immagine per avere 100 cols (larghezza) e 50 righe (altezza):

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

Un'altra opzione è quella di utilizzare il scipymodulo, usando:

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

Esistono ovviamente più opzioni che puoi leggere nella documentazione di tali funzioni ( cv2.resize , scipy.misc.imresize ).


Aggiornamento:
secondo la documentazione di SciPy :

imresizeè obsoleto in SciPy 1.0.0 e verrà rimosso in 1.2.0.
Usa skimage.transform.resizeinvece.

Nota che se stai cercando di ridimensionare in base a un fattore , potresti effettivamente volerlo skimage.transform.rescale.


1
la funzione resize () non rende l'immagine perdere informazioni su se stessa?

8
Sì, non puoi ridurre le dimensioni dell'immagine senza perdere informazioni.
Rafael_Espericueta,

1
L'implementazione opencv (0,05 ms per immagine) sembra essere molto più veloce dell'implementazione di scipy (immagine 0,33 ms). Ho ridimensionato le immagini da 210x160x1 a 84x84x1 con interpolazione bilineare.
gizzmole,

@gizzmole Informazioni interessanti. Non ho testato l'efficienza delle implementazioni, né confrontato i risultati, quindi anche il risultato finale potrebbe differire leggermente. Hai provato a vedere le immagini ridimensionate abbinare bit a bit?
emem

Grazie per aver sottolineato che la funzione di ridimensionamento prende (W * H) mentre cv2 stampa come (H * W)
Shivam Kotwalia,

59

Esempio di raddoppio della dimensione dell'immagine

Esistono due modi per ridimensionare un'immagine. È possibile specificare la nuova dimensione:

  1. manualmente;

    height, width = src.shape[:2]

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

  2. Per un fattore di ridimensionamento.

    dst = cv2.resize(src, None, fx = 2, fy = 2, interpolation = cv2.INTER_CUBIC), dove fx è il fattore di ridimensionamento lungo l'asse orizzontale e fy lungo l'asse verticale.

Per ridurre un'immagine, generalmente avrà un aspetto migliore con l'interpolazione INTER_AREA, mentre per ingrandire un'immagine, avrà generalmente un aspetto migliore con INTER_CUBIC (lento) o INTER_LINEAR (più veloce ma sembra comunque OK).

Esempio di riduzione dell'immagine per adattarla a un'altezza / larghezza massima (mantenendo le proporzioni)

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 il tuo codice 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()

la tua soluzione usando i fattori di ridimensionamento restituisce un errore su cv2.resize () dicendo "src non è un array intorpidito, né uno scalare". si prega di avvisare?
BenP,

hai fatto: src = cv2.imread('YOUR_PATH_TO_IMG')e modificato il 'YOUR_PATH_TO_IMG' sul percorso della tua immagine?
João Cartucho,

lo fa cv2.resizeautomaticamente usi imbottitura? qual è la dimensione della finestra che viene creata usando la dimensione di output desiderata come (width/10, height/10)?
seralouk,

@makaros ottieni un'immagine 10 volte più piccola sia in larghezza che in altezza
João Cartucho,

@ JoãoCartucho sì, lo capisco. Ma quando si usa la zona di vicinato, una finestra dovrebbe essere applicata dietro le quinte. Questo è quello che chiedo ...
seralouk,

8

È possibile utilizzare la funzione GetSize per ottenere tali informazioni, cv.GetSize (im) restituisce una tupla con la larghezza e l'altezza dell'immagine. Puoi anche usare im.depth e img.nChan per ottenere qualche informazione in più.

E per ridimensionare un'immagine, utilizzerei un processo leggermente diverso, con un'altra immagine anziché una matrice. È meglio provare a lavorare con lo stesso tipo di dati:

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

Spero che questo ti aiuti ;)

Julien


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)

lo fa cv2.resizeautomaticamente usi imbottitura? qual è la dimensione della finestra creata usando gli (w, target_height)argomenti?
seralouk,

4

Ecco una funzione per ingrandire o ridurre l'immagine di una larghezza o altezza desiderata mantenendo le proporzioni

# 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()

Utilizzando questa immagine di esempio

inserisci qui la descrizione dell'immagine

Semplicemente downscale a width=100(sinistra) o upscale a width=300(destra)

inserisci qui la descrizione dell'immagine inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.