带alpha通道的图像合成(Python语言)

     我先放代码和结果,再分析过程。

1.实现代码

# coding=utf-8
import numpy as np
import cv2 as cv 

def paste_ROI_to_image(image_in, ROI, paste_area):
    image = image_in.copy()
    y1, x1, y2, x2 = paste_area

    ROI = cv.resize(ROI, (x2 - x1 + 1, y2 - y1 +1))   #cv.resize(src, dsize=(width, height))
    
    image = image.astype(np.float)
    ROI = ROI.astype(np.float)
    
    # alpha通道
    alpha_image = image[y1:y2+1, x1:x2+1, 3]/255.0 
    alpha_ROI = ROI[:,:,3]/255.0
    alpha = 1 - (1 - alpha_image)*(1 - alpha_ROI)
    # BGR通道
    for i in range(3):
        image[y1:y2+1, x1:x2+1, i] = (image[y1:y2+1, x1:x2+1, i]*alpha_image*(1 - alpha_ROI) + ROI[:,:,i]*alpha_ROI) / alpha 
    
    image[y1:y2+1, x1:x2+1, 3] = alpha*255
    image = image.astype(np.uint8)

    return image


image = cv.imread('image.jpg', cv.IMREAD_UNCHANGED)  #

ROI = cv.imread('ROI.png', cv.IMREAD_UNCHANGED)

image_R = paste_ROI_to_image(image, ROI, [50, 0, 206, 117])

cv.imwrite('image_R.png', image_R)

   结果:

          

          image                             ROI                    image_R

   代码分析:

   (1)先导入使用到的两个模块:numpy和Python-OpenCV(cv2)

   (2)定义了一个函数paste_ROI_to_image来完成透明素材的粘贴。函数中,先使用cv.resize函数来调整素材ROI的尺寸,使其和粘贴区域的尺寸是匹配的。x表示图像的列数,y表示图像中的行数。

   (3)粘贴透明素材。(原理在后面解释)

   (4)显示粘贴结果。

2.粘贴透明素材的原理

    首先,透明素材ROI具有透明度是因为它除了有RGB三个颜色通道以外,还有一个alpha通道。包含alpha通道的图像一般存储为png格式。(jpg格式图像是没有alpha通道的,比如程序中的image.jpg图就只有RGB三个颜色通道)我们粘贴透明图像时就利用到了这个透明通道。

    使粘贴的效果能够保持透明的效果,其实就是让image和ROI的RGB三个通道进行混合

    那么,怎么混合呢?混合的比例如何知道呢?

     alpha通道的值不就给我们一个值吗?alpha通道的值取值范围是0-255。0表示完全透明,255表示完全不透明。

  (1)alpha通道: 

      setp1: 将alpha通道值取值范围由0-255转换到0-1

             alpha_image = image[y1:y2+1, x1:x2+1, 3]/255.0

             alpha1_ROI = ROI[:,:,3]/255.0

      setp2:  计算合成后的图像的透明度:

             alpha = 1 - (1 - alpha_image)*(1 - alpha_ROI)

             这个公式可以这么理解,剩余透明度(1 - alpha_image) 和(1 - alpha_ROI)混合后,得到的图像透明度。

   (2)RGB通道:

            image[R,G,B] = (image[R,G,B]*alpha_image*(1 - alpha_ROI) + ROI[R,G,B]*alpha_ROI)    / alpha 

            这个公式怎么理解呢?其实就是按照透明度来分配image和ROI的RGB混合比例。

            ROI是上层,其颜色的透出部分为 ROI[R,G,B]*alpha_ROI,然后按照最后合成图像的透明度分配比例,则ROI提供的RGB值为:

                ROI[R,G,B]*alpha_ROI)    / alpha 

           image是底层,其颜色的透出部分为image[R,G,B]*alpha_image,而由于上层的ROI透过了alpha_ROI,留给image的只有(1 - alpha_ROI), 所以image提供的RGB值为:

               image[R,G,B]*alpha_image*(1 - alpha_ROI)  / alpha              

      (3)合并alpha通道和RGB通道

              image[y1:y2+1, x1:x2+1, 3] = alpha*255
              image = image.astype(np.uint8)


可能涉及到的资料

(1)opencv中imread函数的用法。

(2)numpy数据类型转换的注意。

  • 4
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值