How to concatenate images of different shapes using python and opencv?
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)
Related videos on Youtube
![ajayramesh](https://i.stack.imgur.com/MXiyg.jpg?s=256&g=1)
ajayramesh
Updated on May 25, 2022Comments
-
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)