1

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

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

Flutter - ColorFiltered Widget 的 ColorFilter Matrix (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);
}

结果

筛选结果比较

4

1 回答 1

1

彩色图像最常见的通道顺序是 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);

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

或者您也可以置换矩阵的,因此假定其输入为 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,因此第一列中的系数乘以第一个颜色分量(对于每个输出分量),第一行将输入像素的所有分量混合到输出像素的第一个分量中。

于 2021-09-01T11:20:46.853 回答