天天看點

基于OpenCV實作圖像間快速顔色遷移

作者: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()      

運作效果:

基于OpenCV實作圖像間快速顔色遷移
基于OpenCV實作圖像間快速顔色遷移

用PyQt5加個UI,選擇自己的圖檔進行測試:

處理前:

基于OpenCV實作圖像間快速顔色遷移

處理後:

基于OpenCV實作圖像間快速顔色遷移

含界面代碼背景回複:顔色遷移 即可擷取!