python使用opencv換照片底色的實(shí)現(xiàn)
python使用opencv換照片底色
第一次使用opencv,遇到了很多問(wèn)題,記錄一下
安裝問(wèn)題
代理
由于pip使用了代理而電腦代理沒(méi)開,導(dǎo)致pip install opencv-python時(shí)一直報(bào)錯(cuò)連接不上代理
解決辦法:
- 1.使用pip install -i <清華源>
- 2.開啟代理
無(wú)法引入jar包
安裝完成后在交互模式可以正常使用
輸入python
import cv2
不報(bào)錯(cuò)就說(shuō)明正常安裝了
但是在jupyter notebook 中引入一直報(bào)錯(cuò),找不到cv2模塊
經(jīng)過(guò)百度后,測(cè)試如下
在交互模式下輸入如下命令查看python環(huán)境
import sys sys.executable
這是anaconda下的一個(gè)虛擬環(huán)境,沒(méi)有問(wèn)題
再在jupyter notebook下輸入同樣的命令,查看python環(huán)境,發(fā)現(xiàn)竟然不是上述環(huán)境
而是 anaconda3/share下的環(huán)境
至此,就查詢到了問(wèn)題的原因:
jupyter notebook 是anaconda的公共包
進(jìn)入虛擬環(huán)境后 pip install jupyter 再次啟動(dòng)jupyter notebooke 就正常了
使用opencv及原理
使用opencv換照片底色的原理很簡(jiǎn)單
- 讀取照片
- 將照片轉(zhuǎn)換為灰度圖
- 提取灰度圖底色的BGR上下邊界
- 使用opencv轉(zhuǎn)換背景底色的BGR值(第三步已經(jīng)獲取了背景色的上下邊界,邊界之中的所有顏色都會(huì)被轉(zhuǎn)換為255,邊界之外的顏色都會(huì)被處理為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表示無(wú)限等待 cv2.waitKey(0)
代碼是參照網(wǎng)上的例子,經(jīng)過(guò)實(shí)驗(yàn),很好用
但是在圖片的二值化處理階段,比較麻煩,需要從灰度圖中獲取背景色的BGR值,再計(jì)算上下邊界
灰度圖的顏色使用BGR表示的,而不是 RGB
使用的到方法:
imread()
讀取源圖片imshow()
展示圖片imwrite()
輸出圖片cvtColor()
轉(zhuǎn)換灰度圖inRange()
二值化處理,將上下邊界內(nèi)的顏色值處理為255,其他的顏色值處理為0
python opencv一鍵換底色,不同底色自動(dòng)判斷
圖來(lái)源于網(wǎng)絡(luò),未有冒犯之意
思路來(lái)源
最近到處需要用到一寸照,但是有些底色不同,一開始網(wǎng)上隨便找了幾個(gè),但是完成后都是要收費(fèi)的,后面用到removebg,摳圖一鍵換底色,但是有像素限制,高像素需要收費(fèi)下載,所以自己無(wú)聊用參考網(wǎng)上資料opencv寫了個(gè),網(wǎng)上都是單個(gè)顏色處理,并且對(duì)于參數(shù)有些有限制,在細(xì)節(jié)處理上不通用,所以自己重新寫了一個(gè)并簡(jiǎn)單做了個(gè)界面,雖然比removebg差多了,不過(guò)好歹能用。
需求
- 懶人式換一寸照底色
- 界面應(yīng)用
- 多底色選擇
- 自動(dòng)識(shí)別底色
- 學(xué)習(xí)代碼使用,要求不高
預(yù)覽
對(duì)比
原圖
紅底
綠底
白底
代碼
# -*- 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í)直接將身體也被更換的底色覆蓋了,所以至始至終都是超級(jí)簡(jiǎn)陋的換底,還是removebg這些經(jīng)過(guò)學(xué)習(xí)的好,連發(fā)絲間都能更換,看起來(lái)比較細(xì)膩?lái)樆?,不過(guò)在此過(guò)程中也學(xué)到了一些圖片處理的知識(shí),opencv默認(rèn)是BGR的,而有些庫(kù)是RGB的,所以在判斷底色的時(shí)候一開始我是使用hsv,發(fā)現(xiàn)行不通,后面只好使用BGR提取色塊來(lái)判斷。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Python使用type動(dòng)態(tài)創(chuàng)建類操作示例
這篇文章主要介紹了Python使用type動(dòng)態(tài)創(chuàng)建類操作,結(jié)合實(shí)例形式詳細(xì)分析了Python使用type動(dòng)態(tài)創(chuàng)建類的具體原理、實(shí)現(xiàn)方法與操作注意事項(xiàng),需要的朋友可以參考下2020-02-02Python 在OpenCV里實(shí)現(xiàn)仿射變換—坐標(biāo)變換效果
這篇文章主要介紹了Python 在OpenCV里實(shí)現(xiàn)仿射變換—坐標(biāo)變換效果,本文通過(guò)一個(gè)例子給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-08-08利用Python腳本實(shí)現(xiàn)傳遞參數(shù)的三種方式分享
使用python腳本傳遞參數(shù)在實(shí)際工作過(guò)程中還是比較常用。這篇文章為大家總結(jié)了三個(gè)常用的方式,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-12-12Python 實(shí)現(xiàn)局域網(wǎng)遠(yuǎn)程屏幕截圖案例
這篇文章主要介紹了Python 實(shí)現(xiàn)局域網(wǎng)遠(yuǎn)程屏幕截圖案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03python3實(shí)現(xiàn)單目標(biāo)粒子群算法
這篇文章主要為大家詳細(xì)介紹了python3實(shí)現(xiàn)單目標(biāo)粒子群算法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-11-11Keras多線程機(jī)制與flask多線程沖突的解決方案
這篇文章主要介紹了Keras多線程機(jī)制與flask多線程沖突的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-05-05在Python中實(shí)現(xiàn)貪婪排名算法的教程
這篇文章主要介紹了在Python中實(shí)現(xiàn)貪婪排名算法的教程,也是對(duì)學(xué)習(xí)算法的一個(gè)很好的演示,需要的朋友可以參考下2015-04-04