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

学习《OpenCV应用开发:入门、进阶与工程化实践》一书

做真正的OpenCV开发者,从入门到入职,一步到位!

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官方教程上那样的明显加速的结果,因为教程上没有说明它到底是用了那个并行加速框架得到的。有时候 “尽信书不如无书”

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

好书推荐

《OpenCV应用开发:入门、进阶与工程化实践》全书共计16个章节,重点聚焦OpenCV开发常用模块详解与工程化开发实践,提升OpenCV应用开发能力,助力读者成为OpenCV开发者,同时包含深度学习模型训练与部署加速等知识,帮助OpenCV开发者进一步拓展技能地图,满足工业项目落地所需技能提升。购买请点链接:
《OpenCV4 应用开发-入门、进阶与工程化实践》

学习课程有专属答疑群,负责贴身答疑解惑

读者专属QQ群 :657875553
进群暗号:OpenCV4读者

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

gloomyfish

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值