【问题标题】:OpenCV cv::Mat set ifOpenCV cv::Mat 设置 if
【发布时间】:2014-06-27 16:58:14
【问题描述】:

如果满足某些条件,是否有一种简单的方法可以将 cv::Mat 中的所有值设置为给定值。例如,我有 CV_32FC1,我想将所有值设置为 0 到 20。在 MATLAB 中我会简单地这样做:

M(M == 0) = 20;

【问题讨论】:

    标签: opencv mat


    【解决方案1】:

    你可以使用

    cv::Mat mask = M == 0;
    M.setTo(0.5, mask);
    

    但是,它包括使用额外的内存来创建掩码,但它是使用 opencv API 的解决方案,因此可以应用于所有矩阵类型。如果您考虑性能问题,您始终可以直接参考 Mat::data 以针对具体矩阵类型优化此解决方案。

    【讨论】:

    • 这太强大了!通过使表达式的第二部分更复杂,它可以用于阈值等。在文档或教程中似乎不可能找到它。我们应该宣传这个帖子,让人们知道使用它!不幸的是,它似乎不适用于复合表达式 - 即这有效:cv::Mat newMask = mask <= 2; 但这不适用于cv::Mat newMask = mask > 2 && mask < 5;
    • @DavidDoria 现在我想到的只是使用两个额外的临时掩码,即 cv::Mat maskGreaterThan2 = M > 2; cv::Mat maskLessThan5 = M
    • @DavidDoria 试试这个:(mask > 2) & (mask < 5)
    【解决方案2】:

    这是look-up table 的经典案例。它快速、简单,并且可以同时重新映射多个值。

    【讨论】:

      【解决方案3】:

      感谢@marol 的 cmets,我选择了下面的实现。我正在使用 C++11 lambda 函数来确定需要更改哪些值。为了展示它的强大,我的条件是当值超出范围[MIN_VAL,MAX_VAL]时设置为DEFAULT_VAL

      #include <functional>
      
      #define MatType float
      #define MatCmpFunc std::function<bool(const MatType&)>
      .
      .
      .
      // function which accepts lambda function to condition values which need to
      // be changed
      void MatSetIf(cv::Mat& inputmat, const MatType& newval, MatCmpFunc func) {
        float* pmat = (float*)inputmat.data;
        // iterate and set only values which fulfill the criteria
        for (int idx = 0; idx < inputmat.total(); ++idx) {
          if (func(pmat[idx])) {
            pmat[idx] = newval;
          }
        }
      }
      .
      .
      .
      void main() {
        cv::Mat mymat(100,100,CV_32FC1);
        const float MIN_VAL = 10;
        const float MAX_VAL = 1000;
        const float DEFAULT_VAL = -1;
        .
        .
        .
        // declare lambda function which returns true when mat value out of range
        MatCmpFunc func = [&](const DepthMatType& val) -> bool {
          return (val < MIN_VAL || val > MAX_VAL) ? true : false;
        };
        // use lambda func above to set all out of range values to 50
        Mat32FSetIf(mymat, DEFAULT_VAL, func);
        .
        .
        .
      }
      

      【讨论】:

      • 这部分是我所说的直接 Mat::data 访问。在调试模式下使用 at() 肯定比 setTo() 慢,所以如果你决定使用这种解决方案并且你有特定的矩阵类型,我不建议制作通用模板函数,而不是直接操作的具体函数Mat::data(正如 opencv 文档所说,“在优化方面,没有什么能比 C 数组运算符 [] 更好”)
      • 谢谢@marol ...两个cmets都非常有帮助:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-04
      • 2014-03-06
      相关资源
      最近更新 更多