当前位置: 首页 > news >正文

OpenCV-Python图像处理:区分前景背景权重的图像融合案例

☞ ░ 前往老猿Python博客 https://blog.csdn.net/LaoYuanPython ░

一、引言

在《https://blog.csdn.net/LaoYuanPython/article/details/109143281 OpenCV-Python图像融合cv2.addWeighted权重加法函数详解》介绍了两幅图像按不同权重的融合,但当两幅图中有一幅的背景色为黑色,希望融合时背景色为黑色的部分不能遮挡另一幅图,而没有黑色背景的则按比重融合时,addWeighted已经不能满足要求。为适应这种场景,我们来实现一个这样融合的函数。

二、思路

假设图像A和B融合,B为黑色背景,为了实现黑色背景的图像背景不遮挡图像A,实现类似透明的效果,采用如下思路:

  1. 将黑色背景图像B对应的图像掩码求出,并得到该图像掩码求反的掩码反码;
  2. 按照B图像的掩码和反码,将图像A分成两部分,分别与B图像的前景和背景范围对应,得到A1(对应B前景)和A2(对应B背景);
  3. 让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

四、应用案例

4.1、两幅图像

大图像seaside.jpg:
在这里插入图片描述
小图像Lotus.JPG:

在这里插入图片描述

4.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')

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

在这里插入图片描述

五、小结

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

更多OpenCV-Python的介绍请参考专栏《OpenCV-Python图形图像处理》相关文章。

关于老猿的付费专栏

老猿的付费专栏《使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,付费专栏《moviepy音视频开发专栏》详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,两个专栏都适合有一定Python基础但无相关知识的小白读者学习。

付费专栏文章目录:《moviepy音视频开发专栏文章目录》、《使用PyQt开发图形界面Python应用专栏目录》。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《专栏:Python基础教程目录》从零开始学习Python。

如果有兴趣也愿意支持老猿的读者,欢迎购买付费专栏。

跟老猿学Python、学OpenCV!

☞ ░ 前往老猿Python博文目录 ░

相关文章:

  • 2020年总结:平安辞旧岁,老牛自奋蹄!
  • OpenCV-Python图像处理:插值方法及使用resize函数进行图像缩放
  • Python3装饰器的隐秘角落
  • 一种利用Python库解决视频课程检测窗口是否活动的简单方法
  • 人工智能数学基础6:极限、极限运算、ε-δ语言、ε-N语言、级数和函数连续性
  • 人工智能数学基础专栏目录
  • 人工智能数学基础8:两个重要极限及夹逼定理
  • 人工智能数学基础9:集合相关概念
  • 人工智能数学基础10:域、函数及相关概念
  • 人工智能数学基础-线性代数1:向量及向量加减法与数乘
  • 人工智能数学基础-线性代数2:向量的点积、內积、数量积和外积
  • 人工智能数学基础-线性代数3:线性空间、线性相关及基
  • 请大家支持老猿参加2020年博客之星年度评选,谢谢!
  • 人工智能数学基础-线性代数4:矩阵及矩阵运算
  • 人工智能数学基础-线性代数5:行列式求解线性方程组和拉普拉斯定理
  • 实现windows 窗体的自己画,网上摘抄的,学习了
  • [case10]使用RSQL实现端到端的动态查询
  • 【Leetcode】104. 二叉树的最大深度
  • C++类的相互关联
  • gulp 教程
  • HTML-表单
  • JavaScript DOM 10 - 滚动
  • JavaScript 基本功--面试宝典
  • JavaScript-Array类型
  • log4j2输出到kafka
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • Ruby 2.x 源代码分析:扩展 概述
  • Sass 快速入门教程
  • VirtualBox 安装过程中出现 Running VMs found 错误的解决过程
  • 案例分享〡三拾众筹持续交付开发流程支撑创新业务
  • 大型网站性能监测、分析与优化常见问题QA
  • 关于Java中分层中遇到的一些问题
  • 精彩代码 vue.js
  • 腾讯优测优分享 | Android碎片化问题小结——关于闪光灯的那些事儿
  • 项目管理碎碎念系列之一:干系人管理
  • Hibernate主键生成策略及选择
  • Java总结 - String - 这篇请使劲喷我
  • 曾刷新两项世界纪录,腾讯优图人脸检测算法 DSFD 正式开源 ...
  • ​Spring Boot 分片上传文件
  • ​ssh-keyscan命令--Linux命令应用大词典729个命令解读
  • #100天计划# 2013年9月29日
  • #QT项目实战(天气预报)
  • #鸿蒙生态创新中心#揭幕仪式在深圳湾科技生态园举行
  • #免费 苹果M系芯片Macbook电脑MacOS使用Bash脚本写入(读写)NTFS硬盘教程
  • #微信小程序:微信小程序常见的配置传旨
  • (06)金属布线——为半导体注入生命的连接
  • (2020)Java后端开发----(面试题和笔试题)
  • (AngularJS)Angular 控制器之间通信初探
  • (Bean工厂的后处理器入门)学习Spring的第七天
  • (html转换)StringEscapeUtils类的转义与反转义方法
  • (JS基础)String 类型
  • (分享)一个图片添加水印的小demo的页面,可自定义样式
  • (紀錄)[ASP.NET MVC][jQuery]-2 純手工打造屬於自己的 jQuery GridView (含完整程式碼下載)...
  • (三维重建学习)已有位姿放入colmap和3D Gaussian Splatting训练