Skip to content
Advertisement

OpenCV Composting 2 images of differing size

I need to alpha-blend 2 images that are not the same size. I’ve managed to get them to composite by resizing to the same size, so I’ve got part of the logic:

import cv2 as cv

def combine_two_color_images_composited(foreground_image, background_image):

    foreground = cv.resize(foreground_image, (400,400), interpolation=cv.INTER_CUBIC).copy()
    background = cv.resize(background_image, (400,400), interpolation=cv.INTER_CUBIC).copy()
    alpha =0.5
    # do composite of foreground onto the background
    cv.addWeighted(foreground, alpha, background, 1 - alpha, 0, background)
    
    cv.imshow('composited image', background)
    cv.waitKey(10000)

I’m wondering if I need to make a mask that is the same size as the larger image and then use that with my first image. If so, I don’t know how to do masking yet in OpenCV…. this is but a tiny portion of my project so it’s not something I’ve been able to spend a ton of time researching to learn how masking works.

I have searched all over but the code I’m finding does things like ‘adds’ the images together (side by side).

Advertisement

Answer

To combine the two images you can make use of numpy slicing to select the portion of the background image where you want to blend the foreground, then insert the newly blended portion in your background again.

import cv

def combine_two_color_images(image1, image2):

    foreground, background = image1.copy(), image2.copy()
    
    foreground_height = foreground.shape[0]
    foreground_width = foreground.shape[1]
    alpha =0.5
    
    # do composite on the upper-left corner of the background image.
    blended_portion = cv.addWeighted(foreground,
                alpha,
                background[:foreground_height,:foreground_width,:],
                1 - alpha,
                0,
                background)
    background[:foreground_height,:foreground_width,:] = blended_portion
    cv.imshow('composited image', background)

    cv.waitKey(10000)

edit: To place the foreground at a specified location you use numpy indexing as before. Numpy indexing is very powerful and you will find it useful on many occasions. I linked the documentation above. Is really worth to take a look at.

def combine_two_color_images_with_anchor(image1, image2, anchor_y, anchor_x):
    foreground, background = image1.copy(), image2.copy()
    # Check if the foreground is inbound with the new coordinates and raise an error if out of bounds
    background_height = background.shape[0]
    background_width = background.shape[1]
    foreground_height = foreground.shape[0]
    foreground_width = foreground.shape[1]
    if foreground_height+anchor_y > background_height or foreground_width+anchor_x > background_width:
        raise ValueError("The foreground image exceeds the background boundaries at this location")
    
    alpha =0.5

    # do composite at specified location
    start_y = anchor_y
    start_x = anchor_x
    end_y = anchor_y+foreground_height
    end_x = anchor_x+foreground_width
    blended_portion = cv.addWeighted(foreground,
                alpha,
                background[start_y:end_y, start_x:end_x,:],
                1 - alpha,
                0,
                background)
    background[start_y:end_y, start_x:end_x,:] = blended_portion
    cv.imshow('composited image', background)

    cv.waitKey(10000)
Advertisement