How to concatenate images of different shapes using python and opencv?

11,790

Solution 1

Getting the results that you show in the screenshot might require some more tinkering, but simply stacking the images on top of eachother can be acomplished like this:

import cv2
import numpy as np

image_names = ['original_field_1_0.PNG','original_field_1_1.PNG','original_field_1_3.PNG','original_field_1_4.PNG','original_field_1_5.PNG']
images = []
max_width = 0 # find the max width of all the images
total_height = 0 # the total height of the images (vertical stacking)

for name in image_names:
    # open all images and find their sizes
    images.append(cv2.imread(name))
    if images[-1].shape[1] > max_width:
        max_width = images[-1].shape[1]
    total_height += images[-1].shape[0]

# create a new array with a size large enough to contain all the images
final_image = np.zeros((total_height,max_width,3),dtype=np.uint8)

current_y = 0 # keep track of where your current image was last placed in the y coordinate
for image in images:
    # add an image to the final array and increment the y coordinate
    final_image[current_y:image.shape[0]+current_y,:image.shape[1],:] = image
    current_y += image.shape[0]

cv2.imwrite('fin.PNG',final_image)

The basic idea is to find the total size of the images first, then create an array of that size and finally set the pixels in those ranges to that of each individual image while iterating downwards (or sideways, depending on what you want).

You can also implement threshold values for when you want to start another row or column.

Solution 2

This modification of @ajayramesh's solution worked for me. This function takes in a list of images and outputs a single image where all input images are stacked vertically:

def get_one_image(img_list):
    max_width = 0
    total_height = 200  # padding
    for img in img_list:
        if img.shape[1] > max_width:
            max_width = img.shape[1]
        total_height += img.shape[0]

    # create a new array with a size large enough to contain all the images
    final_image = np.zeros((total_height, max_width, 3), dtype=np.uint8)

    current_y = 0  # keep track of where your current image was last placed in the y coordinate
    for image in img_list:
        # add an image to the final array and increment the y coordinate
        image = np.hstack((image, np.zeros((image.shape[0], max_width - image.shape[1], 3))))
        final_image[current_y:current_y + image.shape[0], :, :] = image
        current_y += image.shape[0]
    return final_image

Solution 3

I modified code to make it a simple function, may be useful for others.

def get_one_image(images):
        img_list = []
        padding = 200
        for img in images:
            img_list.append(cv2.imread(img))
        max_width = []
        max_height = 0
        for img in img_list:
            max_width.append(img.shape[0])
            max_height += img.shape[1]
        w = np.max(max_width)
        h = max_height + padding

        # create a new array with a size large enough to contain all the images
        final_image = np.zeros((h, w, 3), dtype=np.uint8)

        current_y = 0  # keep track of where your current image was last placed in the y coordinate
        for image in img_list:
            # add an image to the final array and increment the y coordinate
            final_image[current_y:image.shape[0] + current_y, :image.shape[1], :] = image
            current_y += image.shape[0]
        cv2.imwrite('out.png', final_image)
Share:
11,790

Related videos on Youtube

ajayramesh
Author by

ajayramesh

Updated on May 25, 2022

Comments

  • ajayramesh
    ajayramesh about 2 years

    I have some images(say 5) and each having different shapes. I want to concatenate into one single image for my project report. Can you please provide an easy way using opencv and python?

    The resulting image is similar to below.

    In numpy I tried something like this, it works but only for two images.

    r = np.concatenate((images[1][:, :, 1], images[1][:, :, 3]), axis=1)
    

    enter image description here