最近到处需要用到一寸照,但是有些底色不同,一开始网上随便找了几个,但是完成后都是要收费的,后面用到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提取色块来判断。