Alpha blending two images with OpenCV and/or Numpy

吃可爱长大的小学妹 提交于 2021-01-27 04:01:48

问题


I would like to add a semi-transparent rectangle filled with a solid colour to an already loaded semi-transparent PNG. Here's an example input image I am using:

That image is loaded with a standard cv2.IMREAD_UNCHANGED flag so that alpha channel is perfectly preserved. That input image is stored in the image variable.

Here's my code that I have so far:

# get image dimensions
imgHeight, imgWidth = image.shape[:2]

# create empty overlay layer with 4 channels
overlay = np.zeros((imgHeight, imgWidth, 4), dtype = "uint8")

# draw semi-transparent red rectangle
overlay[200:300, 0:imgWidth] = (0, 0, 255, 200)

# extract alpha channel from overlay
alpha = cv2.split(overlay)[3]

# compute mask
mask = (np.multiply(alpha, 1.0 / 255))[:, :, np.newaxis]

# blend input image and overlay
output = cv2.convertScaleAbs(overlay * mask + image * (1 - mask))

And here's the result that I am getting:

At first glance it looks acceptable. We have our input image with a semi-transparent rectangle in the middle. However, upon closer inspection, we can observe strange behaviour when mixing alpha channels (marked with arrows):

It seems that alpha is not blended at all which results in original image pixels being only fully opaque or fully transparent.

Perhaps my method of blending transparent PNG with semi-transparent shapes is far from ideal. As a side note, I did try the cv2.addWeighted method but that yielded even worse results.

I would like the solution to be limited to OpenCV and/or Numpy. Any help would be greatly appreciated.


回答1:


As unlut pointed out this is indeed a duplicate. Just in case someone stumbles on it, Mark Setchell's answer works pretty well:

# get image dimensions
imgHeight, imgWidth = image.shape[:2]

# create empty overlay layer with 4 channels
overlay = np.zeros((imgHeight, imgWidth, 4), dtype = "uint8")

# draw semi-transparent red rectangle
overlay[200:300, 0:imgWidth] = (0, 0, 255, 200)

# Extract the RGB channels
srcRGB = image[...,:3]
dstRGB = overlay[...,:3]

# Extract the alpha channels and normalise to range 0..1
srcA = image[...,3]/255.0
dstA = overlay[...,3]/255.0

# Work out resultant alpha channel
outA = srcA + dstA*(1-srcA)

# Work out resultant RGB
outRGB = (srcRGB*srcA[...,np.newaxis] + dstRGB*dstA[...,np.newaxis]*(1-srcA[...,np.newaxis])) / outA[...,np.newaxis]

# Merge RGB and alpha (scaled back up to 0..255) back into single image
outRGBA = np.dstack((outRGB,outA*255)).astype(np.uint8)

plt.imshow(outRGBA)


来源:https://stackoverflow.com/questions/64874129/alpha-blending-two-images-with-opencv-and-or-numpy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!