将 Open CV 的重映射功能与 CV_8SC1 类型的源图像一起使用

Using open CV's remap function with a source image of a type CV_8SC1

对不同类型的源图像使用 open CV 的重映射功能给了我一些有趣的结果。

以下类型按预期工作:CV_8UC1、CV_16UC1、CV_16SC1、CV_32FC1、CV_64FC1。

给我错误的两种类型是:CV_8SC1、CV_32SC1。

有趣的是 CV_16SC1 在工作,而 CV_8SC1 没有。

有人知道为什么会这样吗?

这是我使用的代码:

cv::Mat remapX, remapY;
remapX.create(output_cv_mat.rows, output_cv_mat.cols, CV_32FC1);
remapY.create(output_cv_mat.rows, output_cv_mat.cols, CV_32FC1);

for(int x = 0; x < remapX.cols; x++) //Column iteration
{ 
    for(int y = 0; y < remapX.rows; y++) //Row iteration
    {                                   
        remapX.at<float>(y, x) = (float)(x);
        remapY.at<float>(y, x) = (float)(remapX.rows - y);
    }
}

cv::remap(source_cv_mat, output_cv_mat, remapX, remapY, cv::INTER_LINEAR, cv::BORDER_CONSTANT, cv::Scalar(0, 0, 0));

代码使用源 cv::Mat(我正在尝试的类型)和输出 cv::Mat。我创建了映射 X 和 Y,在 for 循环中使用它们,然后使用重映射函数完成。

我收到的这两种类型的错误是:

在抛出 'cv::Exception' 的实例后调用终止 what(): OpenCV(4.0.1-dev) /home/aljaz/opencv_build/opencv/modules/imgproc/src/imgwarp.cpp:1805: 错误: (-215:断言失败) ifunc != 0 in function 'remap'

如果您查看 cv::remap 的代码,您可以看到以下对与插值类型兼容的数据类型的检查:

    static RemapNNFunc nn_tab[] =
    {
        remapNearest<uchar>, remapNearest<schar>, remapNearest<ushort>, remapNearest<short>,
        remapNearest<int>, remapNearest<float>, remapNearest<double>, 0
    };

    static RemapFunc linear_tab[] =
    {
        remapBilinear<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, RemapVec_8u, short>, 0,
        remapBilinear<Cast<float, ushort>, RemapNoVec, float>,
        remapBilinear<Cast<float, short>, RemapNoVec, float>, 0,
        remapBilinear<Cast<float, float>, RemapNoVec, float>,
        remapBilinear<Cast<double, double>, RemapNoVec, float>, 0
    };

因此,尽管最近邻插值允许使用 signed char 类型,但双线性插值并非如此。所有组合均未实现。

可与 OpenCV 一起使用的 IPP(英特尔图像处理库)也不允许符号字符操作:https://software.intel.com/en-us/ipp-dev-reference-remap。据我了解,英特尔在性能方面没有意义时不提供此类实现(即,它们不提供在函数内部将 8 转换为 16、计算某些内容并在 8 中转换回的函数)。此外,支持数据类型、插值类型、通道数的所有组合肯定需要一些工作,因此专注于最常用的类型也是可以的。

如果您没有绝对需要使用整数的性能瓶颈,我建议您转换为浮点数。同样对于整数,您必须注意量化。

当您遇到 "assert" 错误时,通常是因为您不符合 expected/implemented 输入数据类型或形状(图像 size/number 通道)。

希望对您有所帮助!