Матрица цветовой коррекции в XYZ / RGB не работает - PullRequest
1 голос
/ 06 февраля 2020

Я стремлюсь выполнить цветовую коррекцию на основе эталонного изображения с использованием цветовых карт. В качестве личной цели я пытаюсь исправить цвета изображения, которое я ранее изменил. Конечно, на диаграмме были затронуты те же слои:

Оригиналы:

enter image description here enter image description here

Изменено вручную:

enter image description here enter image description here

Я использую следующая функция, которую я сам написал для получения матрицы:

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 (только что прокомментированные функции преобразования цвета):

enter image description here

В XYZ (не обращайте внимания на изменение размера, это из-за меня ):

enter image description here

Теперь я задаю следующие вопросы:

  1. Нужно ли в этом случае инвертировать гамму? Если так, я делаю это правильно? Должен ли я реализовать LUT, который работает с другими типами данных, такими как np.float32?
  2. Вычитание среднего значения должно быть сделано в XYZ для цветового пространства BGR (случай 1 против случая 2)?
  3. Нужно ли рассматривать случай отражения (как в проблеме вращения твердого тела)?
  4. Требуется ли отсечение? И если да, это правильные значения и типы данных?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...