将 std::async 与接收 cv::OutputArray 的方法一起使用以分配它不起作用

Using std::async with a method receiving a cv::OutputArray in order to assign it doesn't work

我有以下功能:

void MyClass::myFunc(cv::OutputArray dst) const {
    cv::Mat result;
    ...
    dst.assign(result);
}

如果我运行这样:

cv::Mat result;
myFunc(result);
otherFunc(result);

它工作正常并且 otherFunc 收到 result 修改 myFunc

但是如果我这样使用 std::async

cv::Mat result;
auto resultFuture = std::async(&MyClass::myFunc, this, result);
resultFuture.wait();
otherFunc(result);

otherFunc 收到空 result。我做错了什么?

根本原因 是通过引用 (&) 将参数通过 std::async is problematic. You can read about it here: Passing arguments to std::async by reference fails 传递给 运行 的函数(在您的情况下没有编译错误,但 link 概括地解释了这个问题。

在您的情况下,您使用 cv::OutputArray,它在 opencv 中定义为参考类型:

typedef const _OutputArray& OutputArray;

我假设您需要引用语义,因为您希望 result 对象由 myFunc 更新。

解决办法就是用std::ref.
但是由于您传递的 result 对象是 cv::Mat,因此 myFunc 将收到 cv::Mat&.
更可取且更直接 我还设法使用 cv::OutputArray 生成了一个解决方案,但它需要一个丑陋的转换(除了 std::ref)。它在 MSVC 上运行良好,但我不确定它是否普遍有效。

下面是演示这两个选项的代码。如果可以的话,我建议使用第一种方法。您可以在 result 初始化后打印尺寸的地方调用 otherFunc(result);

#include <opencv2/core/core.hpp>
#include <future>
#include <iostream>

// Test using a cv::Mat &:
class MyClass1
{
    void myFunc(cv::Mat & dst) const
    {
        cv::Mat result(4, 3, CV_8UC1);
        result = 1; // ... initialize some values
        dst = result;   // instead of using cv::OutputArray::assign
    }
public:
    void test()
    {
        cv::Mat result;
        std::cout << "MyClass1: before: " << result.cols << " x " << result.rows << std::endl;
        auto resultFuture = std::async(&MyClass1::myFunc, this, std::ref(result));
        resultFuture.wait();
        // Here result will be properly set.
        std::cout << "MyClass1: after: " << result.cols << " x " << result.rows << std::endl;
    }
};

// Test using a cv::OutputArray:
class MyClass2
{
    void myFunc(cv::OutputArray dst) const
    {
        cv::Mat result(4, 3, CV_8UC1); 
        result = 1; // ... initialize some values
        dst.assign(result);
    }
public:
    void test()
    {
        cv::Mat result;
        std::cout << "MyClass2: before: " << result.cols << " x " << result.rows << std::endl;
        auto resultFuture = std::async(&MyClass2::myFunc, this, std::ref(static_cast<cv::OutputArray>(result)));
        resultFuture.wait();
        // Here result will be properly set.
        std::cout << "MyClass2: after: " << result.cols << " x " << result.rows << std::endl;
    }
};

int main()
{
    // Test receiving a cv::Mat&:
    MyClass1 m1;
    m1.test();
    // Test receiving a cv::OutputArray:
    MyClass2 m2;
    m2.test();
    return 0;
}