从文件中并行读取图像

时间:2018-05-29 18:22:02

标签: c++ image opencv parallel-processing

我有这个功能从数据集读取负图像(约122000)

void load_images(const String & dirname, vector< Mat > & img_lst, bool showImages = false)
{
    vector< String > files;
    glob(dirname, files);

    for (size_t i = 0; i < files.size(); ++i)
    {
        Mat img = imread(files[i]); // preia imagine
        if (img.empty())            // treci peste daca este imagine invalida
        {
            cout << files[i] << " is invalid!" << endl;
            continue;
        }

        if (showImages)
        {
            imshow("image", img);
            waitKey(1);
        }
        img_lst.push_back(img);
    }
}

并且需要花费大量时间来处理,有时会被阻止。 如何优化它并使其并行?

2 个答案:

答案 0 :(得分:2)

我稍微改变了你的代码以使用OpenMP来并行加载 - 实际的更改是最小的 - 我只是在pragma循环之前放置了一个OpenMP for并且序列化了对图像矢量的访问权限向量不是线程安全的。

#include <iostream>
#include <vector>
#include <mutex>
#include <opencv2/opencv.hpp>

using namespace cv;
using namespace std;

void load_images(int start,int end){
   vector<Mat>img_lst;
   mutex mtx;

#pragma omp parallel for
   for(size_t i=start;i<=end;i++){
      char filename[16];
      sprintf(filename,"%d.jpg",i);
      Mat img = imread(filename);
      if (img.empty()){
         cerr << "ERROR: Failed to load " << filename << endl;
      }
      mtx.lock();
      img_lst.push_back(img);
      mtx.unlock();
   }
   mtx.lock();
   cout << "INFO: Loaded " << img_lst.size() << endl;
   mtx.unlock();
}

int
main(int argc,char*argv[])
{
    load_images(1,122000);
}

您可以像这样控制线程数:

export OMP_NUM_THREADS=2
time ./main

根据我使用的线程数量,加载122,000张图像的时间根据下表而变化:

Threads Time (s)
================
1       44
2       23
4       12.4
8       8.8

然后我决定,如果你这样做经常足以照顾,你可能会想要预先支付一小笔费用来进一步改善时间。因此,您可能希望将图像转换为更简单的读取格式(例如PNM),而不是执行所有CPU密集型代码来解压缩JPEG。因此,我使用 GNU Parallel 将所有JPEG图像转换为PNM,然后加载PNM图像:

所以看起来像:

seq 122000 | parallel convert {}.jpg {}.pnm

代码是:

...
...
#pragma omp parallel for
   for(size_t i=start;i<=end;i++){
      char filename[16];
      sprintf(filename,"%d.pnm",i);        <--- ONLY LINE CHANGED
      Mat img = imread(filename);
...
...

你可以看到时间相当短:

Nthreads Time(s)
================
1        7
2        4
4        2.5
8        3.2

enter image description here

要使用OpenMP进行编译,请使用:

g++ -fopenmp =O3 -march native ...

答案 1 :(得分:1)

你可以试试这个

PyQt

对它进行了简要测试,但它应该可以读取4个线程的图像。