计算机视觉颜色校正方法
- 调色和色彩矫正之间的区别
- 直方图均衡化
- 原理
- 实现代码
- CCM颜色校正矩阵
- 原理
- 深度学习Deep_White_Balance
- 什么是sRGB图像
- 问题描述:
- 方法概述:
- 模型架构:
- 训练损失函数
- 实现
- 快速开始
调色和色彩矫正之间的区别
调色是指通过调整图像的色调、饱和度和亮度等参数来改变图像的整体颜色效果。这种调整可以是主观的,根据个人或艺术家的审美意图进行。调色通常用于图像处理、摄影和电影制作等领域,以达到特定的视觉效果或情感表达。
色彩校正(Color Correction)则是指对图像的色彩进行修正,使其符合真实场景中的颜色。色彩校正旨在消除图像中的色偏、色差或色均衡问题,以还原真实的色彩。它是通过校准图像的颜色分布或调整色彩通道来实现的。
总结来说,调色更侧重于艺术性和主观性,通过调整参数来改变图像的整体色调和效果。而色彩校正更侧重于修正图像中的色彩问题,使其更准确地反映真实场景中的颜色。
下文主要是为大家介绍几种方法以及对应实现代码(已跑通),:直方图方法、色彩矩阵CCM方法、深度学习方法方法
直方图均衡化
当拍摄图像的环境较暗时,图像往往会显得较为暗淡。我们可以通过直方图处理方法对图像的颜色进行校正,以改善图像的亮度和对比度。直方图处理方法是一种基于像素强度值的统计分析方法,通过重新分配图像的强度值来实现校正。
在这种方法中,我们首先观察图像的直方图,特别是像素强度值的概率密度函数(PDF)。夜间拍摄的图像往往呈现出在较低光谱上偏斜的分布。这意味着图像中的强度值倾向于集中在较暗的区域。
为了校正这种偏斜,我们的目标是将图像的累积分布函数(CDF)拉伸到一个新的目标CDF。这样一来,原本位于较低光谱的强度值将被映射到较高的强度值,从而提亮图像。我们通过对图像的像素值进行变换来实现这个过程。
具体而言,直方图处理方法可以采用直方图均衡化或直方图规定化等技术。直方图均衡化通过重新分配像素强度值,增强图像的对比度。而直方图规定化则通过匹配图像的CDF与目标CDF来调整强度值分布。这些方法都利用了图像中强度值的统计信息,从而提高图像的视觉效果。
同理对于拍摄图像的环境较亮时,也是一个道理
原理
当进行直方图均衡化的图像处理时,我们将原始图像拆分成红、绿、蓝三个通道(RGB)。然后对每个通道进行以下计算流程:
- 计算每个通道的直方图:使用灰度图像的直方图计算方法,统计每个像素值的频率。
- 计算累积分布函数(CDF):将直方图进行累加,得到每个像素值的累积频率。
- 标准化CDF:将CDF值除以图像的总像素数,将其范围限制在0到1之间。
- 构建目标CDF:创建一个线性分布的CDF,其中像素值从0到255均匀分布。
- 映射像素值:对于每个像素值,根据当前通道的标准化CDF和目标CDF,找到最接近的像素值并进行映射。
- 重建通道:将经过映射后的通道重新组合。
- 重复步骤2到6,对于剩下的两个通道进行处理。
将三个处理后的通道堆叠到一起,得到最终的处理图像。
实现代码
导入库
import numpy as np
import matplotlib.pyplot as plt
from skimage.io import imread, imshow
from skimage import img_as_ubyte, img_as_float
from skimage.color import rgb2gray
from skimage.exposure import histogram, cumulative_distribution
from scipy.stats import norm, cauchy, logistic
meimei = imread('meimei.jpg')
meimei_gray = rgb2gray(meimei)
-
skimage.exposure.histogram(image, nbins=256):
- 该函数用于计算图像的直方图。
- 参数 image 是输入的图像数组。
- 参数 nbins 是直方图的 bin 数量,默认为 256。
- 返回值是一个包含两个数组的元组 (hist, bin_centers),其中 hist 是长度为 nbins 的数组,表示每个 bin 中的像素数量,bin_centers 是对应的 bin 中心值。
-
skimage.exposure.cumulative_distribution(image, nbins=256):
- 该函数用于计算图像的累积分布函数(CDF)。
- 参数和返回值同 skimage.exposure.histogram 函数相同。
- 返回的 CDF 数组表示图像中小于或等于对应像素值的像素所占的比例。
我们先看下这个妹妹的真实CDF和目标CDF的对比
image_intensity = img_as_ubyte(meimei_gray)
freq, bins = cumulative_distribution(image_intensity)
target_bins = np.arange(256)
target_freq = np.linspace(0, 1, 256)
new_vals = np.interp(freq, target_freq, target_bins)
fig, ax = plt.subplots(1,2, figsize=(15,5))
ax[0].step(bins, freq, c='b', label='Actual CDF')
ax[0].plot(target_bins, target_freq, c='r', label='Target CDF')
ax[0].legend()
ax[0].set_title('Grayscale: Actual vs. Target Cumulative Distribution')
ax[1].imshow(new_vals[image_intensity.clip(0, len(new_vals)-1)].astype(np.uint8),
cmap='gray')
ax[1].set_title('Corrected Image in Grayscale');
分通道实现CDF转化
def linear_distribution(image, channel):
image_intensity = img_as_ubyte(image[:,:,channel])
print(len(image_intensity))
freq, bins = cumulative_distribution(image_intensity)
target_bins = np.arange(255)
target_freq = np.linspace(0, 1, len(target_bins))
new_vals = np.interp(freq, target_freq, target_bins)
print(len(new_vals))
return new_vals[image_intensity.clip(0,len(new_vals)-1)].astype(np.uint8)
red_channel = linear_distribution(meimei, 0)
green_channel = linear_distribution(meimei, 1)
blue_channel = linear_distribution(meimei, 2)
fig, ax = plt.subplots(1,2, figsize=(15,5))
ax[0].imshow(meimei);
ax[0].set_title('Original Image')
ax[1].imshow(np.dstack([red_channel, green_channel, blue_channel]));
ax[1].set_title('Transformed Image');
CCM颜色校正矩阵
CCM(Color Correction Matrix,颜色校正矩阵)是一种用于图像颜色校正的方法。它通过建立输入图像的颜色空间与目标颜色空间之间的映射关系,实现对图像颜色的校正和调整。CCM方法可以校正图像中的色偏、色彩失真和色彩不一致等问题,以获得更准确和自然的色彩表现。
CCM的基本原理是建立输入图像的颜色空间与目标颜色空间之间的映射关系。通常,CCM使用一个矩阵来表示这种映射关系。矩阵的每个元素表示输入颜色通道与目标颜色通道之间的权重关系。通过将输入图像的每个像素值与CCM矩阵相乘,可以得到校正后的颜色值。这样,输入图像的颜色将根据预先定义的目标颜色进行调整,以实现颜色的校正和调整。
原理
CCM方法的计算流程如下:
- 收集参考图像和参考数据:
使用彩色测试图表,例如X-Rite Colorchecker,其中包含多个色块以代表不同的颜色。
参考数据可以是标准参考值、使用光谱仪测量得到的值,或者是从“黄金标准”图像中提取的Lab*值。
- 图像预处理:
线性化处理:由于CCM的计算需要线性的R、G、B值,因此需要对图像进行适当的线性化处理,以确保输入数据是线性表示的。
饱和度处理:根据需要,可能需要对图像的饱和度进行调整,以控制颜色的鲜艳度或减少颜色失真。
- CCM计算方法:
多项式拟合法:通过对原始图像数据和参考数据进行多项式拟合,计算得到CCM的系数。拟合的目标是使拟合结果与参考数据之间的差异最小化。
三维查找表(3D-LUT)法:将颜色空间划分为离散的网格,并在每个网格点上定义一个CCM。通过对原始图像中的像素进行插值,确定其所在网格,并使用相应的CCM进行校正。
- 优化和评估:
目标函数选择:选择适当的目标函数来评估CCM的校正效果。常用的目标函数包括均方根误差(RMSE)和颜色差异度量(如ΔE 2000)。目标函数的选择取决于具体的应用需求。
非线性优化算法:使用适当的优化算法(如梯度下降法、Levenberg-Marquardt算法等)来寻找最小化目标函数的解,即找到使得CCM能够最好地将原始图像校正为参考数据的参数。
- 评估和调整
对计算得到的CCM进行评估,可以使用其他测试图像或验证数据集来验证校正效果。
根据评估结果,可能需要进行进一步的调整和优化,以获得更好的校正结果。
当计算CCM时,涉及到以下几个公式的计算:
- 彩色图像表示
彩色图像可以表示为一个 m × n × 3 的数组,其中 m 表示图像的高度,n 表示图像的宽度,3 表示颜色通道(R、G、B)。假设原始图像的像素数据被表示为 input_img。
- 线性化处理
对于每个像素 i,首先需要进行线性化处理,将非线性的原始像素值转换为线性表示。线性化后的像素值用 linear_img 表示。具体的线性化处理公式如下:
这里将原始像素值除以 255 是为了将像素值归一化到 [0, 1] 的范围内。
- CCM计算
CCM 是一个 3×3 或 4×3 的矩阵,用来将原始图像的颜色校正为目标颜色。在计算 CCM 之前,需要定义参考数据,可以是标准参考值、光谱仪测量值或从“黄金标准”图像中提取的 Lab* 值。
多项式拟合法:
使用多项式拟合法计算 CCM,将线性化后的输入图像 linear_img 和参考数据进行拟合。假设 CCM 为一个 3×3 矩阵,表示为 ccm,则拟合的过程可以表示为以下公式:
详细资料可以参考链接:https://www.imatest.com/support/docs/23-1/colormatrix/
深度学习Deep_White_Balance
论文地址:https://openaccess.thecvf.com/content_CVPR_2020/papers/Afifi_Deep_White-Balance_Editing_CVPR_2020_paper.pdf
项目地址:https://github.com/mahmoudnafifi/Deep_White_Balance
什么是sRGB图像
sRGB(standard Red Green Blue)是由Microsoft影像巨擘共同开发的一种彩色语言协议,它提供了一种标准方法来定义色彩,让显示、打印和扫描等各种计算机外部设备和应用软件对于色彩有一个共通的语言。
白平衡(White Balance,简称WB)是一项重要的图像处理任务,旨在确保不同照明条件下拍摄的图像中的颜色保持一致。然而,传统的白平衡编辑方法在纠正错误的白平衡设置时面临一些挑战,特别是由于相机综合信号处理器(ISP)的非线性渲染效果。为了解决这一问题,我们引入了一种名为"Deep White-Balance Editing"的深度学习方法。
Deep White-Balance Editing通过训练端到端的深度神经网络(DNN)模型,实现了对sRGB图像进行真实的白平衡编辑。相较于传统的基于k最近邻(KNN)的方法,我们的DNN模型不仅在纠正错误的白平衡设置方面更准确,还允许用户自由编辑图像的白平衡,调整到其他照明条件下。
该方法基于一个单编码器网络和三个解码器网络构成。其中,编码器网络用于提取图像特征,而解码器网络针对三种白平衡设置进行学习:正确的自动白平衡(AWB)设置、室内照明设置和室外照明设置。第一个解码器允许对错误白平衡的图像进行编辑,实现后期白平衡校正的目标。而室内和室外解码器则提供了多种不同白平衡效果的融合输出,为调整图像的美学白平衡属性提供了灵活性。
问题描述:
Deep White-Balance Editing是一种用于编辑图像颜色的方法。给定一个通过未知相机ISP和任意白平衡设置 W B ( i n ) WB^{(in)} WB(in)生成的sRGB图像 W B ( i n ) WB^{(in)} WB(in),我们的目标是将其编辑成具有目标白平衡设置 W B ( t ) WB^{(t)} WB(t)的外观。
I W B ( t ) = G ( F ( I W B ( i n ) ) ) I_{WB^{(t)}}=G(F(I_{WB^{(in)}})) IWB(t)=G(F(IWB(in)))
方法概述:
Deep White-Balance Editing方法旨在建立一个编码器-解码器模型,将输入图像转换为具有不同白平衡设置的输出图像。该方法通过分析图像处理链中的函数G和F的协作方式来实现目标图像的生成。函数F将输入图像转换为中间表示(即具有当前WB(in)设置的原始RGB图像),而函数G接受这个中间表示,并使用目标WB设置将其渲染为sRGB颜色空间编码的最终图像。
为了实现不同白平衡设置的目标定位,Deep White-Balance Editing采用了多解码器架构。每个解码器负责生成具有不同白平衡设置的输出图像。本方法选择了三种不同的白平衡设置:AWB(自动白平衡,表示捕获图像场景的正确照明)、Tungsten/Incandescent(白炽灯,表示室内照明的白平衡)和Shade(阴影,表示室外照明的白平衡)。这些解码器分别命名为gA、gT和gS,并通过独立的解码器实现了对应于这三种白平衡设置的输出图像的生成。
模型架构:
Deep White-Balance Editing采用了U-Net架构,并在编码器和解码器之间使用了多尺度的跳跃连接。整个架构包括两个主要单元:一个4级编码器单元和三个4级解码器单元。编码器负责提取输入图像的多尺度潜在表示,而解码器则根据特定的白平衡设置生成输出图像。在编码器和解码器的不同级别,使用了转置卷积层和具有不同通道数的卷积层,以实现特征的传递和信息的重建。
训练损失函数
模型方法中,使用L1范数损失函数来衡量重建图像与真实图像之间的差异。损失计算的具体步骤如下:
对于每个训练图像和对应的目标白平衡设置(正确AWB、Shade WB和Incandescent WB),从训练图像中随机选择四个大小为128×128的图像块,分别作为输入图像和对应的目标图像。
将输入图像通过编码器网络进行编码,得到特征表示。
将特征表示通过解码器网络分别生成AWB、Shade WB和Incandescent WB三个目标图像的重建结果。
对于每个解码器生成的重建图像和对应的目标图像,计算它们之间的像素级差异,即L1范数损失。这可以通过对每个像素进行绝对值差的累加求和来实现。
将三个解码器生成的重建图像与目标图像的L1损失进行累加,得到总体损失。
具体而言,损失计算公式如下:
L = ∑ i ∑ p = 1 3 h w ∣ P W B ( i ) ( p ) − C W B ( i ) ( p ) ∣ L = \sum_i\sum_{p=1}^{3hw}|P_{WB^{(i)}}(p)-C_{WB^{(i)}}(p)| L=i∑p=1∑3hw∣PWB(i)(p)−CWB(i)(p)∣
其中,L表示总体损失, i ∈ A , T , S i \in {A, T, S} i∈A,T,S 是目标白平衡设置(AWB、Shade WB和Incandescent WB)的索引,p表示训练图像和目标图像的像素索引。
P
W
B
(
i
)
(
p
)
P_{WB^{(i)}}(p)
PWB(i)(p)表示解码器生成的重建图像中的像素值
C
W
B
(
i
)
(
p
)
C_{WB^{(i)}}(p)
CWB(i)(p)表示对应的目标图像中的像素值。
对所有像素进行累加求和,得到每个目标图像与对应重建图像的L1损失,然后对三个目标图像的损失进行累加,得到总体损失。
这种损失计算方式能够使模型学习到与目标图像尽可能接近的重建结果,从而实现准确的白平衡编辑。通过优化这个损失函数,模型能够逐渐提高对不同白平衡设置下图像处理的准确性。
实现
这个项目旨在提供一种深度学习方法,用于进行图像的白平衡编辑。下面是使用该项目的简要介绍和操作指南:
环境要求:
Python 3.6
PyTorch(已测试版本为1.2.0和1.5.0)
torchvision(已测试版本为0.4.0和0.6.0)
cudatoolkit
tensorboard(可选)
numpy
Pillow
future
tqdm
matplotlib
scipy
scikit-learn
请注意,代码可能适用于其他版本的库。
快速开始
示例:
- 运行 demo_single_image.py 来处理单个图像。例如,应用AWB和不同的WB设置:python demo_single_image.py --input_image …/example_images/00.jpg --output_image …/result_images --show。这个示例将保存输出图像到 …/result_images 目录,并输出以下结果图像:
- 运行 demo_images.py 来处理图像目录。例如:python demo_images.py --input_dir …/example_images/ --output_image …/result_images --task AWB。可用的任务包括 AWB、all 和 editing。你也可以在 demo_single_image.py 示例中指定任务。
训练代码:
- 运行 training.py 开始训练。在运行代码之前,请调整训练图像目录。
例如:CUDA_VISIBLE_DEVICE=0 python train.py --training_dir …/dataset/ --fold 0 --epochs 500 --learning-rate-drop-period 50 --num_training_images 0。在这个示例中,fold = 0 和 num_training_images = 0 表示训练将使用所有的训练数据,而不进行交叉验证。如果你想限制训练图像的数量为 n 张图像,请将 num_training_images 设置为 n。如果你想进行 3 折交叉验证,请使用 fold = testing_fold。代码将在剩余的折中进行训练,并保留选择的折用于测试。
其他有用的选项包括:–patches-per-image(选择每个图像的随机补丁数量)、–learning-rate-drop-period 和 –learning-rate-drop-factor(控制学习率的衰减周期和因子),以及 –patch-size(设置训练补丁的大小)。你可以使用 –load 选项从训练检查点 .pth 文件中继续训练。
如果你的机器上安装了 TensorBoard,可以在开始训练后运行 tensorboard --logdir ./runs 来查看训练进展并可视化输入/输出补丁的样本。
这个项目提供了示例代码和训练代码,使你能够快速上手并开始进行白平衡编辑任务。你可以根据自己的需求和数据集进行相应的调整和训练代码提供了灵活的选项,允许你根据自己的需求进行调整。你可以指定训练图像的目录,并选择使用的训练数据数量、训练周期、学习率衰减周期和因子,以及训练补丁的大小。如果你已经有了之前的训练检查点文件,还可以通过使用 --load 选项来从检查点文件中继续训练。
另外,如果你在机器上安装了TensorBoard,你可以在训练过程中运行 tensorboard --logdir ./runs 来可视化训练的进展情况,并查看输入/输出补丁的样本。这可以帮助你更好地理解模型的性能和训练效果。