147 votes

Numpy Redimensionner/Réduire l'image

Je voudrais prendre une image et changer l'échelle de l'image, alors qu'elle est un tableau numpy.

Par exemple, j'ai cette image d'une bouteille de coca-cola : bouteille-1

Ce qui se traduit par un tableau numpy de forme (528, 203, 3) et je veux le redimensionner à la taille de cette deuxième image : bouteille-2

Qui a une forme de (140, 54, 3) .

Comment puis-je modifier la taille de l'image pour lui donner une certaine forme tout en conservant l'image originale ? D'autres réponses suggèrent de supprimer une ligne sur deux ou sur trois, mais ce que je veux faire, c'est réduire l'image comme on le ferait avec un éditeur d'images, mais en code Python. Existe-t-il des bibliothèques pour faire cela en numpy/SciPy ?

0 votes

Pouvez-vous montrer le code de votre tableau numpy ?

1 votes

2 votes

@sascha Déprécié, selon la page que vous avez liée.

177voto

CommuSoft Points 6439

Oui, vous pouvez installer opencv (il s'agit d'une bibliothèque utilisée pour le traitement de l'image et la vision par ordinateur), et utilisez la balise cv2.resize fonction. Et à utiliser par exemple :

import cv2
import numpy as np

img = cv2.imread('your_image.jpg')
res = cv2.resize(img, dsize=(54, 140), interpolation=cv2.INTER_CUBIC)

Ici img est donc un tableau numpy contenant l'image originale, alors que res est un tableau numpy contenant les redimensionné l'image. Un aspect important est le interpolation paramètre : il existe plusieurs façons de redimensionner une image. D'autant plus que vous réduisez l'échelle de l'image, et que la taille de l'image originale est no un multiple de la taille de l'image redimensionnée. Les schémas d'interpolation possibles sont :

  • INTER_NEAREST - une interpolation des plus proches voisins
  • INTER_LINEAR - une interpolation bilinéaire (utilisée par défaut)
  • INTER_AREA - rééchantillonnage utilisant la relation entre la surface des pixels. Il s'agit d'une méthode privilégiée pour la décimation des images, car elle donne des résultats sans moirage. sans moirage. Mais lorsque l'image est zoomée, elle est similaire à l'image INTER_NEAREST méthode.
  • INTER_CUBIC - une interpolation bicubique sur un voisinage de 4x4 pixels
  • INTER_LANCZOS4 - une interpolation de Lanczos sur un voisinage de 8x8 pixels

Comme pour la plupart des options, il n'y a pas de "meilleure" option dans le sens où, pour chaque schéma de redimensionnement, il existe des scénarios où une stratégie peut être préférée à une autre.

5 votes

Je viens d'essayer ce code et il fonctionne ! Un seul changement est que dsize devrait être dsize=(54, 140) car il prend x puis y, alors qu'un tableau numpy montre la forme comme y puis x (y est le nombre de lignes et x est le nombre de colonnes)

8 votes

J'essaie d'éviter cv2, il échange les dimensions et charge dans le format de canal BGR. Je préfère skimage.io.imread('image.jpg') y skimage.transform.resize(img) . scikit-image.org/docs/dev/install.html

2 votes

@EduardoPignatelli J'évite skimage.transform.resize car vous n'avez pas le contrôle de l'algorithme d'interpolation qu'il utilise. Mais, cela peut ne pas être important, selon les cas d'utilisation des gens.

104voto

jakevdp Points 4711

Bien qu'il soit possible d'utiliser numpy seul pour le faire, cette opération n'est pas intégrée. Cela dit, vous pouvez utiliser scikit-image (qui est construit sur numpy) pour faire ce genre de manipulation d'images.

La documentation sur le redimensionnement de Scikit-Image est la suivante aquí .

Par exemple, vous pouvez faire ce qui suit avec votre image :

from skimage.transform import resize
bottle_resized = resize(bottle, (140, 54))

Cela prendra en charge des choses comme l'interpolation, l'anticrénelage, etc. pour vous.

2 votes

Merci ! Cette réponse fonctionne également ! Bien que j'aie un problème avec le anti_aliasing il semble qu'il ait été supprimé de la dernière version de 0.13.1

13 votes

Cela renvoie l'image comme float ndarray même si votre image originale est uint8

3 votes

C'est une technique intéressante car elle fonctionne avec un nombre quelconque de canaux. Je l'ai essayée avec des données rgb combinées à un nuage de points de profondeur et elle a préservé la relation comme je le voulais.

26voto

Waylon Flinn Points 8140

Pour les personnes qui viennent de Google et qui cherchent un moyen rapide de sous-échantillonner des images en numpy pour l'utilisation dans des applications d'apprentissage automatique, voici une méthode super rapide (adaptée de aquí ). Cette méthode ne fonctionne que lorsque les dimensions d'entrée sont un multiple des dimensions de sortie.

Les exemples suivants réduisent l'échantillonnage de 128x128 à 64x64 (ceci peut être facilement modifié).

Dernières commandes de chaînes

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

Commande de canaux en premier lieu

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

Pour les images en niveaux de gris, il suffit de modifier le paramètre 3 à un 1 comme ça :

Commande de canaux en premier lieu

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

Cette méthode utilise l'équivalent du max pooling. C'est la méthode la plus rapide que j'ai trouvée.

7 votes

Large_image[ :, ::2, ::2] renvoie l'image avec une résolution divisée par deux.

2 votes

@LasseKärkkäinen mais elle ne déséchantillonne pas, elle sélectionne simplement un pixel sur deux. La différence est que la fonction finale 'max' peut être modifiée pour sélectionner ou calculer les pixels de manière légèrement plus efficace (en utilisant 'min' ou 'mean' par exemple). Votre méthode est utile (et plus rapide), si cela n'a pas d'importance.

0 votes

@L.Kärkkäinen quel est le contraire de cette double résolution ?

3voto

cemsazara Points 109

SciPy imresize() était une autre méthode de redimensionnement, mais elle sera supprimée à partir de SciPy v 1.3.0 . SciPy fait référence à LIP méthode de redimensionnement de l'image : Image.resize(size, resample=0)

taille - La taille demandée en pixels, sous forme de 2-tuple : (largeur, hauteur).
rééchantillonner - Un filtre de rééchantillonnage facultatif. Il peut s'agir d'un des filtres suivants : PIL.Image.NEAREST (utilisation du plus proche voisin), PIL.Image.BILINEAR (interpolation linéaire), PIL.Image.BICUBIC (interpolation par spline cubique) ou PIL.Image.LANCZOS (filtre de sous-échantillonnage de haute qualité). S'il est omis, ou si l'image a le mode "1" ou "P", il est défini PIL.Image.NEAREST.

Lien ici : https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize

3 votes

Malheureusement, imresize() est déprécié et sera supprimé dans SciPy 1.3.0.

1 votes

La question précise que l'image est un tableau numpy ; vous ne pouvez pas utiliser Pillow sur ce tableau.

0voto

M. Farzalizadeh Points 19
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)

5 votes

Bienvenue sur StackOverflow. C'est bien que vous vouliez aider les autres en répondant à leurs questions. Cependant, je ne vois pas comment votre réponse apporte une valeur ajoutée par rapport à la réponse existante qui utilise déjà cv2 et utilise une fonction de redimensionnement correcte au lieu de réimplémenter une fonction de redimensionnement "sous-optimale" qui fait pire que l'interpolation du plus proche voisin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X