用opencv实现两张半透明png图片以一定透明度叠加

例如我有如下两张透明、半透明图:

在photoshop中打开如下:

用opencv实现两张半透明png图片以一定透明度叠加_第1张图片用opencv实现两张半透明png图片以一定透明度叠加_第2张图片

前景:一张四通道的png图,BGR通道的值全为[0,0,200],透明度完全靠alpha通道的不同值来体现。

后景:一张四通道的png图,BGR通道的值全为[200,0,0] ,透明度完全靠alpha通道的不同值来体现。 

在画图软件中打开分别如下:左侧为前景,右侧为后景

用opencv实现两张半透明png图片以一定透明度叠加_第3张图片

现在想要把红色的画笔以百分之80的透明度叠加到蓝色的画笔上面。

基本的原理来自于alpha compositing 维基百科:

用opencv实现两张半透明png图片以一定透明度叠加_第4张图片

公式中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中打开:

用opencv实现两张半透明png图片以一定透明度叠加_第5张图片

在普通图片浏览器中打开:

用opencv实现两张半透明png图片以一定透明度叠加_第6张图片

你可能感兴趣的:(图像处理,python,opencv,python,opencv,alpha通道,图片处理)