Combine Several Images Horizontally with Python

Combine several images horizontally with Python

You can do something like this:

import sys
from PIL import Image

images = [Image.open(x) for x in ['Test1.jpg', 'Test2.jpg', 'Test3.jpg']]
widths, heights = zip(*(i.size for i in images))

total_width = sum(widths)
max_height = max(heights)

new_im = Image.new('RGB', (total_width, max_height))

x_offset = 0
for im in images:
new_im.paste(im, (x_offset,0))
x_offset += im.size[0]

new_im.save('test.jpg')

Test1.jpg

Test1.jpg

Test2.jpg

Test2.jpg

Test3.jpg

Test3.jpg

test.jpg

Sample Image


The nested for for i in xrange(0,444,95): is pasting each image 5 times, staggered 95 pixels apart. Each outer loop iteration pasting over the previous.

for elem in list_im:
for i in xrange(0,444,95):
im=Image.open(elem)
new_im.paste(im, (i,0))
new_im.save('new_' + elem + '.jpg')

Sample Image
Sample Image
Sample Image

Is there any way to merge multiple image into one single image in Python?

I prefer working with OpenCV&Numpy combo. That means working with arrays.
The code below simply take first image as starting point - Height. Any image you will append with it will be horizontaly stacked based on height. That means, appended image will be resized by the montage Height and then horizontally stacked to montage.

Working Code

import cv2
import numpy as np

image1 = cv2.imread("img1.jpg")[:,:,:3]
image2 = cv2.imread("img2.jpg")[:,:,:3]

class Montage(object):
def __init__(self,initial_image):
self.montage = initial_image
self.x,self.y = self.montage.shape[:2]

def append(self,image):
image = image[:,:,:3]
x,y = image.shape[0:2]
new_image = cv2.resize(image,(int(y*float(self.x)/x),self.x))
self.montage = np.hstack((self.montage,new_image))
def show(self):
cv2.imshow('montage',self.montage)
cv2.waitKey()
cv2.destroyAllWindows()

Firstly, you initialize class with first image which will define HEIGHT. So if you want different height, pass into the class resized image. After that you can append horizontaly the image

Usage

>>> m = Montage(image1)
>>> m.append(image2)
>>> m.show()

Result in your case:
Sample Image


But generally it can work with totaly different sizes

Image 1

Sample Image

Image 2

Sample Image

Montage

Sample Image

How to merge/append/stack/paste all images in folder vertically to a new image

images are numpy arrays. As long as they have the same dimensions, you can np.hstack them.

imlist =[cv2.imread(filename) for filename in allfiles if filename[-4:] in [".png", ".PNG"]]
concat_img = np.hstack(imlist)

cv2.imshow('Horizontal Appended', concat_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Explanation:

  • read in all images into a list with list comprehension: list of images/np.arrays
  • use np.hstack() to concatenate all images along the horizontal dimension. You could use more general concatenation tools with np.concatenate() or np.stack() if you run into issues.

Concatenate multiple pieces of an image to a single image using python

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 in range(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 ) )

Merge images by list python

I solved the problem!

list_= ['home/1.png','home/2.png', ...,'home/100.png']

from PIL import Image

images = [Image.open(x) for x in list_]
widths, heights = zip(*(i.size for i in images))

total_width = sum(widths)
max_height = max(heights)

new_im = Image.new('RGB', (total_width, max_height))

x_offset = 0
for im in images:
new_im.paste(im, (x_offset,0))
x_offset += im.size[0]

new_im.save('/test.png')

Combining multiple images, in many folders in Python

This should do what you want to all groups of files in the current directory. I'll leave you to add error handling and other little variations:

#!/usr/bin/env python3

import cv2
from glob import glob

# Get list of files matching "*A.ome.tif"
files = glob("*A.ome.tif")

# Get list of unique stems
stems = [f.replace('A.ome.tif', '') for f in files]

# Iterate over unique stems
for stem in stems:
A = cv2.imread(stem + 'A.ome.tif')
B = cv2.imread(stem + 'B.ome.tif')
C = cv2.imread(stem + 'C.ome.tif')
# Stack images horizontally (side-by-side), use np.dstack() for merging channels
result = np.hstack((A,B,C))
cv2.imwrite(stem + 'result.tif', result)

Combining two images horizontally in python using OpenCV

If you want to write a JPEG, you need:

cv2.imwrite('lovely.jpg', image)

where image is all your images concatenated together.

How to concatenate 1000 images vertically using for loop in python?

Instead of skimage.io (which may be due to a version or CPU issue), consider using matplotlib.pyplot.imread with list comprehension or map. Below demonstrates with OP's two images.

import numpy as np
import matplotlib.pyplot as plt

img_paths = ["OP_Image_1.png", "OP_Image_2.png"]

data = [plt.imread(img) for img in img_paths]
# data = list(map(mpimg.imread, img_paths))

res = np.concatenate(data)
plt.imshow(res, cmap='inferno', aspect='auto', interpolation='nearest')

plt.axis('off')
plt.show()

Plot Output


Specifically, for OP's iteration of files:

import os
import numpy as np
import matplotlib.pyplot as plt

...
spec_path = r"E:\wavelet\spectrograms\paz05" # RAW STRING FOR BACKSLASHES
spec_file = f"spec_{isPreictal}_{str(nSpectogram+1)}_{{}}.png" # F STRING FOR INTERPOLATION

if nSpectogram <3765:
data = [plt.imread(os.path.join(spec_path, spec_file.format(k+1))) for k in range(21)]

res = np.concatenate(data)
plt.imshow(res, cmap='inferno', aspect='auto', interpolation='nearest')

plt.axis('off')
plt.savefig(os.path.join(spec_path, "Output.png"))


Related Topics



Leave a reply



Submit