有没有直接的方法来创建一个掩码,其中cv::Mat_<double>
中的值与NAN进行比较?
cv::Mat_<real> mat = ...
cv::Mat_<uchar> mask = (mat == NAN);
无效,因为f == NAN
始终为false,即使f
已分配NAN
也是如此。对于矩阵来说似乎没有isnan()
的重载。
答案 0 :(得分:7)
如用户pSoLT所述,如果要确定哪些值为NaN
,只需将矩阵与自身进行比较即可。对于那些不相等的元素,这些元素将被视为NaN
by the standard definition。您可以使用该逻辑创建新的掩码:
cv::Mat mask = cv::Mat(mat != mat);
mat
这里的矩阵包含NaN
个值,mask
将是CV_8UC1
(即uchar
)类型矩阵,每个元素都是{ {1}}如果值为0xFF
,则为NaN
。
OpenCV论坛上的这篇文章也可以提供帮助:http://answers.opencv.org/question/2221/create-a-mask-for-nan-cells/
答案 1 :(得分:2)
我将这个答案发布给那些正在寻找如何从矩阵中过滤出nan
的人的参考。
尽管这可能不是您问题的精确答案,但是如果您想过滤掉那些nan
索引,那么有一种快速简便的方法。
在我的情况下,我有一个zero by zero division
,在我的nan
矩阵中以float
结尾。要将那些nan
设置为另一个值(在我的情况下为0
),可以使用以下方法:
cv::patchNaNs(mat, 0.0);
此方法查找nan
索引并将其替换为给定值。
答案 2 :(得分:1)
如果您想测试NaN
的值,只需将其与自身进行比较即可。根据标准NaN
不等于任何其他数字,包括其自身(fValue != fValue)
应该适用于NaN。
答案 3 :(得分:0)
根据github issue,一种解决方法是使用255 - (mat == mat)
代替mat != mat
(这通常应该可以工作,但是目前是一个错误)。
rayryeng's double-patch approach更强大,但带来了明显的性能缺陷。
下面是一个最小的工作示例:
#include <iostream>
#include <string>
#include <opencv2/opencv.hpp>
cv::Mat1b is_nan(cv::Mat mat)
{
return 255 - (mat == mat);
}
int main()
{
cv::Mat mat(5, 7, CV_32FC1);
cv::randu(mat, cv::Scalar(-1), cv::Scalar(1));
mat.at<float>(0,0) = std::nan("");
mat.at<float>(4,5) = std::nan("");
std::cout << mat << std::endl;
std::cout << is_nan(mat) << std::endl;
return 0;
}
输出
[nan, -0.60148162, -0.19788112, 0.62877017, -0.12573405, -0.5024206, 0.54621011;
0.52418745, -0.38441104, 0.40486339, -0.043105587, 0.58438003, -0.82831377, -0.8498795;
-0.67315322, -0.40044156, 0.81130785, 0.41937166, -0.70057499, 0.53087986, -0.75143719;
-0.9925428, 0.10302717, 0.99639863, -0.68201572, -0.6776439, -0.92362136, -0.14827734;
0.69225526, 0.77520895, -0.47057521, -0.4584339, 0.9053328, nan, 0.62043273]
[255, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 255, 0]