
Il cuscino (PIL) può essere utilizzato per concatenare (combinare) più immagini verticalmente e orizzontalmente. Crea uno sfondo con Image.new() e incolla le immagini con Image.paste().
Esistono diversi modi per concatenare immagini di dimensioni diverse.
In questo articolo vengono descritti i casi seguenti.
- Concatena immagini con la stessa altezza o larghezza
- Concatena immagini con diverse altezze o larghezze
- Taglia un’area extra e concatena
- Crea margini e concatena
- Ridimensiona e concatena
- Concatena più immagini contemporaneamente
- Concatena scelta la stessa immagine
Usa le seguenti due immagini come esempio.
from PIL import Image
im1 = Image.open('data/src/lena.jpg')
im2 = Image.open('data/src/rocket.jpg')
Si presume che il codice di esempio sia un’immagine a colori (mode=”RGB”), ma flusso il flusso è lo stesso per le immagini monocromatiche (mode=”L”).
Per ulteriori informazioni sulla concatenazione delle immagini utilizzando OpenCV e scikit-image, vedere gli articoli seguenti. Per immagini della stessa dimensione, scikit-image è facile da usare. Puoi anche aggiungere un bordo tra le immagini.
Concatena immagini con la stessa altezza o larghezza
Crea uno sfondo con Image.new() e incolla le immagini con 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')


Taglia un’area extra e concatena
In Image.paste(), l’area fuori dall’intervallo dell’immagine da incollare viene ignorata (tagliata).
Nel caso dell’allineamento orizzontale, generi uno sfondo con un’altezza inferiore, e nel caso dell’allineamento verticale, generi una larghezza inferiore, l’area in eccesso viene tagliata e concatenata.
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')


Nell’esempio sopra, il bordo superiore o sinistro di ciascuna immagine è allineato. I centri possono anche essere allineati.
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')


Crea margini e concatena
Crea margini e concatena originale per evitare che l’immagine venga tagliata.
Crea prima uno sfondo grande. Puoi creare il parametro di qualsiasi margine colore specificando il parametro color di 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')


Ridimensiona e concatena
Ridimensiona l’immagine in modo che corrisponda alla larghezza o all’altezza e collegale.
Nell’esempio è possibile selezionare se ridimensionare un’immagine grande piccola o ridimensionare un’immagine piccola grande. Fondamentalmente, è meglio ridurre le dimensioni di un’immagine grande a una dimensione inferiore perché la qualità dell’immagine ridotta quando viene ingrandita.
Inoltre, è possibile specificare il filtro per il ricampionamento.
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')


Concatena più immagini contemporaneamente
È possibile ottenere un’immagine concatenata in cui più immagini sono disposte in fila verticalmente e orizzontalmente utilizzando la funzione sopra definita.
Ad esempio, passare un elenco di PIL.Image e concatenarli verticalmente e orizzontalmente.
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')

Nell’esempio sopra, la funzione per creare margini. Se vuoi concatenare con altri modi, usa la funzione corrispondente come appropriato.
Quando si riduceno e si dispone più immagini, è meglio ridimensionare prima tutte le immagini alla larghezza o all’altezza finali per evitare il ridimensionamento adeguato e il deterioramento della qualità dell’immagine.
Qui, crea prima uno sfondo grande con 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')


Anche la funzione per disporre in una piastrella è facile. Passa un elenco 2D di PIL.Image e disponi in riquadri verticalmente e orizzontalmente.
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')

Le comprensioni degli elenchi vengono utilizzate per creare un elenco di immagini ridimensionato e per calcolare la larghezza e l’altezza minima, la larghezza e l’altezza totale.
Concatena scelta la stessa immagine
Se si desidera combinare e utilizzare la stessa immagine verticalmente, è problematico specificarlo nell’elenco 2D, quindi è conveniente preparare una funzione per specificare il numero di ripetizioni.
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')

