基于RGB颜色空间使用OpenCV-Python实现照片换底

2023-11-20

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

一、引言

前一阵子家人报考教师资格证考试,因报名需要将蓝底的数字相片换成白底的,老猿虽然在学习图像处理相关开发技术,但并没有熟练使用的图像编辑软件,一般也就是用个windows的画图工具简单处理一下,因此这个事情就只好求助于OpenCV的图像处理技术。不过老猿OpenCV图像处理也就学了最低级的图像处理,其他的还没学完,也就会图像空间变换、腐蚀和膨胀处理、阈值处理、几何变换、四则运算、鼠标键盘事件等。具体请参考《OpenCV-Python图形图像处理》。

二、处理思路

2.1、初步思路

老猿试图用学过的图像处理基础知识能完成数字图像的处理,大致构思如下:

  1. 先将图像分离为R、G、B三通道的三个图像,蓝底应该是R、G分量小B分量较大的部分,分别对这三部分进行阈值处理(R、G分量小于某个值,B分量要求大于某个值),满足这样条件的我们就认为该像素对应区域为背景色区域,阈值处理后可以得到背景的掩膜图像A以及其反转后对应前景色的掩膜图像F
  2. 将原照片自身与自身相乘,相乘时设置其掩膜为掩膜图像F,得到照片前景;
  3. 构造一与照片大小相同的纯白色(新底色)图像,将其自身与自身相乘,相乘时设置其掩膜为掩膜图像A,得到对应的新底色背景;
  4. 将新得到的照片前景和新底色背景相加或相或得到新底色的照片。
2.3、实际处理遇到的问题及应对

实际处理时,发现远比这个复杂,有2个问题:

  • 照片的背景色不是单一的像素值,而是不同位置会有不同,特别是前景色周边的灰度值与其他部分差异较大;
  • 背景色的灰度值与前景色的灰度值不是简单的大于等于或小于等于关系,而是部分前景色小于背景色灰度值,部分前景色灰度值大于背景色灰度值,甚至有部分灰度值前景色和背景色是相同的。

在这个时候就需要根据实际相片底色情况调整RGB三个分量阈值处理的阈值,需要能对未能有效识别为背景区域的背景区域方便获取对应像素值。同时为了解决边界问题,可能需要进行背景色的膨胀处理。

2.4、代码实现

按照以上处理思路和问题应对方式,老猿实现了一个图像鼠标点击获取像素值输出的函数和一个图像背景色替换的函数,代码如下:

import cv2
import numpy as np
from opencvPublic import readImgFile #类似imread的图片文件装载函数,支持识别中文文件名

def OnMouseEvent( event, x, y, flags,img):#图片点击时输出对应位置和像素值
    #鼠标左键按下打印对应位置的图像的像素值
    if event==cv2.EVENT_LBUTTONDOWN:
        print(f'{(x,y)}:{img[y][x]}')

def changePhotoBG(fileName,BGRThresh,MorphOpCount=0):
    photo = readImgFile(fileName)  #读入图像
    BThresh,GThresh,RThresh = BGRThresh
    bgWhite = np.full(photo.shape[:],255,dtype=np.uint8) #构造一个与图像大小完全相同的全白图像

    #分离读入图像的rgb分量,并对每个分量进行阈值处理,确认每个分量的阈值是最关键的一步,与具体图像背景紧密相关,根据背景调整相关阈值
    b,g,r = cv2.split(photo)
    ret, maskb = cv2.threshold(b, BThresh, 255, cv2.THRESH_BINARY)  
    ret,maskg  = cv2.threshold(g, GThresh, 255, cv2.THRESH_BINARY)
    ret, maskr = cv2.threshold(r,RThresh, 255, cv2.THRESH_BINARY)


    #因要替换蓝色底,因此需要判断哪些像素是蓝底像素,判断时,要求经过阈值处理的G、R分量为0,B分量为255
    # 把符合此要求的灰度图作为处理图像的掩膜就能得到输入图像的背景色区域
    #如果要处理非蓝底的,则需要进行下面两行代码的修改将非底色的其他两个颜色的掩膜相或后求反,再与底色的掩膜相与
    maskrg = cv2.bitwise_not(cv2.bitwise_or(maskr,maskg))
    maskbgr = cv2.bitwise_and(maskb,maskrg)

    #由于在边界位置可能存在像素值情况可能与其他背景色不同的情况,因此可能需要进行背景掩膜的扩展膨胀(MORPH_DILATE)处理,且迭代次数可能也有不同,视具体图像而定

    if MorphOpCount:#背景色掩膜进行扩张处理
        kernal = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3))
        maskbgr = cv2.morphologyEx(maskbgr, cv2.MORPH_DILATE , kernal, iterations=MorphOpCount)


    #获得背景掩膜的反图像得到前景掩膜
    maskbgrInv = cv2.bitwise_not(maskbgr)

    #获取背景掩膜对应的白色背景对应图像
    bgWhite = cv2.bitwise_and(bgWhite, bgWhite, mask=maskbgr)

    #将输入图像应用前景掩膜,得到输入图像的前景,并将该前景与掩膜处理后的白色背景相叠加获得最后处理图像
    photoFront = cv2.bitwise_and(photo,photo,mask=maskbgrInv)
    result = cv2.bitwise_or(photoFront,bgWhite)

    #显示处理图像并设置鼠标回调函数,当出现未完全处理好的噪点时,通过鼠标获得该噪点位置的像素值,以调整前面的阈值处理的阈值
    cv2.imshow('pic',result)
    cv2.setMouseCallback('pic', OnMouseEvent,result)

    cv2.waitKey(0)

使用的自定义公用模块函数readImgFile,其功能请参考《https://blog.csdn.net/LaoYuanPython/article/details/111351901 OpenCV-Python图形图像处理:自用的一些工具函数功能及调用语法介绍》中的介绍。

三、测试过程

3.1、处理图片说明

本次介绍以百度“蓝底相片”找到的图片(如果涉及侵权请博客留言处理)作为处理对象介绍:
在这里插入图片描述

2、获取图像的背景色的阈值

怎么来确认R、G、B的阈值呢?网上有蓝底相片RGB值的多种说法,一方面太过理想化,另一方面说法还矛盾,怎么办呢?其实很简单,相片的左上角一般为底色,将图像加载后,看前几个像素的R、G、B值,让其作为参考阈值上下浮动一下。上述照片的前几个像素值如下:
在这里插入图片描述
可以看到前几个像素的B、G、R分量中B大于等于238、G小于等于115、R小于等于57,注意阈值处理函数在type为THRESH_BINARY时是小于等于阈值时为0,否则为指定最大值。

3、以前几个像素值作为参考来设定阈值

我们以B、G、R分别设置为237、115、57来设置阈值,不进行膨胀处理来调用上面实现的changePhotoBG函数来看看效果。
执行:changePhotoBG(r'f:\pic\girl.jpg',(237,115,57))

处理效果:
在这里插入图片描述
可以看到在涉及图像边界时处理效果不好,需要叠加背景色的扩展处理,对应调用为:

changePhotoBG(r'f:\pic\girl.jpg',(237,115,57),1)
changePhotoBG(r'f:\pic\girl.jpg',(237,115,57),2)
changePhotoBG(r'f:\pic\girl.jpg',(237,115,57),3)
changePhotoBG(r'f:\pic\girl.jpg',(237,115,57),5)

下图四张照片从上到下、从左到右对应分别做了1、2、3、5次膨胀后的结果图像:
在这里插入图片描述
可以看到膨胀5次以后基本上正常了,但还有一点点边界蓝色,再膨胀的话图片人像就会失真。
点击上述图片蓝色地方,看到输出的像素值如下:

(229, 266):[237 123  62]
(263, 116):[235 117  65]
(104, 269):[207 116  77]

因此根据这些输出调整BGR三个分量的值,将调用改为:changePhotoBG(r'f:\pic\girl.jpg',(206,123,77),3),可以得到如下图像:
在这里插入图片描述
可以看到效果相当不错了,老猿就没有再调整了。

四、小结

本文介绍了基于BGR颜色空间给蓝底照片换底的实现思路及程序代码,并将相关代码做成了一个比较通用的函数,只需要根据照片的背景色调整底色识别的B、G、R三个分量的阈值,就可以适应不同蓝色的背景色的照片情况,如果要处理非蓝底的,就需要将函数中求背景掩膜的两行代码相应进行调整。

本文代码测试完成并写完博文后,在网上找到了一篇类似功能介绍的博文,不过是基于HSV空间的,因此在标题中特地加上“基于RGB颜色空间”。过2天老猿将基于HSV的实现方式也写出,并提供参考博文对照一下。大家可以这2种颜色空间的实现方式都参考一下。具体博文请见《基于HSV颜色空间用OpenCV-Python给照片换底》。

更多图像处理的内容请参考专栏《OpenCV-Python图形图像处理 https://blog.csdn.net/laoyuanpython/category_9979286.html》、《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》及《图像处理基础知识》的介绍。

如对文章内容存在疑问,可在博客评论区留言,或关注老猿Python 微信公号发消息咨询。
在这里插入图片描述

关于老猿的付费专栏

  1. 付费专栏《https://blog.csdn.net/laoyuanpython/category_9607725.html 使用PyQt开发图形界面Python应用》专门介绍基于Python的PyQt图形界面开发基础教程,对应文章目录为《 https://blog.csdn.net/LaoYuanPython/article/details/107580932 使用PyQt开发图形界面Python应用专栏目录》;
  2. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10232926.html moviepy音视频开发专栏 )详细介绍moviepy音视频剪辑合成处理的类相关方法及使用相关方法进行相关剪辑合成场景的处理,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/107574583 moviepy音视频开发专栏文章目录》;
  3. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10581071.html OpenCV-Python初学者疑难问题集》为《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的伴生专栏,是笔者对OpenCV-Python图形图像处理学习中遇到的一些问题个人感悟的整合,相关资料基本上都是老猿反复研究的成果,有助于OpenCV-Python初学者比较深入地理解OpenCV,对应文章目录为《https://blog.csdn.net/LaoYuanPython/article/details/109713407 OpenCV-Python初学者疑难问题集专栏目录
  4. 付费专栏《https://blog.csdn.net/laoyuanpython/category_10762553.html Python爬虫入门 》站在一个互联网前端开发小白的角度介绍爬虫开发应知应会内容,包括爬虫入门的基础知识,以及爬取CSDN文章信息、博主信息、给文章点赞、评论等实战内容。

前两个专栏都适合有一定Python基础但无相关知识的小白读者学习,第三个专栏请大家结合《https://blog.csdn.net/laoyuanpython/category_9979286.html OpenCV-Python图形图像处理 》的学习使用。

对于缺乏Python基础的同仁,可以通过老猿的免费专栏《https://blog.csdn.net/laoyuanpython/category_9831699.html 专栏:Python基础教程目录)从零开始学习Python。

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

老猿Python, 跟老猿学Python!

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

老猿Python,跟老猿学Python!

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于RGB颜色空间使用OpenCV-Python实现照片换底 的相关文章

随机推荐

  • error: (-209) The operation is neither ‘array op array‘ (where arrays have the same size and type)

    问题展示 error 209 The operation is neither array op array where arrays have the same size and type 错误原因 两个矩阵尺寸大小不一样 解决方法 指定
  • IDEA运行缓慢卡顿,解决idea卡顿,控制台中文乱码 以及其它常用设置

    IDEA运行缓慢卡顿 解决idea卡顿问题以及常用设置 IDEA卡顿原因 优化IDEA配置 重点推荐的方法 手动修改IDEA配置步骤 其他卡顿优化 参考 1 idea启动时会有两个快捷方式 2 卸载不需要用的插件 3 减少内存 4 适当关闭
  • HttpClient 简介说明

    转自 HttpClient 简介说明 下文笔者将讲述HttpClient框架的简介说明 如下所示 HttpCient简介说明 HttpClient是一个开源项目 它是Apache Jakarta Common下的一个子项目 HttpClie
  • Invalid Address specified to RtlValidateHeap

    Invalid Address specified to RtlValidateHeap VC编程 最后推出对话框的时候 会有错误提示声音 硄 但是没有弹出错误提示对话框 症状描述与下面的类似 声音就和Assertion Failure一样
  • html遍历数组,JS数组遍历的几种方式

    JS数组遍历 基本就是for forin foreach forof map等等一些方法 以下介绍几种本文分析用到的数组遍历方式以及进行性能分析对比 第一种 普通for循环 代码如下 for j 0 j lt arr length j 简要
  • 【三电平SVPWM学习

    导读 本期对三电平SVPWM的原理和建模做一个简单介绍 并与两电平SVPWM做了一个对比 后面把三电平的SVPWM运用到异步电机直接转矩控制中 看与传统的两电平SVPWM 控制性能是否得到改善 模型可分享 关注公众号 浅谈电机控制 留下邮箱
  • 八大排序算法(六)——优先队列、堆和堆排序

    6 1 API 优先队列是一种抽象数据类型 它表示了一组值和对这些值的操作 优先队列最重要的操作就是删除最大元素和插入元素 6 2 初级实现 6 2 1 数组实现 无序 或许实现优先队列最简单方法就是基于下压栈的代码 insert 方法的代
  • java通过文件路径读取该路径下的所有文件并将其放入list中

    java通过文件路径读取该路径下的所有文件并将其放入list中 java中可以通过递归的方式获取指定路径下的所有文件并将其放入List集合中 假设指定路径为path 目标集合为fileList 遍历指定路径下的所有文件 如果是目录文件则递归
  • 旋转链表(leetcode)

    61 旋转链表 给你一个链表的头节点 head 旋转链表 将链表每个节点向右移动 k 个位置 示例 1 输入 head 1 2 3 4 5 k 2 输出 4 5 1 2 3 示例 2 输入 head 0 1 2 k 4 输出 2 0 1 提
  • centos安装配置hadoop超详细过程(含故障排除)

    1 集群部署介绍 1 1 Hadoop简介 Hadoop是Apache软件基金会旗下的一个开源分布式计算平台 以Hadoop分布式文件系统 HDFS Hadoop Distributed Filesystem 和MapReduce Goog
  • 计算机科学丛书(2014-2018.Q1)

    ISBN 名称 作者 出版时间 978 7 111 53451 8 数学设计和计算机体系结构 原书第2版 美 戴维 莫尼 哈里斯 莎拉 L 哈里斯著 978 7 111 44075 8 嵌入式计算系统设计原理 美 Marilyn Wolf著
  • C#中string.Format输出内容中含有花括号的解决方法

    转载一篇 版权声明 本文为CSDN博主 九德真君 的原创文章 遵循CC 4 0 BY SA版权协议 转载请附上原文出处链接及本声明 原文链接 https blog csdn net lzdidiv article details 69469
  • python matrix用法_numpy中matrix使用方法

    matrix T transpose 返回矩阵的转置矩阵 matrix H hermitian conjugate transpose 返回复数矩阵的共轭元素矩阵 matrix I inverse 返回矩阵的逆矩阵 matrix A bas
  • 基于C语言实现的文件压缩算法-哈夫曼编码

    哈夫曼编码 是一种数据压缩算法 通常用于无损数据压缩 该算法是由 David A Huffman在麻省理工学院就读理学博士 Doctor of Science 的时候发明的 这位大佬在1952年发表了相关的一篇论文A Method for
  • 页面上input输入框宽度实现自动调整

    input输入框宽度实现自动调整 本文介绍两种方式 一是通过获取input内容的宽度实现输入框宽度的自动调整 二是通过内容字符串的长度乘以文本字体大小的积 来实现输入框宽度的自动调整 1 input输入框宽度的获取方式一 由于input输入
  • 利用maven项目创建一个web项目工程(图文详解)

    最近正开始学习java 老师布置的第一个作业便是用maven项目创建一个web项目工程 不会 跑去百度了半天 跳出来的全是我们csdn的教程 但到创建资源包的时候就没法跟着做了 因为显示已存在 没法跟着创建了 那些文章基本一样的讲法 都是默
  • 超详细的用IDEA整合SSM框架和profile 配置环境

    SSM作为现在最流行的开发框架 很大的提升了开发效率 一些同学在SSM基础上的整合一些更实用的开发基础框架 被用来作为快速开发的基础框架 本次实践主要是以下3个目标 从最基础的SSM框架做起 摸索和处理SSM框架整合中可能会遇到的问题 使用
  • 手机知识:手机的快充技术是什么,看完本文你就懂了

    目录 1 什么是手机快充 2 目前主流的手机快充协议 2 1 PD协议 2 2 PE协议 联发科 2 3 QC协议 高通 2 4 VOOC闪充 OPPO厂商 2 5 SCP FCP闪充 华为厂商 2 6 FlashCharge闪充 Vivo
  • 【前后端数据交互:Axios】

    前后端数据交互 Axios Axios 介绍 在前端页面展示的数据大多数都是通过访问一个API获取的 做这件事的方法有好几种 例如jquery ajax vue resource axios 而vue resource是vue插件 但3版本
  • 基于RGB颜色空间使用OpenCV-Python实现照片换底

    前往老猿Python博文目录 https blog csdn net LaoYuanPython 一 引言 前一阵子家人报考教师资格证考试 因报名需要将蓝底的数字相片换成白底的 老猿虽然在学习图像处理相关开发技术 但并没有熟练使用的图像编辑