OpenCV C++多线程

5

我有一个opencv图像处理函数,被调用了4次,分别对应4个不同的Mat对象。

void processBinary(Mat& binaryMat) {
    //image processing
}

我希望您能将其多线程化,以便所有4个方法调用同时完成,但主线程要等待每个线程完成后再继续执行。
例如:
int main() {

    Mat m1, m2, m3, m4;

    //perform each of these methods simultaneously, but have main thread wait for all processBinary() calls to finish
    processBinary(m1);
    processBinary(m2);
    processBinary(m3);
    processsBinary(m4);
}

我希望能够调用processBinary()方法多次,并且保持与仅调用一次相同的效率。我查阅了多线程资料,但对于调用线程、加入线程和分离线程还有些困惑。我认为我需要实例化每个线程并在每个线程上调用join()方法,以便主线程等待每个线程执行完毕,但是执行时间并没有显著增加。可以有人解释一下如何开启多线程程序吗?谢谢!
编辑:我尝试过的内容如下:
//this does not significantly increase execution time. However, calling processBinary() only once does.4

    thread p1(&Detector::processBinary, *this, std::ref(m1));
    thread p2(&Detector::processBinary, *this, std::ref(m2));
    thread p3(&Detector::processBinary, *this, std::ref(m3));
    thread p4(&Detector::processBinary, *this, std::ref(m4));
    p1.join();
    p2.join();
    p3.join();
    p4.join();

1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - David Thomas
1
我不确定我理解了。我想将processBinary()并行化,因为它被调用了4次,而不是方法内部的代码。每个processBinary()都在不同的Mat对象上调用,因此它们彼此不依赖。 - Sumeet Batra
1
啊...你应该添加调用processBinary的代码。我们不需要了解processBinary的内部细节来帮助您并行调用它。 - David Thomas
抱歉我的解释不够清楚;我更新了问题,现在更有意义了 :) - Sumeet Batra
你尝试过什么?如果processBinary是一个纯函数,你可以只生成4个标准线程并将它们连接起来。 - E net4
我已经尝试过这个方法了。首先,对于每个processBinary()函数,创建一个线程,然后将每个线程join()起来。但是,性能并没有提高。我尝试只对一个Mat对象调用一次processBinary()函数,速度更快。 - Sumeet Batra
2个回答

6
实现这一目标的巧妙方式不是自己进行线程管理,而是使用提供微并行化的库。
OpenCV本身使用Intel Thread Building Blocks(TBB)来完成这个任务--在并行中运行循环。
在您的情况下,您的循环只有四次迭代。使用C++11,您可以使用lambda表达式轻松编写它。在您的示例中:
std::vector<cv::Mat> input = { m1, m2, m3, m4; }
tbb::parallel_for(size_t(0), input.size(), size_t(1), [=](size_t i) {
    processBinary(input[i]); 
});

对于这个例子,我从这里获取了代码。


1
我会尝试一下。我正在尝试通过ndk在Android上编译此代码,但它似乎无法识别<tbb/tbb.h>的头文件。我已经检查了sdk,libtbb.a在其中.....也许我的Android.mk没有设置正确。你是否了解这方面的知识?也许需要另外一个问题。 - Sumeet Batra
不知道。 - ypnos
@SumeetBatra Intel tbb 是一个独立的库。只有在使用 tbb 支持构建 Opencv 时,它才会被使用。否则,它将使用您编译它时使用的任何线程库,例如 pthreads、gdb 等。 - nnrales
@nnrales 那并不完全正确。TBB与pthreads的目的不同。GDB是何种线程库呢? - ypnos
@ypnos。哦,gcd。嗯...我认为tbb有助于创建线程池和分配工作。pthread也可以用于此。 - nnrales
1
@nnrales TBB 和 GCD 在 pthreads 的上一层。TBB 在适用时实际上使用 pthreads。如果您没有 TBB 或 GCD,就不能从 OpenCV 中期望相同的并行化效果。 - ypnos

0

如果您正在使用Python语言,则可以使用我的强大的开源多线程VidGear OpenCV包装Python库,该库可在GitHubPyPI上获得,以实现更高的FPS。

项目概述:

VidGear是OpenCV视频I/O模块的轻量级Python包装器,包含强大的多线程模块(gears),可在各种设备和平台上实现高速视频帧捕获功能。

特点:

与其他现有的多线程开源解决方案相比,其关键特点包括:

  • 多线程高速OpenCV视频帧捕获(结果为高FPS)

  • 灵活的直接控制视频流,易于操作

  • 轻量级

  • 内置强大的错误和帧同步处理

  • 多平台兼容性(也与树莓派相机兼容)

  • 完全支持网络视频流(包括Gstreamer原始视频捕获管道)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接