【竹篮打水】OpenCV4.x 中新增并行代码执行演示

简介: 【竹篮打水】OpenCV4.x 中新增并行代码执行演示

OpenCV支持的并行框架

OpenCV从4.5版本开始,新增了并行代码执行支持,以常见的图像像素遍历卷积计算为例,演示OpenCV中卷积计算并行代码执行与非并行的卷积计算代码执行,同时对比时间消耗。OpenCV并行框架支持下面几种方法启用并行加速,分别是:

1. Intel TBB (第三方库,需显式启用)
2. C=并行C/C++编程语言扩展 (第三方库,需显式启用)
3. OpenMP (编译器集成, 需显式启用)
4. APPLE GCD (苹果系统自动使用)
5. Windows RT并发(Windows RT自动使用)
6. Windows并发(运行时部分, Windows,MSVC++ >= 10自动使用)
7. Pthreads

在VS IDE中开启OpenMP,只需要右键点击项目,从属性中

这样就可以开启并行加速。

卷积并行实现与时间比较

OpenCV支持两种方式的并行代码实现,分别是:

parallel_for_
ParallelLoopBody

以3x3卷积为例,原始的代码实现如下:

start = (double)cv::getTickCount();
for (int row = 0; row < rows; row++) {
  for (int col = 1; col < cols - 1; col++)
  {
    int sum = src.at<uchar>(row, col) + src.at<uchar>(row - 1, col) + src.at<uchar>(row + 1, col) +
      src.at<uchar>(row, col - 1) + src.at<uchar>(row - 1, col - 1) + src.at<uchar>(row + 1, col - 1) +
      src.at<uchar>(row, col + 1) + src.at<uchar>(row - 1, col + 1) + src.at<uchar>(row + 1, col + 1);
    int pv = sum / 9;
    dst.at<uchar>(row, col) = pv;
  }
}

parallel_for_ 3x3卷积的代码实现如下

double start = (double)cv::getTickCount();
parallel_for_(Range(0, rows * cols), [&](const Range &range)
{
  for (int r = range.start; r < range.end; r++)
  {
    int i = r / cols, j = r % cols;
    double value = 0;
    for (int k = -sz; k <= sz; k++)
    {
      uchar *sptr = src.ptr(i + sz + k);
      for (int l = -sz; l <= sz; l++)
      {
        value += kernel.ptr<double>(k + sz)[l + sz] * sptr[j + sz + l];
      }
    }
    dst.ptr(i)[j] = saturate_cast<uchar>(value);
  }
});
double time = (((double)cv::getTickCount() - start)) / cv::getTickFrequency();
std::cout << "parallel_for_conv3x3 execute time: " << time * 1000 << " ms" << std::endl;

ParallelLoopBody 3x3卷积的代码实现如下

class parallelConvolution : public ParallelLoopBody
{
private:
  Mat m_src, &m_dst;
  Mat m_kernel;
  int sz;
public:
  parallelConvolution(Mat src, Mat &dst, Mat kernel)
  : m_src(src), m_dst(dst), m_kernel(kernel)
  {
    sz = kernel.rows / 2;
  }
  virtual void operator()(const Range &range) const CV_OVERRIDE
  {
    for (int r = range.start; r < range.end; r++)
    {
      int i = r / m_src.cols, j = r % m_src.cols;
      double value = 0;
      for (int k = -sz; k <= sz; k++)
      {
        const uchar *sptr = m_src.ptr(i + sz + k);
        for (int l = -sz; l <= sz; l++)
        {
          value += m_kernel.ptr<double>(k + sz)[l + sz] * sptr[j + sz + l];
        }
      }
      m_dst.ptr(i)[j] = saturate_cast<uchar>(value);
    }
  }
};

调用方式如下:

start = (double)cv::getTickCount();
parallelConvolution obj(src, dst, kernel);
parallel_for_(Range(0, rows * cols), obj);
time = (((double)cv::getTickCount() - start)) / cv::getTickFrequency();
  std::cout << "parallelConvolution conv3x3 execute time: " << time * 1000 << " ms" << std::endl;

运行结果如下:

我晕倒,不是说并行加速了吗,可是我得不到OpenCV官方教程上那样的明显加速的结果,因为教程上没有说明它到底是用了那个并行加速框架得到的。有时候 “尽信书不如无书”

对此,我自己也有一些原因分析,但是更希望大家留言分析一下相关原因,为什么没有加速效果??

相关文章
|
1月前
|
传感器 C++ 计算机视觉
【opencv3】详述PnP测距完整流程(附C++代码)
【opencv3】详述PnP测距完整流程(附C++代码)
|
8月前
|
计算机视觉 Python
最快速度写出一个识别效果——OpenCV模板匹配(含代码)
最快速度写出一个识别效果——OpenCV模板匹配(含代码)
168 0
|
1月前
|
机器学习/深度学习 算法 数据可视化
计算机视觉+深度学习+机器学习+opencv+目标检测跟踪+一站式学习(代码+视频+PPT)-2
计算机视觉+深度学习+机器学习+opencv+目标检测跟踪+一站式学习(代码+视频+PPT)
123 0
|
18天前
|
算法 开发工具 计算机视觉
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
【零代码研发】OpenCV实验大师工作流引擎C++ SDK演示
20 1
|
1月前
|
机器学习/深度学习 Ubuntu Linux
计算机视觉+深度学习+机器学习+opencv+目标检测跟踪+一站式学习(代码+视频+PPT)-1
计算机视觉+深度学习+机器学习+opencv+目标检测跟踪+一站式学习(代码+视频+PPT)
88 1
|
12天前
|
监控 安全 计算机视觉
实战 | 18行代码轻松实现人脸实时检测【附完整代码与源码详解】Opencv、人脸检测
实战 | 18行代码轻松实现人脸实时检测【附完整代码与源码详解】Opencv、人脸检测
|
1月前
|
算法 API 计算机视觉
基于opencv的大米计数统计(详细处理流程+代码)
基于opencv的大米计数统计(详细处理流程+代码)
195 1
基于opencv的大米计数统计(详细处理流程+代码)
|
1月前
|
计算机视觉 索引 Python
分析”圣诞帽“代码,入门OpenCV
分析”圣诞帽“代码,入门OpenCV
分析”圣诞帽“代码,入门OpenCV
|
10月前
|
机器学习/深度学习 TensorFlow 算法框架/工具
计算机视觉实战(十七)OpenCV的DNN模型 (附完整代码)
计算机视觉实战(十七)OpenCV的DNN模型 (附完整代码)
198 0
|
11月前
|
机器学习/深度学习 人工智能 算法
Python+OpenCV 十几行代码模仿世界名画
我最近才发现在 OpenCV 的 Sample 代码中就有图像风格迁移的 Python 示例(原谅我的后知后觉),是基于 ECCV 2016 论文中的网络模型实现。所以,即使作为人工智能的菜鸟,也可以拿别人训练好的模型来玩一玩,体会下神经网络的奇妙。
Python+OpenCV 十几行代码模仿世界名画