将开放 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”实例后调用终止 什么():OpenCV(4.0.1-dev)/home/aljaz/opencv_build/opencv/modules/imgproc/src/imgwarp.cpp:1805:错误:(-215:断言失败)ifunc!= 0函数'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
};
因此,尽管最近邻插值允许使用有符号字符类型,但双线性插值却并非如此。所有组合均未实现。
可与 OpenCV 一起使用的 IPP(英特尔图像处理库)也不允许有符号字符操作:https://software.intel.com/en-us/ipp-dev-reference-remap 。根据我的理解,当英特尔在性能方面没有意义时,不会提供此类实现(即,他们不提供在函数内部将 8 秒转换为 16 秒、计算某些内容并在 8 秒内转换回来的函数)。此外,支持数据类型、插值类型、 channel 数的所有组合肯定需要一些工作,因此专注于最常用的类型也可以。
如果您没有绝对需要使用整数的性能瓶颈,我建议转换为 float 。对于整数,您还必须注意量化。
当您收到“断言”错误时,通常是因为您不符合预期/实现的输入数据类型或形状(图像大小/ channel 数)。
希望这有帮助!
关于c++ - 使用 open CV 的重映射函数和 CV_8SC1 类型的源图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55157623/