Skip to content Skip to sidebar Skip to footer

Concatenate Multiple Pieces Of An Image To A Single Image Using Python

I have 15 images (from 1 to 15). I would like to stitch these images together so that it forms one single image. What I tried so far? import numpy as np import PIL from PIL import

Solution 1:

These are stitched together horizontally because you have stuck them together with np.hstack() when you actually want to hstack only three at a time into rows and then vstack them together vertically. Replacing that one line with the below should do what you need.

img_rows = []
for min_id inrange(0, 15, 3):
    img_row = np.hstack( (np.asarray( i.resize(min_shape) ) for i in imgs[min_id: min_id+3] ) )
    img_rows.append(img_row)
imgs_comb = np.vstack( ( i for i in img_rows ) )

Solution 2:

Since you've mentioned they are all the same size you can create a new image:

c, h, w = image.shapenew_image= np.zeros((5 * h, 3 * w))

Now we have an empty image in the correct size.

The next step is copying the images into the big image (forgive me cause i didnt test this bit of code but with minor changes / fixes it should work, the important part is the idea)

row=-1for i, img in enumerate(list_of_images):
    if i %3:
        col =0row+=1
    
    new_image[:, row* h: (row+1) * h, col * w: (col +1) * w] = img
    col +=1

essentially you are tiling the images into the big image and the result should be as you hoped for.

Solution 3:

I tried the same approach as Dr. Prof. Patrick and made more universal function. Number of images can be less than rows * cols in this version.

#!/usr/bin/env python3import numpy as np
from imageio import imread, imwrite
from pathlib import Path
import math

deftile_images(images, cols=None, bg_val=None, tile_size=None):
    """Tile images to grid with given number of columns.
    
    Args:
        images (list of np.arrays)
        cols (int): 1 = vertical, None = horizontal stitch
        bg_val (int or tuple): color of empty background
    
    Returns:
        np.array: stitched image
    """
    im1 = np.atleast_3d(images[0])  # add 3rd dim to grey image
    h, w, ch = im1.shape
    if tile_size isnotNone:
        h, w = tile_size
    
    ifnot cols:
        cols = len(images) 
    
    rows = math.ceil(len(images) / cols)
    
    # make empty array 
    new = np.zeros((h * rows, w * cols, ch), dtype=im1.dtype)

    # change bg coloriflen(images) < rows * cols and bg_val isnotNone:
        new = np.add(new, bg_val)  
    
    # paste images into array    
    c, r = 0, 0for i, im inenumerate(images):
        x, y = r * h, c * w
        new[x : x + im.shape[0], y : y + im.shape[1]] = np.atleast_3d(im)
        c += 1ifnot (i+1) % cols:
            r += 1# next row
            c = 0return new        

defmain():
    paths = sorted(f for f in Path().glob("*.*") if f.suffix in (".jpg", ".png") and f.stem != "new")
    images = [imread(f) for f in paths] 
    new = tile_images(images, cols=3, bg_val=(127,150,127))
    imwrite("new.png", new)


if __name__ == "__main__":
    main()

EDIT: I have removed the need to check if image has 2 or 3 dim with np.atleast_3d function. Parameter tile_size allows to set grid size manually, if omitted, first image will be used.

In this version input images need not to be of the same size. Images can overlay, but they must not overflow.

Post a Comment for "Concatenate Multiple Pieces Of An Image To A Single Image Using Python"