0

I'm trying to place an image on top of another image using opencv.Both images have transparent background. Here's the code I'm trying

s_img = cv2.imread("obama2.png", -1)
l_img = cv2.imread('obama.png',-1)
x_offset = 162
y_offset = 69

y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]

alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s

for c in range(0, 3):
    l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] +
                              alpha_l * l_img[y1:y2, x1:x2, c])
cv2.imwrite('final.png',l_img)

obama.png obama.png

obama2.pngenter image description here

final.pngenter image description here

I'm expecting second obama2.png to be on top of obama.png(something similar to composite function in imagemagick/libvips).

What can I do to achieve the desired image

Saikiran
  • 756
  • 2
  • 11
  • 29

2 Answers2

1

This is giving me desired solution but would prefer a better one if possible

    s_img = cv2.imread("obama2.png", -1)
    l_img = cv2.imread('obama.png',-1)
    for i in range(0,s_img.shape[0]):
        for j in range(0,s_img.shape[1]):   
            if s_img[i][j][3]!=0:
                l_img[i+y_offset][j+x_offset][0:3] = s_img[i][j][0:3]
                l_img[i+y_offset][j+x_offset][3] = 255

    cv2.imwrite('final2.png',l_img)

Edit: Looks like i missed something basic. I have to consider alpha channel while looping since the background image has transparency as well.

s_img = cv2.imread("obama2.png", -1)
l_img = cv2.imread('obama.png',-1)
x_offset = 162
y_offset = 69

y1, y2 = y_offset, y_offset + s_img.shape[0]
x1, x2 = x_offset, x_offset + s_img.shape[1]

alpha_s = s_img[:, :, 3] / 255.0
alpha_l = 1.0 - alpha_s

for c in range(0, 4):
    l_img[y1:y2, x1:x2, c] = (alpha_s * s_img[:, :, c] +
                              alpha_l * l_img[y1:y2, x1:x2, c])
cv2.imwrite('final.png',l_img)
Saikiran
  • 756
  • 2
  • 11
  • 29
0

Sorry, I do not know OpenCV well. But I think you may have forgotten to subtract half the width of the obama2 image from your computation of where to place it. Offsets are relative to the top left corner of the obama image from the top left corner of the obama2 image. And you probably measured to the center of the face, which is at about x=162 on the obama image.

But if you can use Imagemagick, that process is very simple:

convert obama.png obama2.png -geometry +82-6 -compose over -composite result.png


enter image description here

The -geometry arguments just define the offsets of the obama2 image relative to the top left corner of the obama image. If I measure the center of the face in obama image, I get about x=176. So I have to subtract half the width of obama2, which is x=192/2=96. So the offset would be x=176-96=80. I adjusted that to 82 and set the y=-6 to move it up slightly.

If you need a Python solution, then you can use Wand, which is based upon Imagemagick

fmw42
  • 46,825
  • 10
  • 62
  • 80