Je voudrais prendre une image et changer l'échelle de l'image, alors que c'est un tableau numpy.
Par exemple, j'ai cette image d'une bouteille de coca-cola: bottle-1
Ce qui se traduit par un tableau numpy de forme (528, 203, 3)
et je tiens à le redimensionner pour dire la taille de cette seconde image: bottle-2
Qui a la forme de (140, 54, 3)
.
Comment changer la taille de l'image en une certaine forme tout en conservant l'image d'origine? D'autres réponses suggèrent de supprimer toutes les lignes ou les trois lignes, mais ce que je veux faire, c'est réduire l'image comme vous le feriez avec un éditeur d'image, mais dans le code python. Existe-t-il des bibliothèques pour le faire dans numpy/SciPy?
Oui, vous pouvez installer opencv
(c'est une bibliothèque utilisée pour le traitement d'images, et la vision par ordinateur), et utiliser le cv2.resize
fonction. Et par exemple utiliser:
_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 d'origine, tandis que res
est un tableau numpy contenant l'image redimensionnée. Un aspect important est le paramètre interpolation
: il existe plusieurs façons de redimensionner une image. Surtout que vous réduisez l'image et que la taille de l'image d'origine est not un multiple de la taille de l'image redimensionnée. Les schémas d'interpolation possibles sont:
- _
INTER_NEAREST
_ - une interpolation du plus proche voisin- _
INTER_LINEAR
_ - une interpolation bilinéaire (utilisée par défaut)- _
INTER_AREA
_ - ré-échantillonnage en utilisant une relation de zone de pixel. Il peut s’agir d’une méthode privilégiée de décimation d’image, car elle donne des résultats sans moiré. Mais lorsque l'image est agrandie, elle est similaire à la méthode _INTER_NEAREST
_.- _
INTER_CUBIC
_ - une interpolation bicubique sur un voisinage de 4x4 pixels- _
INTER_LANCZOS4
_ - une interpolation Lanczos sur un voisinage de 8x8 pixels
Comme avec la plupart des options, il n'existe pas d'option "optimale" dans la mesure où, pour chaque schéma de redimensionnement, il existe des scénarios dans lesquels une stratégie peut être préférée à une autre.
Bien qu'il soit possible d'utiliser numpy seul pour cela, l'opération n'est pas intégrée. Cela dit, vous pouvez utiliser scikit-image
(qui est construit sur numpy) pour effectuer ce type de manipulation d’image.
La documentation de redimensionnement de Scikit-Image est ici .
Par exemple, vous pouvez faire ce qui suit avec votre image:
from skimage.transform import resize
bottle_resized = resize(bottle, (140, 54), anti_aliasing=True)
Cela prendra en charge pour vous des choses telles que l'interpolation, l'anti-aliasing, etc.
La méthode imresize()
de SciPy était une autre méthode de redimensionnement, mais elle sera supprimée à partir de SciPy v 1.3.0. SciPy fait référence à PIL méthode de redimensionnement de l'image: Image.resize(size, resample=0)
size - La taille souhaitée en pixels, sous forme de 2-Tuple: (largeur, hauteur).
resample - Filtre de rééchantillonnage facultatif. Il peut s'agir de PIL.Image.NEAREST (utiliser le plus proche voisin), PIL.Image.BILINEAR (interpolation linéaire), PIL.Image.BICUBIC (interpolation de spline cubique) ou PIL.Image.LANCZOS (filtre de sous-échantillonnage de haute qualité ). Si omis, ou si l'image a le mode “1” ou “P”, la valeur est PIL.Image.NEAREST.
Lien ici: https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize
Pour les personnes venant de Google qui recherchent un moyen rapide de sous-échantillonner les images dans les tableaux numpy
à utiliser dans les applications d’apprentissage automatique, voici une méthode très rapide (adaptée de here ). Cette méthode ne fonctionne que lorsque les dimensions en entrée sont un multiple des dimensions en sortie.
Les exemples suivants sous-échantillonnent de 128x128 à 64x64 (cela peut être facilement modifié).
Chaîne dernière commande
# 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)
Chaînes premier ordre
# 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 changer le 3
en 1
comme ceci:
Chaînes premier ordre
# 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 de la mise en pool maximale. C'est le moyen le plus rapide de le faire que j'ai trouvé.
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)