天天看點

使用Python,OpenCV實作圖像之間超快速的顔色轉移

圖像之間超快速的顔色轉移

    • 1. 效果圖
    • 2. 步驟
    • 3. 改進算法的方法
    • 4. 源碼
    • 參考
目标:源圖像與目标圖像,轉移源圖像的色彩空間到目标圖像,生成一張新的圖像;

有關如何在兩個圖像之間轉移顔色,有倆種方式,

  • (1)基于直方圖的方法,該方法旨在平衡三種“類型”的顔色:相等,過多和不足。 該方法獲得了良好的結果-但以速度為代價。使用此算法将要求您對源圖像中的每個像素執行查找,這将随着圖像尺寸的增加而變得非常昂貴。
  • (2)僅使用圖像通道的均值和标準差的顔色轉移算法。沒有複雜的代碼。沒有計算直方圖。隻是簡單的統計……這種方法甚至可以輕松處理巨大的圖像。

1. 效果圖

輸入源圖像和目标圖像。源圖像包含期待目标圖像模仿的色彩空間。

在下圖中,左側的藍色夢幻水母是我的源,中間的紅色水母是我的目标圖像,而右側的圖像是将左圖色彩應用于目标圖像的色彩空間。

2019年中秋節青島海洋世界裡拍的水母圖,把夢幻的藍色(左圖)應用于目标烈焰紅(中間圖),合成獨特的水母“紅”(右邊圖);

使用Python,OpenCV實作圖像之間超快速的顔色轉移

水母2:左圖的色彩應用于目标圖夢幻的水母圖,得到右邊的結果圖(有點像拍出來的骨片的色彩);

使用Python,OpenCV實作圖像之間超快速的顔色轉移

水母轉換圖3:左圖 + 中間圖 = 右圖(結果是比較仙的淺紫色~~~)

使用Python,OpenCV實作圖像之間超快速的顔色轉移

2. 步驟

  1. 輸入來源和目标圖像。源圖像包含您希望目标圖像模仿的色彩空間。在此頁頂部的圖中,左側的水母圖像是我的源,中間的圖像是我的目标,而右側的圖像是應用到目标的源的色彩空間。
  2. 将源圖像和目标圖像都轉換為L * a * b *顔色空間。 L * a * b *顔色空間模拟了感覺均勻性,其中顔色值的微小變化也應該在顔色重要性上産生相對相等的變化。與标準RGB顔色空間相比,L * a * b *顔色空間在模仿人類如何解釋顔色方面做得好得多,并且您将看到,它在顔色轉移方面效果很好。
  3. 分割源和目标圖像的顔色通道值。
  4. 為源圖像和目标圖像計算每個L * a * b *通道的平均值和标準差。
  5. 從目标通道中減去目标圖像的L * a * b *通道的平均值。
  6. 按目标的标準偏差除以源的标準偏差再乘以目标通道的比例來縮放目标通道。
  7. 為源圖像添加L * a * b 通道的均值。
  8. 裁剪掉[0,255]範圍之外的所有值。
  9. 将通道顔色值合并在一起。
  10. 從L * a * b 空間轉換回RGB顔色空間。

3. 改進算法的方法

該算法非常快,有一個缺點——它依賴于全局顔色統計資訊,是以像素強度值相似的大區域會極大地影響平均值(進而影響總體顔色傳遞)。

為了解決這個問題,有兩個解決方案:

  • (1)計算要模拟顔色的較小關注區域(ROI)中的源圖像的均值和标準偏差,而不是使用整個圖像。采用這種方法将使您的均值和标準差更好地表示您要使用的色彩空間。
  • (2)将k均值應用于兩個圖像。可以在L * a * b *顔色空間中的每個圖像的像素強度上聚類,然後使用歐幾裡德距離确定最相似的兩個圖像之間的質心。

    然後,僅計算每個區域内的統計資訊。同樣,這将使您的平均數和标準差更具“局部”效果,并有助于減輕全局統計資料的過分表達問題。當然,缺點是這種方法的速度要慢得多,因為添加了昂貴的聚類步驟。

4. 源碼

用到了 color_transfer子產品的方法,可通過 pip install color_transfer 安裝
# USAGE
# python example.py --source images/01.jpg --target images/02.jpg -o images/01_02.jpg

import argparse

import cv2
# 導入必要的類
from color_transfer import color_transfer


def show_image(title, image, width=300):
    # resize圖像以使得圖像具有固定的大小,以便整個螢幕都可以展示
    r = width / float(image.shape[1])
    dim = (width, int(image.shape[0] * r))
    resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)

    # 展示縮放後的圖像
    cv2.imshow(title, resized)

# 建構指令行參數及解析
# --source 源圖像
# --target 目标圖像
# --output 是否輸出轉換後的圖像,此為其路徑
ap = argparse.ArgumentParser()
ap.add_argument("-s", "--source", required=True,
                help="Path to the source image")
ap.add_argument("-t", "--target", required=True,
                help="Path to the target image")
ap.add_argument("-o", "--output", help="Path to the output image (optional)")
args = vars(ap.parse_args())

# 加載圖像
source = cv2.imread(args["source"])
target = cv2.imread(args["target"])

# 轉移源圖像的色彩配置設定 到 目标圖像
transfer = color_transfer(source, target)

# 檢測是否儲存輸出圖像
if args["output"] is not None:
    cv2.imwrite(args["output"], transfer)

# 展示圖像
show_image("Source", source)
show_image("Target", target)
show_image("Transfer", transfer)
cv2.waitKey(0)
           

參考

  • https://www.pyimagesearch.com/2014/06/30/super-fast-color-transfer-images/

繼續閱讀