首页 > 解决方案 > XYZ/RGB 中的颜色校正矩阵不起作用

问题描述

我的目标是使用颜色图表根据参考图像执行颜色校正。作为个人目标,我正在尝试纠正我之前修改过的图像的颜色。当然,图表也受到相同层的影响:

原件:

在此处输入图像描述 在此处输入图像描述

手动修改:

在此处输入图像描述 在此处输入图像描述

我正在使用我自己编写的以下函数来获取矩阵:

def _get_matrix_transformation(self,
                    observed_colors: np.ndarray,
                    reference_colors: np.ndarray):
    """
    Args:
        observed_colors: colors found in target chart
        reference_colors:  colors found on source/reference image

    Returns:
        Nothing.
    """
    # case 1
    observed_m = [observed_colors[..., i].mean() for i in range(observed_colors.shape[-1])]
    observed_colors = (observed_colors - observed_m).astype(np.float32)
    reference_m = [reference_colors[..., i].mean() for i in range(reference_colors.shape[-1])]
    reference_colors = (reference_colors - reference_m).astype(np.float32)

    # XYZ color conversion
    observed_XYZ = cv.cvtColor(observed_colors, cv.COLOR_BGR2XYZ)
    observed_XYZ = np.reshape(observed_colors, (observed_XYZ.shape[0] * observed_XYZ.shape[1],
                                                observed_XYZ.shape[2]))

    reference_XYZ = cv.cvtColor(reference_colors, cv.COLOR_BGR2XYZ)
    reference_XYZ = np.reshape(reference_colors, (reference_XYZ.shape[0] * reference_XYZ.shape[1],
                                                  reference_XYZ.shape[2]))

    # case 2
    # mean subtraction in order to use the covariance matrix
    # observed_m = [observed_XYZ[..., i].mean() for i in range(observed_XYZ.shape[-1])]
    # observed_XYZ = observed_XYZ - observed_m
    # reference_m = [reference_XYZ[..., i].mean() for i in range(reference_XYZ.shape[-1])]
    # reference_XYZ = reference_XYZ - reference_m

    # apply SVD
    H = np.dot(reference_XYZ.T, observed_XYZ)
    U, S, Vt = np.linalg.svd(H)

    # get transformation
    self._M = Vt.T * U.T

    # consider reflection case
    if np.linalg.det(self._M) < 0:
        Vt[2, :] *= -1              
        self._M = Vt.T * U.T

    return

我正在应用这样的更正:

def _apply_profile(self, img: np.ndarray) -> np.ndarray:
    """
    Args:
        img: image to be corrected.

    Returns:
        Corrected image.
    """
    # Revert gamma compression
    img = adjust_gamma(img, gamma=1/2.2)

    # Apply color correction
    corrected_img = cv.cvtColor(img.astype(np.float32), cv.COLOR_BGR2XYZ)
    corrected_img = corrected_img.reshape((corrected_img.shape[0]*corrected_img.shape[1], corrected_img.shape[2]))
    corrected_img = np.dot(self._M, corrected_img.T).T.reshape(img.shape)
    corrected_img = cv.cvtColor(corrected_img.astype(np.float32), cv.COLOR_XYZ2BGR)
    corrected_img  = np.clip(corrected_img, 0, 255)

    # Apply gamma
    corrected_img  = adjust_gamma(corrected_img.astype(np.uint8), gamma=2.2)

    return corrected_img

如果在 BGR 中完成转换,我目前得到的结果(只是注释了颜色转换函数):

在此处输入图像描述

在 XYZ 中(不要注意调整大小,那是因为我):

在此处输入图像描述

现在,我在问这些问题:

  1. 在这种情况下是否需要反转伽马?如果是这样,我做得对吗?我应该实现一个与其他数据类型(如 np.float32)一起使用的 LUT 吗?
  2. 应在 BGR 颜色空间的 XYZ 中减去平均值(案例 1 与案例 2)?
  3. 是否需要考虑反射情况(如刚体旋转问题)?
  4. 剪裁有必要吗?如果是这样,这些是正确的值和数据类型吗?

标签: pythonimagenumpyopencvimage-processing

解决方案


推荐阅读