作者:Adrian Rosebrock
編譯:Color Space
導讀
本文主要介紹如何在兩個圖像之間實作顔色遷移的功能。給定任意兩個圖像,一個源圖像,一個目标圖像,然後可以将源圖像的顔色空間遷移到目标圖像。
算法實作與步驟
算法實作:通過分别利用L*a*b顔色空間以及每個L*、a*和b*通道的均值和标準差來實作顔色遷移。
實作步驟:
(1)輸入源圖像和目标圖像。源圖像包含你希望目标圖像模仿的顔色空間,在本頁中,左側日落圖像
是source, 中間是target, 右側是source應用與target的結果;
(2)将源圖像和目标圖像都轉換到Lab顔色空間。Lab顔色空間模拟感覺均勻性,其中顔色量的微小變化也應該産生顔色重要性的相對相等的變化。L*a*b* 顔色空間比标準 RGB 顔色空間在模仿人類如何解釋顔色方面做得更好,并且如您所見,非常适合顔色轉移。
(3)将源圖像和目标圖像都做通道分離。
(4)計算source和target圖像的每個 L*a*b* 通道的平均值和标準偏差。
(5)目标圖像通道分離為L,a,b後,每個通道減去對應通道的均值
(6)target圖像每個通道的标準偏差除以源圖像對應通道标準偏差,再乘以對應通道圖像對目标圖像通道進行縮放。
(7)添加 L*a*b* 通道的均值source。
(8)裁剪任何超出範圍[0, 255] 的值。(注意:這一步不是原始論文的一部分。由于 OpenCV 處理顔色空間轉換的方式,我添加了它。如果你要在不同的語言/庫中實作這個算法,你要麼必須執行顔色空間轉換自己,或了解進行轉換的庫是如何工作的)。
(9)将通道重新合并在一起。
(10)從L*a*b*空間轉換回RGB色彩空間。
實作代碼與效果
Python OpenCV代碼:
# 導入需要的包
import numpy as np
import cv2
import sys
def color_transfer(source, target):
# 将源圖像和目标圖像從BGR顔色空間轉到Lab顔色通道
# 確定使用OpenCV圖像為32位浮點類型資料
source = cv2.cvtColor(source, cv2.COLOR_BGR2LAB).astype("float32")
target = cv2.cvtColor(target, cv2.COLOR_BGR2LAB).astype("float32")
# 計算源圖像和目标圖像的顔色統計資訊(每個通道的均值和标準差)
# L通道均值、标準差,a通道均值、标準差,b通道均值、标準差
(lMeanSrc, lStdSrc, aMeanSrc, aStdSrc, bMeanSrc, bStdSrc) = image_stats(source)
(lMeanTar, lStdTar, aMeanTar, aStdTar, bMeanTar, bStdTar) = image_stats(target)
# 從目标圖像中減去均值
(l, a, b) = cv2.split(target)
l -= lMeanTar
a -= aMeanTar
b -= bMeanTar
# 按标準差縮放(scale_rate = 目标圖像标準差/源圖像标準差)
l = (lStdTar / lStdSrc) * l
a = (aStdTar / aStdSrc) * a
b = (bStdTar / bStdSrc) * b
# 加入源圖像對應通道的均值
l += lMeanSrc
a += aMeanSrc
b += bMeanSrc
# 如果像素強度超出範圍,則将像素強度剪裁為[0, 255]範圍
l = np.clip(l, 0, 255)
a = np.clip(a, 0, 255)
b = np.clip(b, 0, 255)
# 将通道合并在一起并轉換回BGR顔色空間,確定確定使用 8 位無符号整數資料類型
transfer = cv2.merge([l, a, b])
transfer = cv2.cvtColor(transfer.astype("uint8"), cv2.COLOR_LAB2BGR)
# 傳回顔色遷移後的圖像
return transfer
def image_stats(image):
# 計算每個通道的均值和标準差
(l, a, b) = cv2.split(image)
(lMean, lStd) = (l.mean(), l.std())
(aMean, aStd) = (a.mean(), a.std())
(bMean, bStd) = (b.mean(), b.std())
# 傳回顔色統計資訊
return (lMean, lStd, aMean, aStd, bMean, bStd)
if __name__ == '__main__':
src = cv2.imread('./0.jpg')
target = cv2.imread('./2.jpg')
if src is None or target is None:
print('圖像加載失敗,請檢查圖檔路徑!')
else:
cv2.imshow('src',src)
cv2.imshow('target', target)
dst = color_transfer(src, target)
cv2.imshow('result', dst)
cv2.waitKey()
cv2.destroyAllWindows()
運作效果:
用PyQt5加個UI,選擇自己的圖檔進行測試:
處理前:
處理後:
含界面代碼背景回複:顔色遷移 即可擷取!