Comment redimensionner une image avec OpenCV2.0 et Python2.6

163

Je souhaite utiliser OpenCV2.0 et Python2.6 pour afficher des images redimensionnées. J'ai utilisé et adopté l'exemple à http://opencv.willowgarage.com/documentation/python/cookbook.html mais malheureusement ce code est pour OpenCV2.1 et ne semble pas fonctionner sur 2.0. Voici mon code:

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)

Puisque je ne peux pas utiliser

cv.LoadImageM

j'ai utilisé

cv.LoadImage

au lieu de cela, ce qui ne posait aucun problème dans d'autres applications. Néanmoins cv.iplimage n'a pas de lignes d'attributs, de colonnes ou de taille. Quelqu'un peut-il me donner un indice, comment résoudre ce problème? Merci.

Bastian
la source
4
Si l'une des réponses était correcte, veuillez la marquer car elle aidera les autres.
Michał

Réponses:

343

Si vous souhaitez utiliser CV2, vous devez utiliser la resizefonction.

Par exemple, cela redimensionnera les deux axes de moitié:

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

et cela redimensionnera l'image pour avoir 100 cols (largeur) et 50 lignes (hauteur):

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

Une autre option consiste à utiliser le scipymodule, en utilisant:

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

Il y a évidemment plus d'options que vous pouvez lire dans la documentation de ces fonctions ( cv2.resize , scipy.misc.imresize ).


Mise à jour:
selon la documentation SciPy :

imresizeest obsolète dans SciPy 1.0.0 et sera supprimé dans 1.2.0.
Utilisez skimage.transform.resizeplutôt.

Notez que si vous cherchez à redimensionner par un facteur , vous voudrez peut-être skimage.transform.rescale.

emem
la source
1
la fonction resize () ne fait-elle pas perdre à l'image des informations sur elle-même?
8
Oui, vous ne pouvez pas réduire la taille de l'image sans perdre d'informations.
Rafael_Espericueta
1
L'implémentation opencv (0,05 ms par image) semble être beaucoup plus rapide que l'implémentation scipy (image 0,33 ms). J'ai redimensionné des images de 210x160x1 à 84x84x1 avec interpolation bilinéaire.
gizzmole
@gizzmole Un aperçu intéressant. Je n'ai pas testé l'efficacité des implémentations, ni comparé les résultats - le résultat final peut donc également différer légèrement. Avez-vous testé pour voir les images redimensionnées correspondent au niveau du bit?
emem
Merci d'avoir souligné que la fonction de redimensionnement prend (W * H) alors que cv2 s'imprime comme (H * W)
Shivam Kotwalia
59

Exemple de doublement de la taille de l'image

Il existe deux façons de redimensionner une image. La nouvelle taille peut être spécifiée:

  1. Manuellement;

    height, width = src.shape[:2]

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

  2. Par un facteur d'échelle.

    dst = cv2.resize(src, None, fx = 2, fy = 2, interpolation = cv2.INTER_CUBIC), où fx est le facteur de mise à l'échelle le long de l'axe horizontal et fy le long de l'axe vertical.

Pour réduire une image, elle sera généralement meilleure avec l'interpolation INTER_AREA, tandis que pour agrandir une image, elle sera généralement meilleure avec INTER_CUBIC (lent) ou INTER_LINEAR (plus rapide mais semble toujours OK).

Exemple d'image réduite pour s'adapter à une hauteur / largeur maximale (en conservant le rapport hauteur / largeur)

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

Utiliser votre code avec 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
la source
votre solution utilisant les facteurs de mise à l'échelle renvoie une erreur sur cv2.resize () en disant 'src n'est pas un tableau numpy, ni un scalaire.' s'il vous plaît donnez votre avis?
BenP
avez-vous fait: src = cv2.imread('YOUR_PATH_TO_IMG')et édité le 'YOUR_PATH_TO_IMG' sur le chemin de votre propre image?
João Cartucho
cv2.resizen'utilise automatiquement le rembourrage? quelle est la taille de la fenêtre créée en utilisant la taille de sortie souhaitée (width/10, height/10)?
seralouk
@makaros vous obtenez une image 10x plus petite en largeur et en hauteur
João Cartucho
@ JoãoCartucho oui je comprends cela. Mais lorsque plus proche_neighbours est utilisé, une fenêtre doit être appliquée dans les coulisses. C'est ce que je demande ..
seralouk
8

Vous pouvez utiliser la fonction GetSize pour obtenir ces informations, cv.GetSize (im) renverrait un tuple avec la largeur et la hauteur de l'image. Vous pouvez également utiliser im.depth et img.nChan pour obtenir plus d'informations.

Et pour redimensionner une image, j'utiliserais un processus légèrement différent, avec une autre image au lieu d'une matrice. Il vaut mieux essayer de travailler avec le même type de données:

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

J'espère que cela t'aides ;)

Julien

Jlengrand
la source
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
la source
cv2.resizen'utilise automatiquement le rembourrage? quelle est la taille de la fenêtre créée à l'aide d' (w, target_height)arguments?
seralouk
4

Voici une fonction pour augmenter ou réduire une image de la largeur ou de la hauteur souhaitée tout en conservant le rapport hauteur / largeur

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

Usage

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

Utilisation de cette image d'exemple

entrez la description de l'image ici

Réduisez simplement l'échelle vers width=100(gauche) ou augmentez l'échelle vers width=300(droite)

entrez la description de l'image ici entrez la description de l'image ici

Nathancy
la source