使用开放式CV的remap函数处理不同类型的源图像会给我带来一些有趣的结果。
以下类型可以正常工作: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,在循环中使用它们,然后完成remap函数。
这两种类型的错误是:
抛出'cv :: Exception'实例后调用terminate what():OpenCV(4.0.1-dev)/home/aljaz/opencv_build/opencv/modules/imgproc/src/imgwarp.cpp:1805:error:(-215:Assertion failed)ifunc!= 0 in function'remap '
答案 0 :(得分:2)
如果您查看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
};
因此,尽管最近邻插值允许使用带符号的char类型,但双线性插值并非如此。所有组合均未实现。
可以与OpenCV一起使用的IPP(用于图像处理的Intel库)不允许签名char操作:https://software.intel.com/en-us/ipp-dev-reference-remap。据我了解,英特尔在性能方面没有意义的情况下不提供此类实现(即,它们未提供将函数内部的8s转换为16s,计算某些内容并转换回8s的功能)。此外,支持数据类型,插值类型,通道数量的所有组合肯定需要做一些工作,因此专注于最常用的类型也很好。
如果您没有绝对需要使用整数的性能瓶颈,我建议将其转换为float。另外,对于整数,您还必须注意量化。
当您收到“断言”错误时,通常是因为您不符合预期/实现的输入数据类型或形状(图像大小/通道数)。
希望这会有所帮助!