第十五章:OpenCV-Python图像处理:区分前景背景权重的图像融合案例-灵析社区

金某某的算法生活

一、思路

假设图像A和B融合,B为黑色背景,为了实现黑色背景的图像背景不遮挡图像A,实现类似透明的效果,采用如下思路:将黑色背景图像B对应的图像掩码求出,并得到该图像掩码求反的掩码反码;按照B图像的掩码和反码,将图像A分成两部分,分别与B图像的前景和背景范围对应,得到A1(对应B前景)和A2(对应B背景);

让A1和B前景部分按对应权重融合,将A2部分和B背景部分按另外的权重融合,两融合结果图像相加,即得到最终的结果图像。

二、实现

具体的代码实现遵循上述思路,但编码的细节比较复杂一些,具体参考注释:

def addWeightedDistinguishBLK(img1, alpha, img2, beta, sigma, gamma=0.0):
    """
    图像img1和img2权重相加,但图像img2中像素为黑色的部分取img1的像素权重为sigma
    参数img1, alpha, img2, beta, gamma与addWeighted的参数相同,sigma为img1中对应img2黑色部分范围的权重
    """
    l = len(img2.shape)
    if l == 3:#是彩色图
        row, col, channel = img2.shape
        if channel == 3:
            img2Gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
        else:
            img2Gray = cv2.cvtColor(img2, cv2.COLOR_BGRA2GRAY)
    else:#是灰度图
        img2Gray = img2
    retval, img2Inv = cv2.threshold(img2Gray, 43, 255, cv2.THRESH_BINARY_INV) #将灰度小于43的像素作为黑色,img2Inv为img2黑色部分设为255,非黑色部分设为0的img2图像掩码反码
   
    #为了对img2图像前景进行平滑,对img2图像掩码反码进行开、闭、膨胀运算,
    kernal = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
    img2Inv = cv2.morphologyEx(img2Inv, cv2.MORPH_OPEN, kernal)
    img2Inv = cv2.morphologyEx(img2Inv,cv2.MORPH_CLOSE,kernal)
    img2Inv = cv2.morphologyEx(img2Inv, cv2.MORPH_DILATE, kernal)
    
    retval, img2Mask = cv2.threshold(img2Inv, 0, 255, cv2.THRESH_BINARY_INV) #求img2的掩码
    
    img1Transparent = cv2.bitwise_and(img1, img1, mask=img2Inv) #获得img1中与img2背景范围对应的部分
    img1NotTransparent = cv2.bitwise_and(img1, img1, mask=img2Mask)#获得img1中与img2前景范围对应的部分
    img2NotTransparent = cv2.bitwise_and(img2, img2, mask=img2Mask) #获得img2中前景部分

    imgTmp = cv2.addWeighted(img1NotTransparent, alpha, img2NotTransparent, beta, gamma) #img1中与img2前景范围对应的部分与img2前景部分融合
    dest = cv2.addWeighted(imgTmp, 1, img1Transparent, sigma, gamma) #将融合前景部分与img1对应img2背景部分融合
    return dest

def addWeightedSmallImgToLargeImgDstgshBLK(largeImg,alpha,smallImg,beta,sigma,gamma=0.0,regionTopLeftPos=(0,0)):
    "将小图像与大图像指定位置的内容融合,但对小图像透明部分单独处理,取大图像sigma的权重部分"
    srcW, srcH = largeImg.shape[1::-1]
    refW, refH = smallImg.shape[1::-1]
    x,y =  regionTopLeftPos
    if (refW>srcW) or (refH>srcH):
        #raise ValueError("img2's size must less than or equal to img1")
        raise ValueError(f"img2's size {smallImg.shape[1::-1]} must less than or equal to img1's size {largeImg.shape[1::-1]}")
    else:
        if (x+refW)>srcW:
            x = srcW-refW
        if (y+refH)>srcH:
            y = srcH-refH
        destImg = np.array(largeImg)
        tmpSrcImg = destImg[y:y+refH,x:x+refW]
        tmpImg = addWeightedDistinguishBLK(tmpSrcImg, alpha, smallImg, beta,sigma,gamma)
        destImg[y:y + refH, x:x + refW] = tmpImg
        return destImg

三、应用案例

3.1、两幅图像

大图像seaside.jpg:

小图像Lotus.JPG:

3.2、实现代码

addWeightedSmallImgToLargeImgDstgshBLK在opencvPublic模块中提供:

from opencvPublic import addWeightedSmallImgToLargeImgDstgshBLK,readImgFile
def main(largeImg,smallImg):
    information = "老猿Python博客文章目录:https://blog.csdn.net/LaoYuanPython/article/details/109160152,敬请关注同名微信公众号"

    img1 = readImgFile(largeImg, False) #自定义读入图片文件的函数,具体功能请参考:https://blog.csdn.net/LaoYuanPython/article/details/111351901
    img2 = readImgFile(smallImg, False)
    img = addWeightedSmallImgToLargeImgDstgshBLK(img1,1,img2,0.5,1)
    cv2.imwrite(r'f:\pic\addWeightedBlk.jpg',img)
    cv2.imshow('img',img)
    print(f"\n更多学习资料请参考:\n    {information}")
    cv2.waitKey(0)

main(r'f:\pic\seaside.JPG',r'f:\pic\lotus.JPG')

3.3、输出图像和程序运行信息

四、小结

本文介绍了一种区分前景、背景按不同权重进行图像融合的思路、具体实现及应用案例,这种模式对于需要融合图像中存在黑色背景的图像时能实现将黑色作为透明处理,达到将带黑色背景的前景部分融合到另外的图像,使得融合后的图像更自然。

阅读量:109

点赞量:0

收藏量:0