基于OpenCV实现图像间快速颜色迁移

2021-07-01 15:50:48 浏览数 (1)

作者: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代码:

代码语言:javascript复制
# 导入需要的包
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,选择自己的图片进行测试:

处理前:

处理后:

0 人点赞