python使用opencv换照片底色的实现

 更新时间:2022年11月29日 10:05:16   作者:zhang.yao  
这篇文章主要介绍了python使用opencv换照片底色的实现方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

python使用opencv换照片底色

第一次使用opencv,遇到了很多问题,记录一下

安装问题

代理

由于pip使用了代理而电脑代理没开,导致pip install opencv-python时一直报错连接不上代理

解决办法:

  • 1.使用pip install -i <清华源>
  • 2.开启代理

无法引入jar包

安装完成后在交互模式可以正常使用

输入python

import cv2

不报错就说明正常安装了

但是在jupyter notebook 中引入一直报错,找不到cv2模块

经过百度后,测试如下

交互模式下输入如下命令查看python环境

import sys
sys.executable

这是anaconda下的一个虚拟环境,没有问题

再在jupyter notebook下输入同样的命令,查看python环境,发现竟然不是上述环境

而是 anaconda3/share下的环境

至此,就查询到了问题的原因:

jupyter notebook 是anaconda的公共包

进入虚拟环境后 pip install jupyter 再次启动jupyter notebooke 就正常了

使用opencv及原理

使用opencv换照片底色的原理很简单

  • 读取照片
  • 将照片转换为灰度图
  • 提取灰度图底色的BGR上下边界
  • 使用opencv转换背景底色的BGR值(第三步已经获取了背景色的上下边界,边界之中的所有颜色都会被转换为255,边界之外的颜色都会被处理为0)
  • 循环处理像素点,将第四步转换后的255(背景色)转换为你想要的颜色
  • 输出,保存
import cv2
import numpy as np
# 读取照片
img=cv2.imread('zhuominghua.jpg')
 
# 图像缩放
img = cv2.resize(img,None,fx=0.5,fy=0.5)
rows,cols,channels = img.shape
print(rows,cols,channels)
cv2.imshow('[img]',img)
 
# 图片转换为灰度图
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
# 查看灰度图
cv2.imshow('hsv',hsv)
 
# 图片的二值化处理
lower_blue=np.array([100,0,200])
upper_blue=np.array([200,255,255])
mask = cv2.inRange(hsv, lower_blue, upper_blue)
print(mask)
 
 
#腐蚀膨胀
erode=cv2.erode(mask,None,iterations=1)
# cv2.imshow('erode',erode)
 
dilate=cv2.dilate(erode,None,iterations=1)
# cv2.imshow('dilate',dilate)
 
#遍历每个像素点,进行颜色的替换
for i in range(rows):
  for j in range(cols):
    if erode[i,j]==255: # 像素点为255表示的是白色,我们就是要将白色处的像素点,替换为红色
      img[i,j]=(255,255,255) # 此处替换颜色,为BGR通道,不是RGB通道
# 显示处理后的图片
cv2.imshow('res',img)

# 保存
cv2.imwrite("zhuominghu_white.jpg", img)
# 窗口等待的命令,0表示无限等待
cv2.waitKey(0)

代码是参照网上的例子,经过实验,很好用

但是在图片的二值化处理阶段,比较麻烦,需要从灰度图中获取背景色的BGR值,再计算上下边界

灰度图的颜色使用BGR表示的,而不是 RGB

使用的到方法:

  • imread() 读取源图片
  • imshow() 展示图片
  • imwrite() 输出图片
  • cvtColor() 转换灰度图
  • inRange() 二值化处理,将上下边界内的颜色值处理为255,其他的颜色值处理为0

python opencv一键换底色,不同底色自动判断

图来源于网络,未有冒犯之意

思路来源

最近到处需要用到一寸照,但是有些底色不同,一开始网上随便找了几个,但是完成后都是要收费的,后面用到removebg,抠图一键换底色,但是有像素限制,高像素需要收费下载,所以自己无聊用参考网上资料opencv写了个,网上都是单个颜色处理,并且对于参数有些有限制,在细节处理上不通用,所以自己重新写了一个并简单做了个界面,虽然比removebg差多了,不过好歹能用。

需求

  • 懒人式换一寸照底色
  • 界面应用
  • 多底色选择
  • 自动识别底色
  • 学习代码使用,要求不高

预览

在这里插入图片描述

对比

原图

图像来源于网络

红底

在这里插入图片描述

绿底

在这里插入图片描述

白底

在这里插入图片描述

代码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'untitled.ui'
#
# Created by: PyQt5 UI code generator 5.13.0
#
# WARNING! All changes made in this file will be lost!

import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox,QInputDialog,QFileDialog
import cv2,time,sys
import numpy as np

def change_bg_color(path,color):
    global new_path
    color_dict={'red':[0,0,255],'green':[0,255,0],'blue':[255,0,0],'white':[255,255,255]}
    color_list=color_dict[color]
    #导入图片,不能有中文路径
    # img=cv2.imread(path)
    #导入图片,可以有中文路径
    img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), 1)
    #图片缩放
    #img=cv2.resize(img,None,fx=0.5,fy=0.5)
    #转换hsv,提取颜色
    #cv2.cvtColor是颜色空间转换函数,img是需要转换的图片,第二个是转换成何种格式。
    hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
    #判断当前图片底色
    if img[0][0][0]>200 and img[0][0][1]<230 and img[0][0][2]<230:
#         print('原图蓝色底')
        #提取颜色区域,不在范围的设为0,在范围的设为255
        hsv_min=np.array([47,79,79])
        hsv_max=np.array([102,255,255])
    elif img[0][0][1]>200 and img[0][0][0]<230 and img[0][0][2]<230:
#         print('原图绿色底')
        hsv_min = np.array([41,40,41])
        hsv_max = np.array([90,255,255])   
    elif img[0][0][2]>200 and img[0][0][0]<230 and img[0][0][1]<230:
#         print('原图红色底')
        hsv_min = np.array([0,200,40])
        hsv_max = np.array([10,255,255])
    else:
#         print('原图白色底')
        hsv_min = np.array([0,0,221])
        hsv_max = np.array([180,30,255])
        
    mask = cv2.inRange(hsv, hsv_min, hsv_max)
    # #腐蚀膨胀
    erode=cv2.erode(mask,None,iterations=1)
    dilate=cv2.dilate(erode,None,iterations=1)
#     cv2.imshow('res',dilate)
    rows,cols,channels = img.shape
    #遍历替换
    for i in range(rows):
        for j in range(cols):
            if dilate[i,j]==255:
                img[i,j]=(color_list[0],color_list[1],color_list[2])#此处替换颜色,为BGR通道
    new_path='%s_%s.jpg'%(str(int(time.time())),color)
    path=path.replace(path.split('/')[-1],new_path)
    new_path=path
    #防止中文路径
    cv2.imencode('.jpg',img)[1].tofile(path)
#     cv2.imwrite(path,img)
#     cv2.imshow('res',img)
#     cv2.waitKey(0)
#     cv2.destroyAllWindows()

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(280, 0, 251, 331))
        self.pushButton.setObjectName("pushButton")
        self.pushButton.clicked.connect(self.openFile)
        
        self.pushButton_2 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_2.setGeometry(QtCore.QRect(140, 390, 101, 51))
        self.pushButton_2.setObjectName("pushButton_2")
        self.pushButton_2.clicked.connect(lambda:self.setimg_bg("blue"))
        
        self.pushButton_3 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_3.setGeometry(QtCore.QRect(280, 390, 101, 51))
        self.pushButton_3.setObjectName("pushButton_3")
        self.pushButton_3.clicked.connect(lambda:self.setimg_bg("green"))
        
        self.pushButton_4 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_4.setGeometry(QtCore.QRect(430, 390, 101, 51))
        self.pushButton_4.setObjectName("pushButton_4")
        self.pushButton_4.clicked.connect(lambda:self.setimg_bg("red"))
        
        self.pushButton_5 = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_5.setGeometry(QtCore.QRect(570, 390, 101, 51))
        self.pushButton_5.setObjectName("pushButton_5")
        self.pushButton_5.clicked.connect(lambda:self.setimg_bg("white"))
        
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 26))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
        
    def openFile(self):
        global img_path
        get_filename_path, ok = QFileDialog.getOpenFileName()
        if ok:
            img_path=str(get_filename_path)
            self.pushButton.setStyleSheet("QPushButton{border-image: url(%s)}"%str(get_filename_path))
            
    def setimg_bg(self,color):
        global img_path,new_path
        if img_path != '':
            change_bg_color(img_path,color)
            self.pushButton.setStyleSheet("QPushButton{border-image: url(%s)}"%str(new_path))
            
    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", ""))
        self.pushButton_2.setText(_translate("MainWindow", "蓝色"))
        self.pushButton_3.setText(_translate("MainWindow", "绿色"))
        self.pushButton_4.setText(_translate("MainWindow", "红色"))
        self.pushButton_5.setText(_translate("MainWindow", "白色"))

if __name__ == '__main__':
    global img_path,new_path
    img_path=''
    app = QApplication(sys.argv)
    MainWindow = QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

小结:在网络上下载不同底色的图片实验了几十次,发现白底穿白色衣服时直接将身体也被更换的底色覆盖了,所以至始至终都是超级简陋的换底,还是removebg这些经过学习的好,连发丝间都能更换,看起来比较细腻顺滑,不过在此过程中也学到了一些图片处理的知识,opencv默认是BGR的,而有些库是RGB的,所以在判断底色的时候一开始我是使用hsv,发现行不通,后面只好使用BGR提取色块来判断。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Django开发中的日志输出的方法

    Django开发中的日志输出的方法

    这篇文章主要介绍了Django开发中的日志输出的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-07-07
  • python2.7使用scapy发送syn实例

    python2.7使用scapy发送syn实例

    这篇文章主要介绍了python2.7使用scapy发送syn实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-05-05
  • 基于Python-turtle库绘制路飞的草帽骷髅旗、美国队长的盾牌、高达的源码

    基于Python-turtle库绘制路飞的草帽骷髅旗、美国队长的盾牌、高达的源码

    这篇文章主要介绍了基于Python-turtle库绘制路飞的草帽骷髅旗、美国队长的盾牌、高达的源码,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-02-02
  • Python之Sklearn使用入门教程

    Python之Sklearn使用入门教程

    这篇文章主要介绍了Python之Sklearn使用入门教程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-02-02
  • python整合ffmpeg实现视频文件的批量转换

    python整合ffmpeg实现视频文件的批量转换

    这篇文章主要为大家详细介绍了python整合ffmpeg实现视频文件的批量转换,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • Pytorch写数字识别LeNet模型

    Pytorch写数字识别LeNet模型

    这篇文章主要介绍了Pytorch写数字识别LeNet模型,LeNet-5是一个较简单的卷积神经网络,  LeNet-5 这个网络虽然很小,但是它包含了深度学习的基本模块:卷积层,池化层,全连接层。是其他深度学习模型的基础, 这里我们对LeNet-5进行深入分析,需要的朋友可以参考下
    2022-01-01
  • 解决python3安装pandas出错的问题

    解决python3安装pandas出错的问题

    这篇文章主要介绍了解决python3安装pandas出错的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-05-05
  • Python算法思想集结深入理解动态规划

    Python算法思想集结深入理解动态规划

    这篇文章主要为大家介绍了Python算法思想集结深入理解动态规划详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • Python smtplib实现发送邮件功能

    Python smtplib实现发送邮件功能

    这篇文章主要为大家详细介绍了Python smtplib实现发送邮件功能,包含文本、附件、图片等,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Python中有哪些关键字及关键字的用法

    Python中有哪些关键字及关键字的用法

    这篇文章主要介绍了Python中有哪些关键字及关键字的用法,分享python中常用的关键字,本文结合示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-02-02

最新评论