pythonopencvimage-processingtransparencyalphablending

How overlay a image to specific part on another image in opencv


I have below image and I want to overlay a black patch on the right most side of the image. So I am resizing the both the images to specific size in below code and get only the non white part of overlay and paste it over the specific x,y coordinates but not getting the expected results. I looked into cv2.addWeighted but I dont find any option to specify the option use coordinates of where to paste the overlay. Can someone guide on how to achieve it in cv2?

vr_overlay = "/Users/templates/vertical_overlay.png"

show_image = "/Users/templates/image_3.png"

vr_overlay_co = (0, 0, 100, 412)
img_size = (0, 0, 440, 412)

img = cv2.imread(show_image)
img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)

v_overlay = cv2.imread(vr_overlay)

resize_v_overlay = cv2.resize(v_overlay, (vr_overlay_co[2], vr_overlay_co[3]))

plt.imshow(resize_v_overlay ,cmap='gray')
plt.axis('off')
plt.show()

resize_img = cv2.resize(img_rgb, (img_size[2], img_size[3]))

plt.imshow(resize_img ,cmap='gray')
plt.axis('off')
plt.show()
resize_img[vr_overlay_co[1]: vr_overlay_co[1] + 
           vr_overlay_co[3],vr_overlay_co[0]: vr_overlay_co[0] + 
           vr_overlay_co[2]] = np.where(resize_v_overlay != [0, 0, 0],
                                        resize_img[vr_overlay_co[1]: vr_overlay_co[1] 
                                                   + vr_overlay_co[3], vr_overlay_co[0]: 
                                                   vr_overlay_co[0] + vr_overlay_co[2],], resize_v_overlay)



plt.imshow(resize_img ,cmap='gray')
plt.axis('off')
plt.show()

enter image description here

enter image description here

Expected result:

enter image description here


Solution

  • Here is one way to do that in Python/OpenCV.

    (I note that the images you posted are not sizes you say, especially the gradient. So extra processing is needed to match the sizes of the images. Also the gradient image has a white border that I doubt you want.)

    Input:

    enter image description here

    Gradient (with white borders):

    enter image description here

    import cv2
    import numpy as np
    
    # read the image
    img = cv2.imread('people.png')
    hh, ww = img.shape[:2]
    
    # read the small gradient
    grad = cv2.imread('small_gradient.png')
    hg, wg = grad.shape[:2]
    
    # create white image the size of the image
    # then insert gradient on right side while trimming off excess white from right side of gradient
    ox = ww-wg+1
    grad2 = np.full_like(img, (255,255,255))
    grad2[0:hh, ox:ww-9+1] = grad[0:hg-1, 0:wg-9]
    
    # blend the img with grad2 via multiply
    #result = img.astype(np.float32) * grad2.astype(np.float32) / 255
    #result = result.clip(0,255).astype(np.uint8)
    #or
    scale = 1/255
    result = cv2.multiply(img, grad2, scale=scale)
    
    # save results
    cv2.imwrite('people_gradient.png', result)
    
    # show results
    cv2.imshow('result', result)
    cv2.waitKey(0)
    

    enter image description here