例如我有如下两张透明、半透明图:
在photoshop中打开如下:
前景:一张四通道的png图,BGR通道的值全为[0,0,200],透明度完全靠alpha通道的不同值来体现。
后景:一张四通道的png图,BGR通道的值全为[200,0,0] ,透明度完全靠alpha通道的不同值来体现。
在画图软件中打开分别如下:左侧为前景,右侧为后景
现在想要把红色的画笔以百分之80的透明度叠加到蓝色的画笔上面。
基本的原理来自于alpha compositing 维基百科:
公式中src代表的就是前景,dst代表后景。RGB为RGB通道,A为Alpha通道。
那么要把前景以某百分比叠加到后景的话,无非就是先对前景的alpha通道做一个更透明化的处理(乘以透明度比例),再叠加到后景上。 代码如下:
def img_float32(img):
return img.copy() if img.dtype != 'uint8' else (img/255.).astype('float32')
def over(fgimg, bgimg):
fgimg, bgimg = img_float32(fgimg),img_float32(bgimg)
(fb,fg,fr,fa),(bb,bg,br,ba) = cv2.split(fgimg),cv2.split(bgimg)
color_fg, color_bg = cv2.merge((fb,fg,fr)), cv2.merge((bb,bg,br))
alpha_fg, alpha_bg = np.expand_dims(fa, axis=-1), np.expand_dims(ba, axis=-1)
color_fg[fa==0]=[0,0,0]
color_bg[ba==0]=[0,0,0]
a = fa + ba * (1-fa)
a[a==0]=np.NaN
color_over = (color_fg * alpha_fg + color_bg * alpha_bg * (1-alpha_fg)) / np.expand_dims(a, axis=-1)
color_over = np.clip(color_over,0,1)
color_over[a==0] = [0,0,0]
result_float32 = np.append(color_over, np.expand_dims(a, axis=-1), axis = -1)
return (result_float32*255).astype('uint8')
def overlay_with_transparency(bgimg, fgimg, xmin = 0, ymin = 0,trans_percent = 1):
'''
bgimg: a 4 channel image, use as background
fgimg: a 4 channel image, use as foreground
xmin, ymin: a corrdinate in bgimg. from where the fgimg will be put
trans_percent: transparency of fgimg. [0.0,1.0]
'''
#we assume all the input image has 4 channels
assert(bgimg.shape[-1] == 4 and fgimg.shape[-1] == 4)
fgimg = fgimg.copy()
roi = bgimg[ymin:ymin+fgimg.shape[0], xmin:xmin+fgimg.shape[1]].copy()
b,g,r,a = cv2.split(fgimg)
fgimg = cv2.merge((b,g,r,(a*trans_percent).astype(fgimg.dtype)))
roi_over = over(fgimg,roi)
result = bgimg.copy()
result[ymin:ymin+fgimg.shape[0], xmin:xmin+fgimg.shape[1]] = roi_over
return result
结果:
在photoshop中打开:
在普通图片浏览器中打开: