I have a bunch of jpeg
images that I want to join in a specific position following its filename. Examples of filenames are:
7_1.jpeg
--> This image should be pasted in the 7th row, 1st column
15_5.jpeg
--> This image should be pasted in the 15th row, 5th column
etc
In this case, the filenames range from 1_1.jpeg
to 40_20.jpeg
but I would like to join any number of images.
The final image would have empty cells because not all positions have an image.
The closest post for my purposes that I found is this one: https://stackoverflow.com/a/42853439/8252488
UPDATE: I tried different option and now I can paste different images in specific positions using:
import cv2
import numpy
import glob
import os
dir = "." # current directory
ext = ".jpg" # whatever extension you want
pathname = os.path.join(dir, "*" + ext)
images = [cv2.imread(img) for img in glob.glob(pathname)]
height = sum(image.shape[0] for image in images)
width = max(image.shape[1] for image in images)
output = numpy.zeros((height,width,3))
y = 0
for image in images:
h,w,d = image.shape
output[y:y+h,0:w] = image
y += h
cv2.imwrite("test.jpg", output)
from here
Now I am trying to specify the positions using filenames, as follows:
pathname = os.path.join(dir, "*" + ext)
images = [cv2.imread(img) for img in glob.glob(pathname)]
names = [img for img in glob.glob(pathname)]
#Get filenames from paths
files = [re.sub("/.*/", "", x) for x in names]
#Get positions
position = [re.sub(".jpeg", "", x) for x in files]
#Get hight position and tranform to int
height = [re.sub("_.*", "", x) for x in position]
height2 = [int(i) for i in height]
#Get width position and tranform to int
width = [re.sub(".*_", "", x) for x in position]
width2 = [int(i) for i in width]
#Generate background image
height_tot = 280*max(height2) #All images are 280*280
width_tot = 280*max(width2)
output = numpy.zeros((height_tot,width_tot,3))
#Locate images
for name, image in zip(names,images):
files = re.sub("/.*/", "", name)
position = re.sub(".jpeg", "", files)
height = re.sub("_.*", "", position)
height2 = int(height)*280
width = re.sub(".*_", "", position)
width2 = int(width)*280
output[height2:height2+280,width2:width2+280] = image
cv2.imwrite("test.jpg", output)
I know its very far from clean but at this point I only want the thing working. However, I got the following error:
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-70-529c37a03571> in <module>()
6 width = re.sub(".*_", "", position)
7 width2 = int(width)*280
----> 8 output[height2:height2+280,width2:width2+280] = image
9 # print(height2)
10 cv2.imwrite("test.jpg", output)
ValueError: could not broadcast input array from shape (280,280,3) into shape (0,280,3)
Any idea what is missing? Thanks!
UPDATE2 If I change the 280 to 262 then I do not have the error but the image is not well arranged. Actually I found that the patches are actually pasted more than one time. The code:
for name, image in zip(names,images):
h,w,d = image.shape
files = re.sub("/.*/", "", name)
position = re.sub(".jpeg", "", files)
height = re.sub("_.*", "", position)
height2 = int(height)*262
width = re.sub(".*_", "", position)
width2 = int(width)*262
output[height2:height2+h,width2:width2+w,:] = image
cv2.imwrite("test.jpg", output)