在 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
,因此 第一列中的系数 乘以第一个颜色分量(对于每个输出分量),并且 第一行 将输入像素的所有分量混合到输出像素的第一个 分量中。
在 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
,因此 第一列中的系数 乘以第一个颜色分量(对于每个输出分量),并且 第一行 将输入像素的所有分量混合到输出像素的第一个 分量中。