在 OpenCV (C++) 中应用 4x5 矩阵(而不是 4x4)进行变换

Apply a 4x5 Matrix (instead of 4x4) to Transform in OpenCV (C++)

在 Flutter 方面,我使用 4x5 矩阵将滤色器应用于图像(用于预览)。 通过 FFI,然后我使用 OpenCV 应用过滤器并对图像进行变换并保存新图像结果。
然而,结果总是与预览不同。

所以我想知道,如何使用 OpenCV 使用相同的矩阵 (4x5) 获得相同的结果?

Flutter - ColorFiltered Widget 的 ColorFilter 矩阵 (RGBA):

const ColorFilter _FILTER_2 = ColorFilter.matrix(<double>[
  0.9,  0.11, 0.11, 0.0,  0.0, //
  0.11, 0.7,  0.44, 0.0,  0.0, //
  0.22, 0.22, 0.9,  0.0,  0.0, //
  0.0,  0.0,  0.0,  1.0,  0.0
]);

C++ - 带矩阵的变换函数 (BGRA):

__attribute__((visibility("default"))) __attribute__((used)) void filter_2(char *inputImagePath, char *outputImagePath)
{
    Mat input = imread(inputImagePath);
    Mat output = input.clone();

    Mat filter = (Mat_<float>(4, 4) <<
                  0.22, 0.22, 0.9,  0.0,
                  0.11, 0.7,  0.44, 0.0,
                  0.9,  0.11, 0.11, 0.0,
                  0.0,  0.0,  0.0,  1.0);

    transform(output, input, filter);
    imwrite(outputImagePath, input);
}

结果

彩色图像最常见的通道顺序是 RGB。由于历史原因,OpenCV 的原生通道顺序是 BGR(相反)。

// maps RGB to RGB
Mat filter = (Mat_<float>(4, 4) <<
    0.9,  0.11, 0.11, 0.0
    0.11, 0.7,  0.44, 0.0
    0.22, 0.22, 0.9,  0.0
    0.0,  0.0,  0.0,  1.0);

用于将 RGB 映射到 RGB(有一些效果)的颜色矩阵在左上角的 3x3 部分有特定的值,它们以新的方式组合了 RGB 值。

为了解决 输出 数据中的 RGB/BGR 差异,我看到您排列了混合矩阵的 .该矩阵会正确地将 RGB 输入映射到 BGR 输出。

// maps RGB to BGR (rows permuted)
Mat filter = (Mat_<float>(4, 4) <<
    0.22, 0.22, 0.9,  0.0
    0.11, 0.7,  0.44, 0.0
    0.9,  0.11, 0.11, 0.0
    0.0,  0.0,  0.0,  1.0);

您可以使用该矩阵,但在 输入 (使用 COLOR_BGR2RGB)上使用 cvtColor,使其适合该矩阵。

或者您也可以置换矩阵的 ,因此假定其输入为 BGR:

// maps BGR to BGR (columns and rows permuted)
Mat filter = (Mat_<float>(4, 4) <<
    0.9,  0.22, 0.22, 0.0,
    0.44, 0.7,  0.11, 0.0,
    0.11, 0.11, 0.9,  0.0,
    0.0,  0.0,  0.0,  1.0);

在该矩阵的应用中,将输入像素的颜色通道作为列向量(并附加1以启用仿射变换)。然后将该向量乘以 M v,因此 第一列中的系数 乘以第一个颜色分量(对于每个输出分量),并且 第一行 将输入像素的所有分量混合到输出像素的第一个 分量中。