《Color Transfer between Images》提出了一个非常经典的色彩迁移算法,用来将目标图像的色彩空间迁移到原图像上。
Python的实现代码见:https://github.com/ReBoRn8888/colorTransfer-python
 出发点
- RGB三通道具有很强的相关性,改一个通道就得跟着改另外两个通道,否则图像会失真。
- 在RGB空间改变色彩有困难,因此考虑寻找一个各通道互不相关的色彩空间,lαβ空间就是个不错的选择。
- 在lαβ空间下,改变任何一个通道都不会影响其他通道,从而避免了像改变RGB通道时会导致的失真情况。
- l:亮度,α:黄蓝通道,β:红绿通道。
 算法流程
将RGB空间转换为lαβ空间需要经过一个中间转换过程,即LMS空间,算法的整体流程如下:
RGB⇒LMS⇒log10(LMS)⇒lαβ⇒ 在 lαβ 空间下进行色彩变换 ⇒LMS⇒10LMS⇒RGB
 1、RGB ⇒ LMS
通过以下矩阵运算将RGB色彩空间转换为LMS色彩空间
![]()
| 12
 3
 4
 5
 6
 7
 8
 
 | def RGB2LMS(RGB):RGB2LMSMatrix = np.array([[0.3811, 0.5783, 0.0402], [0.1967, 0.7244, 0.0782], [0.0241, 0.1288, 0.8444]]).astype('float32')
 L = (RGB2LMSMatrix[0]*RGB).sum(2)
 M = (RGB2LMSMatrix[1]*RGB).sum(2)
 S = (RGB2LMSMatrix[2]*RGB).sum(2)
 LMS = cv2.merge([L, M, S])
 LMS[np.where(LMS == 0)] = 1
 return LMS
 
 | 
 2、对LMS空间取以10为底的对数
 3、LMS ⇒ lαβ
通过以下矩阵运算将LMS色彩空间转换为lαβ色彩空间
![]()
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | def LMS2lab(LMS):a = [[1/np.sqrt(3), 0, 0], [0, 1/np.sqrt(6), 0], [0, 0, 1/np.sqrt(2)]]
 b = [[1, 1, 1], [1, 1, -2], [1, -1, 0]]
 c = np.matmul(a, b)
 ll = (c[0]*LMS).sum(2)
 aa = (c[1]*LMS).sum(2)
 bb = (c[2]*LMS).sum(2)
 lab = cv2.merge([ll, aa, bb])
 return lab
 
 | 
 4、在lαβ空间下进行色彩变换
- 求出原图像src在lαβ空间下三通道各自的均值srcMean和标准差srcStd
- 求出目标图像tar在lαβ空间下三通道各自的均值tarMean和标准差tarStd
- 将原图像减去它本身的均值,再除以它本身的标准差:res=srcStdsrc−srcMean
- 乘以目标图像的标准差,再加上目标图像的均值即可:res=res∗tarStd+tarMean
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | def transfer(src, tar):srcMean = np.mean(src, axis=(0, 1))
 srcStd = np.std(src, axis=(0, 1))
 tarMean = np.mean(tar, axis=(0, 1))
 tarStd = np.std(tar, axis=(0, 1))
 
 res = src - srcMean
 res /= srcStd
 res *= tarStd
 res += tarMean
 return res
 
 | 
 5、将经过色彩变换后的图像转回到LMS空间
通过以下矩阵运算将 lαβ 色彩空间转换为 LMS 色彩空间
![]()
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | def lab2LMS(lab):a = [[1, 1, 1], [1, 1, -1], [1, -2, 0]]
 b = [[1/np.sqrt(3), 0, 0], [0, 1/np.sqrt(6), 0], [0, 0, 1/np.sqrt(2)]]
 c = np.matmul(a, b)
 L = (c[0]*lab).sum(2)
 M = (c[1]*lab).sum(2)
 S = (c[2]*lab).sum(2)
 LMS = cv2.merge([L, M, S])
 return LMS
 
 | 
 6、对LMS空间计算10的指数(即还原第二步的操作)
 7、LMS ⇒ RGB
通过以下矩阵运算将 LMS 色彩空间转换为 RGB 色彩空间
![]()
| 12
 3
 4
 5
 6
 7
 8
 
 | def LMS2RGB(LMS):LMS2RGBMatrix = np.array([[4.4679, -3.5873, 0.1193], [-1.2186, 2.3809, -0.1624], [0.0497, -0.2439, 1.2045]]).astype('float32')
 R = (LMS2RGBMatrix[0]*LMS).sum(2)
 G = (LMS2RGBMatrix[1]*LMS).sum(2)
 B = (LMS2RGBMatrix[2]*LMS).sum(2)
 RGB = cv2.merge([R, G, B])
 RGB = np.clip(RGB, 0, 1)
 return RGB
 
 | 
 算法结果演示
![]()
![]()