Titan
Titan

Reputation: 224

How to put images on another image in order?

In below example there are three images on a white background in order. How to achieve this in python using CV2 or PIL or any working code.

Thank you.

enter image description here

Image must be aligned according to aspect ratio.

Input = 3 images with BG,

Output = single image as shown in above picture

UPDATE !!!!

Each and every loop only one image gets pasted on BG.

from PIL import Image
import cv2
import numpy as np

d=0
folder = 'save'
image_paths = []
for path, subdirs, files in os.walk(folder):
    for filename in files:
        f = os.path.join(path, filename)
        if f.endswith(".jpg"):
            image_paths.append(f)
        if f.endswith(".png"):
            image_paths.append(f)
        if f.endswith(".JPG"):
            image_paths.append(f)
        if f.endswith(".PNG"):
            image_paths.append(f)  
        if f.endswith(".jpeg"):
            image_paths.append(f)    
        if f.endswith(".JPEG"):
            image_paths.append(f)
          

for image in image_paths:
    image = cv2.imread(image)
    r = 720.0 / image.shape[1]
    dim = (720, int(image.shape[0] * r))

    resized = cv2.resize(image, dim)
    #resized = resized[:,:,0]
    h, w, z = resized.shape

    back = cv2.imread('template.jpg')

    yoff = round((1080-h)/4)
    xoff = round((1920-w)/6)

    d+=1
    result = back.copy()
    result[yoff:yoff+h, xoff:xoff+w] = resized
    #result = np.stack((result)*3)
    cv2.imwrite('saves/resized_centered_%d.jpg'%d,  result)

So multiple images in input gets pasted in a background but the thing is, i want three images to paste in the background instead of one image in order.

NOTE: THE IMAGE ON TOP IS JUST TO REPRESENT MY HELP !!! YOU CAN TELL ME WHATEVER POSSIBLE APART FROM THAT !!!

This line of code moves the image towards top-left and seated properly but likewise i need two more image to be seated on top-right and as well as bottom.

yoff = round((1080-h)/4)
xoff = round((1920-w)/6) 

Upvotes: 0

Views: 898

Answers (1)

HansHirse
HansHirse

Reputation: 18925

I assume some template like this:

Template

The "final image" has dimensions (1920, 1080) (cf. your calculations on xoff and yoff). Since you wrote, you want to keep the aspect ratio for each "single image", you'd need to check both cases: Resize w.r.t. to the single image's width, and if the resulting height is too large, re-resize w.r.t. to the single image's height.

What's left is to track the number of single images per final image inside the loop, and set up proper xoff and yoff values for each of the three cases. Maybe, looking at the code here helps more than long explanations:

import cv2
import numpy as np
import os

folder = 'path/to/your/images'
image_paths = []
for path, subdirs, files in os.walk(folder):
    for filename in files:
        f = os.path.join(path, filename)
        if f.endswith((".jpg", ".png", ".JPG", ".PNG", ".jpeg", ".JPEG")):
            image_paths.append(f)

d = 0                                               # Final image counter
e = 0                                               # Single image counter
back = np.ones((1080, 1920, 3), np.uint8) * 255     # Background
result = back.copy()                                # Final image
for i, image in enumerate(image_paths):

    # Read image
    image = cv2.imread(image)
    h, w = image.shape[:2]

    # First two single images: Enforce subimage with h_max = 480 and w_max = 900
    if e <= 1:
        r = 900.0 / w
        dim = (900, int(h * r))
        if dim[1] > 480:
            r = 480.0 / h
            dim = (int(w * r), 480)
        resized = cv2.resize(image, dim)
        hr, wr = resized.shape[:2]
        x_off = 40
        if e == 0:
            y_off = 40
        else:
            y_off = 560

    # Third single image: Enforce subimage with h_max = 1000 and w_max = 900
    else:
        r = 900.0 / w
        dim = (900, int(h * r))
        if dim[1] > 1000:
            r = 1000.0 / h
            dim = (int(w * r), 1000)
        resized = cv2.resize(image, dim)
        hr, wr = resized.shape[:2]
        x_off, y_off = 980, 40

    # Add single image to final image
    result[y_off:y_off + hr, x_off:x_off + wr] = resized

    # Increment single image counter
    e += 1

    # After three single images: Write final image; start new final image
    if (e == 3) or (i == (len(image_paths) - 1)):
        cv2.imwrite('resized_centered_%d.jpg' % d, result)
        result = back.copy()
        d += 1
        e = 0

For some random images from my StackOverflow archive, I get the following outputs:

Example #1

Example #2

Example #3

If you want to have different sized boxes or margins around or between the single images, just adapt the corresponding values in the code.

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.9.1
PyCharm:       2021.1.1
NumPy:         1.20.2
OpenCV:        4.5.1
----------------------------------------

Upvotes: 2

Related Questions