簡體   English   中英

為 NAN 值過濾 OpenCV Mat

[英]Filter OpenCV Mat for NAN values

有沒有一種直接的方法來創建一個掩碼,其中將cv::Mat_<double>中的值與 NAN 進行比較?

cv::Mat_<real> mat = ...
cv::Mat_<uchar> mask = (mat == NAN);

不起作用,因為f == NAN總是假的,即使f被分配了NAN 而且似乎沒有矩陣的isnan()過載。

正如用戶 pSoLT 所指出的,如果您想確定哪些值是NaN ,只需將矩陣與其自身進行比較。 對於那些不相等的元素, 標准定義將其視為NaN 您可以使用該邏輯創建一個新的掩碼:

cv::Mat mask = cv::Mat(mat != mat);

這里的mat將是一個包含NaN值的矩陣,而mask將是一個CV_8UC1 (即uchar )類型的矩陣,如果值為NaN ,則每個元素為0xFF ,否則為0x00

OpenCV 論壇上的這篇文章也可能有所幫助: http : //answers.opencv.org/question/2221/create-a-mask-for-nan-cells/


編輯(截至 2020 年 4 月 23 日)

正如評論以及這篇文章中的一個答案中提到的,上面的布爾表達式有問題,可能會導致不一致的行為。 這是由於 OpenCV 做出的某些優化決策。 請參閱此 Github 問題: https : //github.com/opencv/opencv/issues/16465

對此的解決方案是使用cv::patchNaNs()來解決此問題,它將NaN值轉換為特定數字。

要復制在問題中創建掩碼,請注意patchNaNs執行值的就地替換,因此您必須制作圖像的兩個副本,使用patchNaNsNaN值設置為每個圖像的不同值,然后檢查以查看兩個值同時在相同位置的出現。 換句話說:

cv::Mat mat1 = mat.clone();
cv::Mat mat2 = mat.clone();
cv::patchNaNs(mat1, 128);
cv::patchNaNs(mat2, 200);
cv::Mat mask = mat1 == 128 & mat2 == 200;

mask將為您提供此答案原始版本中的預期結果。

我發布這個答案是為了那些可能正在尋找如何從矩陣中過濾掉nan的人的參考。

雖然這可能不是您問題的准確答案,但如果您想過濾掉那些nan指數,有一種快速簡便的方法可以做到。

在我的例子中,我有一個zero by zero division ,最終在我的float矩陣中得到了nan s。 要將這些nan設置為另一個值(在我的情況下為0 ),可以使用以下方法:

cv::patchNaNs(mat, 0.0);

此方法查找並用給定值替換nan索引。

如果您想測試NaN值,只需將其與自身進行比較。 根據標准NaN不等於任何其他數字,包括它自己(fValue != fValue)對 NaN 應該是真的。

根據github issue ,解決方法是使用255 - (mat == mat)而不是mat != mat (這應該可以正常工作,但目前是一個錯誤)。 rayryeng 的雙補丁方法更健壯,但帶來了顯着的性能缺陷。

這是一個最小的工作示例:

#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]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM