將指定的顏色變透明
這篇教學會介紹使用 OpenCV 讀取影像,將影像轉換成具有透明色版 ( alpha channel ) 的顏色模式後,將某些指定的顏色換成透明,做到在單色背景中去背的影像效果。
快速導覽:
因為程式中的 OpenCV 會需要使用鏡頭或 GPU,所以請使用本機環境 ( 參考:使用 Python 虛擬環境 ) 或使用 Anaconda Jupyter 進行實作 ( 參考:使用 Anaconda ) ,並安裝 OpenCV 函式庫 ( 參考:OpenCV 函式庫 )。
開啟圖片,轉換色彩
使用 imread() 的 cv2.IMREAD_UNCHANGED 參數開啟圖片,可以開啟原本帶有透明色版 ( alpha channel ) 的圖片,下方的例子,img1 是一張帶有透明色版的 png,img2 是一張沒有透明色版的 jpg,開啟圖片後使用 img.shape 就能看到第三個數值有所不同。
import cv2
img1 = cv2.imread('test.jpg', cv2.IMREAD_UNCHANGED)
img2 = cv2.imread('test.png', cv2.IMREAD_UNCHANGED)
print(img1.shape) # (400, 300, 3) JPG 只有三個色版 BGR
print(img2.shape) # (400, 300, 4) PNG 四個色版 GRA
除了直接開啟帶有透明色版的圖片,也可使用 cv2.cvtColor 的方法,將沒有包含透明色版的圖片,轉換為帶有透明色版的 BGRA 色彩模式。
參考:影像的色彩轉換
import cv2
img = cv2.imread('test.jpg', cv2.IMREAD_UNCHANGED)
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA) # 轉換成 BGRA 色彩模式
print(img.shape) # (400, 300, 4) 第三個數值變成 4
將指定的顏色變成透明
影像中透明色版區間為 0~255,0 表示全透明,255 表示不透明,因此只要將指定顏色的透明色版設定為 0,就能讓該顏色變成透明,下方的程式碼執行後,會將 opencv logo 圖檔中的白色去除變成透明,最後儲存為背景透明的 png。
範例圖檔:OpenCV logo
import cv2
img = cv2.imread('logo.jpg', cv2.IMREAD_UNCHANGED) # 開啟圖片
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA) # 因為是 jpg,要轉換顏色為 BGRA
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 新增 gray 變數為轉換成灰階的圖片
h = img.shape[0] # 取得圖片高度
w = img.shape[1] # 取得圖片寬度
# 依序取出圖片中每個像素
for x in range(w):
for y in range(h):
if gray[y, x]>200:
img[y, x, 3] = 255 - gray[y, x]
# 如果該像素的灰階度大於 200,調整該像素的透明度
# 使用 255 - gray[y, x] 可以將一些邊緣的像素變成半透明,避免太過鋸齒的邊緣
cv2.imwrite('oxxostudio.png', img) # 存檔儲存為 png
cv2.waitKey(0) # 按下任意鍵停止
cv2.destroyAllWindows()
使用同樣的方法,也可以將某個顏色置換為另外一種顏色,下方的程式碼會將白色部分置換為黃色。
import cv2
img = cv2.imread('logo.jpg', cv2.IMREAD_UNCHANGED)
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
h = img.shape[0]
w = img.shape[1]
for x in range(w):
for y in range(h):
if gray[y, x]>200:
img[y, x] = [0,255,255,255] # 換成黃色
cv2.imwrite('oxxostudio.png', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
圖片去背,加上其他背景圖
下方的程式碼運用同樣的原理,將背景單純的物體去背 ( 去除背景 ),然後再與其他圖片進行重疊合成。
範例圖檔:悟空公仔、Windows 經典背景
import cv2
bg = cv2.imread('bg.jpg', cv2.IMREAD_UNCHANGED) # 開啟背景圖
bg = cv2.cvtColor(bg, cv2.COLOR_BGR2BGRA) # 轉換成 BGRA
img = cv2.imread('goku.jpg', cv2.IMREAD_UNCHANGED) # 開啟悟空公仔圖
img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA) # 轉換成 BGRA
h = img.shape[0] # 取得圖片高度
w = img.shape[1] # 取得圖片寬度
for x in range(w):
for y in range(h):
r = img[y, x, 2] # 取得該像素的紅色值
g = img[y, x, 1] # 取得該像素的綠色值
b = img[y, x, 0] # 取得該像素的藍色值
if r>20 and r<80 and g<190 and g>110 and b<150 and b>60:
img[y, x] = bg[y, x] # 如果在範圍內的顏色,換成背景圖的像素值
cv2.imwrite('oxxostudio.png', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
意見回饋
如果有任何建議或問題,可傳送「意見表單」給我,謝謝~