Skip to content

Concaténation d’images avec Python, Pillow

Oreiller (PIL) peut être utilisé pour concaténer (combiner) plusieurs images verticalement et horizontalement. Créez un arrière-plan avec Image.new() et collez les images avec Image.paste().

Il existe plusieurs façons de concaténer des images de tailles différentes.

Cet article décrit les cas suivants.

  • Concaténer des images de même hauteur ou largeur
  • Concaténer des images avec différentes hauteurs ou largeurs
    • Couper la zone supplémentaire et concaténer
    • Créer des marges et concaténer
    • Redimensionner et concaténer
  • Concaténer plusieurs images à la fois
  • Concaténer la même image à plusieurs reprises

Utilisez les deux images suivantes comme exemple.

from PIL import Image

im1 = Image.open('data/src/lena.jpg')
im2 = Image.open('data/src/rocket.jpg')

L’exemple de code est supposé être une image couleur (mode= »RGB »), mais le flux est le même pour les images monochromes (mode= »L »).

Pour plus d’informations sur la concaténation d’images à l’aide d’OpenCV et de scikit-image, consultez les articles suivants. Pour des images de même taille, scikit-image est facile à utiliser. Vous pouvez également ajouter une bordure entre les images.

Concaténer des images de même hauteur ou largeur

Créez un arrière-plan avec Image.new() et collez les images avec Image.paste().

def get_concat_h(im1, im2):
    dst = Image.new('RGB', (im1.width + im2.width, im1.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (im1.width, 0))
    return dst

def get_concat_v(im1, im2):
    dst = Image.new('RGB', (im1.width, im1.height + im2.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (0, im1.height))
    return dst

get_concat_h(im1, im1).save('data/dst/pillow_concat_h.jpg')
get_concat_v(im1, im1).save('data/dst/pillow_concat_v.jpg')

python oreiller concat h

python oreiller concat v

Couper la zone supplémentaire et concaténer

Dans Image.paste(), la zone hors de la plage de l’image à coller est ignorée (coupée).

Dans le cas d’un alignement horizontal, générez un arrière-plan avec une hauteur plus petite, et dans le cas d’un alignement vertical, générez une largeur plus petite, la zone en excès est coupée et concaténée.

def get_concat_h_cut(im1, im2):
    dst = Image.new('RGB', (im1.width + im2.width, min(im1.height, im2.height)))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (im1.width, 0))
    return dst

def get_concat_v_cut(im1, im2):
    dst = Image.new('RGB', (min(im1.width, im2.width), im1.height + im2.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (0, im1.height))
    return dst

get_concat_h_cut(im1, im2).save('data/dst/pillow_concat_h_cut.jpg')
get_concat_v_cut(im1, im2).save('data/dst/pillow_concat_v_cut.jpg')

oreiller python coupe concat h

python oreiller concat coupe v

Dans l’exemple ci-dessus, le bord supérieur ou gauche de chaque image est aligné. Les centres peuvent également être alignés.

def get_concat_h_cut_center(im1, im2):
    dst = Image.new('RGB', (im1.width + im2.width, min(im1.height, im2.height)))
    dst.paste(im1, (0, 0))
    dst.paste(im2, (im1.width, (im1.height - im2.height) // 2))
    return dst

def get_concat_v_cut_center(im1, im2):
    dst = Image.new('RGB', (min(im1.width, im2.width), im1.height + im2.height))
    dst.paste(im1, (0, 0))
    dst.paste(im2, ((im1.width - im2.width) // 2, im1.height))
    return dst

get_concat_h_cut_center(im1, im2).save('data/dst/pillow_concat_h_cut_center.jpg')
get_concat_v_cut_center(im1, im2).save('data/dst/pillow_concat_v_cut_center.jpg')

python oreiller concat h coupe centre

python oreiller concat v coupe centre

Créer des marges et concaténer

Créez des marges et concaténez pour éviter que l’image d’origine ne soit coupée.

Créez d’abord un grand arrière-plan. Vous pouvez faire la marge de n’importe quelle couleur en spécifiant le paramètre color de Image.new().

def get_concat_h_blank(im1, im2, color=(0, 0, 0)):
    dst = Image.new('RGB', (im1.width + im2.width, max(im1.height, im2.height)), color)
    dst.paste(im1, (0, 0))
    dst.paste(im2, (im1.width, 0))
    return dst

def get_concat_v_blank(im1, im2, color=(0, 0, 0)):
    dst = Image.new('RGB', (max(im1.width, im2.width), im1.height + im2.height), color)
    dst.paste(im1, (0, 0))
    dst.paste(im2, (0, im1.height))
    return dst

get_concat_h_blank(im1, im2).save('data/dst/pillow_concat_h_blank.jpg')
get_concat_v_blank(im1, im2, (0, 64, 128)).save('data/dst/pillow_concat_v_blank.jpg')

python oreiller concat h blanc

python oreiller concat v blanc

Redimensionner et concaténer

Redimensionnez l’image pour qu’elle corresponde à la largeur ou à la hauteur et reliez-les.

Dans l’exemple, il est possible de choisir de redimensionner une grande image en petit ou de redimensionner une petite image en grand. Fondamentalement, il est préférable de réduire la taille d’une grande image à une taille plus petite car la qualité de l’image diminue lorsqu’elle est agrandie.

En outre, le filtre de rééchantillonnage peut être spécifié.

def get_concat_h_resize(im1, im2, resample=Image.BICUBIC, resize_big_image=True):
    if im1.height == im2.height:
        _im1 = im1
        _im2 = im2
    elif (((im1.height > im2.height) and resize_big_image) or
          ((im1.height  im2.height) and not resize_big_image)):
        _im1 = im1.resize((int(im1.width * im2.height / im1.height), im2.height), resample=resample)
        _im2 = im2
    else:
        _im1 = im1
        _im2 = im2.resize((int(im2.width * im1.height / im2.height), im1.height), resample=resample)
    dst = Image.new('RGB', (_im1.width + _im2.width, _im1.height))
    dst.paste(_im1, (0, 0))
    dst.paste(_im2, (_im1.width, 0))
    return dst

def get_concat_v_resize(im1, im2, resample=Image.BICUBIC, resize_big_image=True):
    if im1.width == im2.width:
        _im1 = im1
        _im2 = im2
    elif (((im1.width > im2.width) and resize_big_image) or
          ((im1.width  im2.width) and not resize_big_image)):
        _im1 = im1.resize((im2.width, int(im1.height * im2.width / im1.width)), resample=resample)
        _im2 = im2
    else:
        _im1 = im1
        _im2 = im2.resize((im1.width, int(im2.height * im1.width / im2.width)), resample=resample)
    dst = Image.new('RGB', (_im1.width, _im1.height + _im2.height))
    dst.paste(_im1, (0, 0))
    dst.paste(_im2, (0, _im1.height))
    return dst

get_concat_h_resize(im1, im2).save('data/dst/pillow_concat_h_resize.jpg')
get_concat_v_resize(im1, im2, resize_big_image=False).save('data/dst/pillow_concat_v_resize.jpg')

oreiller python concat h redimensionner

python oreiller concat v redimensionner

Concaténer plusieurs images à la fois

Vous pouvez obtenir une image concaténée dans laquelle plusieurs images sont disposées en ligne verticalement et horizontalement à l’aide de la fonction définie ci-dessus.

Par exemple, passez une liste de PIL.Image et concaténez-les verticalement et horizontalement.

def get_concat_h_multi_blank(im_list):
    _im = im_list.pop(0)
    for im in im_list:
        _im = get_concat_h_blank(_im, im)
    return _im

get_concat_h_multi_blank([im1, im2, im1]).save('data/dst/pillow_concat_h_multi_blank.jpg')

python oreiller concat h multi blanc

Dans l’exemple ci-dessus, nous utilisons la fonction pour créer des marges. Si vous souhaitez concaténer avec d’autres méthodes, utilisez la fonction correspondante, le cas échéant.

Lors du redimensionnement et de l’organisation de plusieurs images, il est préférable de redimensionner d’abord toutes les images à la largeur ou à la hauteur finale pour éviter un redimensionnement répété et une détérioration de la qualité de l’image.

Ici, créez d’abord un grand arrière-plan avec Image.new().

def get_concat_h_multi_resize(im_list, resample=Image.BICUBIC):
    min_height = min(im.height for im in im_list)
    im_list_resize = [im.resize((int(im.width * min_height / im.height), min_height),resample=resample)
                      for im in im_list]
    total_width = sum(im.width for im in im_list_resize)
    dst = Image.new('RGB', (total_width, min_height))
    pos_x = 0
    for im in im_list_resize:
        dst.paste(im, (pos_x, 0))
        pos_x += im.width
    return dst

def get_concat_v_multi_resize(im_list, resample=Image.BICUBIC):
    min_width = min(im.width for im in im_list)
    im_list_resize = [im.resize((min_width, int(im.height * min_width / im.width)),resample=resample)
                      for im in im_list]
    total_height = sum(im.height for im in im_list_resize)
    dst = Image.new('RGB', (min_width, total_height))
    pos_y = 0
    for im in im_list_resize:
        dst.paste(im, (0, pos_y))
        pos_y += im.height
    return dst

get_concat_h_multi_resize([im1, im2, im1]).save('data/dst/pillow_concat_h_multi_resize.jpg')
get_concat_v_multi_resize([im1, im2, im1]).save('data/dst/pillow_concat_v_multi_resize.jpg')

python oreiller concat h multi redimensionner

python oreiller concat v multi redimensionner

La fonction d’arrangement dans une tuile est également facile. Passez une liste 2D de PIL.Image et disposez-les en mosaïques verticalement et horizontalement.

def get_concat_tile_resize(im_list_2d, resample=Image.BICUBIC):
    im_list_v = [get_concat_h_multi_resize(im_list_h, resample=resample) for im_list_h in im_list_2d]
    return get_concat_v_multi_resize(im_list_v, resample=resample)

get_concat_tile_resize([[im1],
                        [im1, im2],
                        [im1, im2, im1]]).save('data/dst/pillow_concat_tile_resize.jpg')

python oreiller concat tuile redimensionner

Les compréhensions de liste sont utilisées pour créer une liste d’images redimensionnée et pour calculer la largeur et la hauteur minimales, la largeur et la hauteur totales.

Concaténer la même image à plusieurs reprises

Si vous souhaitez combiner la même image à plusieurs reprises verticalement et horizontalement, il est difficile de le spécifier dans la liste 2D, il est donc pratique de préparer une fonction pour spécifier le nombre de répétitions.

def get_concat_h_repeat(im, column):
    dst = Image.new('RGB', (im.width * column, im.height))
    for x in range(column):
        dst.paste(im, (x * im.width, 0))
    return dst

def get_concat_v_repeat(im, row):
    dst = Image.new('RGB', (im.width, im.height * row))
    for y in range(row):
        dst.paste(im, (0, y * im.height))
    return dst

def get_concat_tile_repeat(im, row, column):
    dst_h = get_concat_h_repeat(im, column)
    return get_concat_v_repeat(dst_h, row)

im_s = im1.resize((im1.width // 2, im1.height // 2))
get_concat_tile_repeat(im_s, 3, 4).save('data/dst/pillow_concat_tile_repeat.jpg')

python oreiller concat tuile répéter