python使用opencv換照片底色的實(shí)現(xiàn)
python使用opencv換照片底色
第一次使用opencv,遇到了很多問題,記錄一下
安裝問題
代理
由于pip使用了代理而電腦代理沒開,導(dǎo)致pip install opencv-python時(shí)一直報(bào)錯(cuò)連接不上代理
解決辦法:
- 1.使用pip install -i <清華源>
- 2.開啟代理
無法引入jar包
安裝完成后在交互模式可以正常使用
輸入python
import cv2
不報(bào)錯(cuò)就說明正常安裝了
但是在jupyter notebook 中引入一直報(bào)錯(cuò),找不到cv2模塊
經(jīng)過百度后,測試如下
在交互模式下輸入如下命令查看python環(huán)境
import sys sys.executable

這是anaconda下的一個(gè)虛擬環(huán)境,沒有問題
再在jupyter notebook下輸入同樣的命令,查看python環(huán)境,發(fā)現(xiàn)竟然不是上述環(huán)境
而是 anaconda3/share下的環(huán)境
至此,就查詢到了問題的原因:
jupyter notebook 是anaconda的公共包
進(jìn)入虛擬環(huán)境后 pip install jupyter 再次啟動(dòng)jupyter notebooke 就正常了
使用opencv及原理
使用opencv換照片底色的原理很簡單
- 讀取照片
- 將照片轉(zhuǎn)換為灰度圖
- 提取灰度圖底色的BGR上下邊界
- 使用opencv轉(zhuǎn)換背景底色的BGR值(第三步已經(jīng)獲取了背景色的上下邊界,邊界之中的所有顏色都會被轉(zhuǎn)換為255,邊界之外的顏色都會被處理為0)
- 循環(huán)處理像素點(diǎn),將第四步轉(zhuǎn)換后的255(背景色)轉(zhuǎn)換為你想要的顏色
- 輸出,保存
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)
# 圖片轉(zhuǎn)換為灰度圖
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)
#遍歷每個(gè)像素點(diǎn),進(jìn)行顏色的替換
for i in range(rows):
for j in range(cols):
if erode[i,j]==255: # 像素點(diǎn)為255表示的是白色,我們就是要將白色處的像素點(diǎn),替換為紅色
img[i,j]=(255,255,255) # 此處替換顏色,為BGR通道,不是RGB通道
# 顯示處理后的圖片
cv2.imshow('res',img)
# 保存
cv2.imwrite("zhuominghu_white.jpg", img)
# 窗口等待的命令,0表示無限等待
cv2.waitKey(0)代碼是參照網(wǎng)上的例子,經(jīng)過實(shí)驗(yàn),很好用
但是在圖片的二值化處理階段,比較麻煩,需要從灰度圖中獲取背景色的BGR值,再計(jì)算上下邊界
灰度圖的顏色使用BGR表示的,而不是 RGB
使用的到方法:
imread()讀取源圖片imshow()展示圖片imwrite()輸出圖片cvtColor()轉(zhuǎn)換灰度圖inRange()二值化處理,將上下邊界內(nèi)的顏色值處理為255,其他的顏色值處理為0
python opencv一鍵換底色,不同底色自動(dòng)判斷
圖來源于網(wǎng)絡(luò),未有冒犯之意
思路來源
最近到處需要用到一寸照,但是有些底色不同,一開始網(wǎng)上隨便找了幾個(gè),但是完成后都是要收費(fèi)的,后面用到removebg,摳圖一鍵換底色,但是有像素限制,高像素需要收費(fèi)下載,所以自己無聊用參考網(wǎng)上資料opencv寫了個(gè),網(wǎng)上都是單個(gè)顏色處理,并且對于參數(shù)有些有限制,在細(xì)節(jié)處理上不通用,所以自己重新寫了一個(gè)并簡單做了個(gè)界面,雖然比removebg差多了,不過好歹能用。
需求
- 懶人式換一寸照底色
- 界面應(yīng)用
- 多底色選擇
- 自動(dòng)識別底色
- 學(xué)習(xí)代碼使用,要求不高
預(yù)覽

對比
原圖

紅底

綠底

白底

代碼
# -*- 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]
#導(dǎo)入圖片,不能有中文路徑
# img=cv2.imread(path)
#導(dǎo)入圖片,可以有中文路徑
img = cv2.imdecode(np.fromfile(path, dtype=np.uint8), 1)
#圖片縮放
#img=cv2.resize(img,None,fx=0.5,fy=0.5)
#轉(zhuǎn)換hsv,提取顏色
#cv2.cvtColor是顏色空間轉(zhuǎn)換函數(shù),img是需要轉(zhuǎn)換的圖片,第二個(gè)是轉(zhuǎn)換成何種格式。
hsv=cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
#判斷當(dāng)前圖片底色
if img[0][0][0]>200 and img[0][0][1]<230 and img[0][0][2]<230:
# print('原圖藍(lán)色底')
#提取顏色區(qū)域,不在范圍的設(shè)為0,在范圍的設(shè)為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", "藍(lán)色"))
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_())
小結(jié):在網(wǎng)絡(luò)上下載不同底色的圖片實(shí)驗(yàn)了幾十次,發(fā)現(xiàn)白底穿白色衣服時(shí)直接將身體也被更換的底色覆蓋了,所以至始至終都是超級簡陋的換底,還是removebg這些經(jīng)過學(xué)習(xí)的好,連發(fā)絲間都能更換,看起來比較細(xì)膩順滑,不過在此過程中也學(xué)到了一些圖片處理的知識,opencv默認(rèn)是BGR的,而有些庫是RGB的,所以在判斷底色的時(shí)候一開始我是使用hsv,發(fā)現(xiàn)行不通,后面只好使用BGR提取色塊來判斷。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python Matplotlib 基于networkx畫關(guān)系網(wǎng)絡(luò)圖
這篇文章主要介紹了Python Matplotlib 基于networkx畫關(guān)系網(wǎng)絡(luò)圖,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07
Python格式化字符串f-string概覽(小結(jié))
這篇文章主要介紹了Python格式化字符串f-string概覽(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-06-06
Python算法思想集結(jié)深入理解動(dòng)態(tài)規(guī)劃
這篇文章主要為大家介紹了Python算法思想集結(jié)深入理解動(dòng)態(tài)規(guī)劃詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09
淺析Python的web.py框架中url的設(shè)定方法
web.py是Python的一個(gè)輕量級Web開發(fā)框架,這里我們來淺析Python的web.py框架中url的設(shè)定方法,需要的朋友可以參考下2016-07-07

