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