OpenCV使用ParallelLoopBody進行平行計算

mylaf發表於2020-12-09

環境:Windows 10 x64, VS2017 x64, OpenCV 4.3.0 x64

步驟:

1,宣告一個 ParallelLoopBody 的子類(取名為FillParallel),並實現其純虛擬函式 virtual void operator() (const Range& range) const的功能;

2,例項化子類(FillParallel)的物件(取名為 fill) ;

3,呼叫 cv::parallel_for_()方式進行平行計算。

詳細與程式碼:

step 1:

  // Step 1: 宣告 ParallelLoopBody 的一個子類,取名為 FillParallel (並行填充顏色)
  class FillParallel : public cv::ParallelLoopBody {
  public:
    // 通過建構函式進行填充引數(填充影像,填充區域,顏色等)的設定
    FillParallel(cv::Mat& image, const std::vector<cv::Rect>& rects, const std::vector<cv::Scalar>& colors) {
      _image = image;
      _rects = rects;
      _colors = colors;
    }

    // OpenCV 平行計算的內部呼叫介面約定
    // 【重點】實現此介面的功能
    virtual void operator() (const cv::Range& range) const {
      for (int i = range.start; i < range.end; ++i) {
        _image(_rects[i]).setTo(_colors[i]);
        printf("curr thread: %d, all %d.\r\n", cv::getThreadNum(), cv::getNumThreads());
      }
    }

    // 填充引數
  private:
    mutable cv::Mat          _image; // 此處關注 mutable 關鍵字
    std::vector<cv::Rect>    _rects;
    std::vector<cv::Scalar>  _colors;
  };

step 2:

    // Step 2: 例項化子類(FillParallel)的物件(取名為 fill) ;
    FillParallel fill(image, vec_rects, vec_colors);

step 3:

    // Step 3: 呼叫 cv::parallel_for_()方式進行平行計算。
    cv::parallel_for_(cv::Range(0, vec_rects.size()), fill);

完整程式碼;

// Mylaf 
#include <opencv2/opencv.hpp>
#include <opencv2/xfeatures2d.hpp>

#define TICK2TIME(tick) ((tick)*1000/cv::getTickFrequency())

bool SubRectangle(std::vector<cv::Rect> & rects,
  int width, int height,      // 大區域的尺寸
  int subwidth, int subheight,   // 子區域的尺寸
  int stepx, int stepy,       // 子區域間的步進
  int offx = 0, int offy = 0) {  // 子區域左上點偏移
  //
  for (int y = 0; y < height; y += stepy) {
    for (int x = 0; x < width; x += stepx) {
      rects.emplace_back(x + offx, y + offy, subwidth, subheight);

      if (x + subwidth >= width) break;
    }
    if (y + subheight >= height) break;
  }
  return true;
}

// Step 1: 宣告 ParallelLoopBody 的一個子類,取名為 FillParallel (並行填充顏色)
class FillParallel : public cv::ParallelLoopBody {
public:
  // 通過建構函式進行填充引數(填充影像,填充區域,顏色等)的設定
  FillParallel(cv::Mat& image, const std::vector<cv::Rect>& rects, const std::vector<cv::Scalar>& colors) {
    _image = image;
    _rects = rects;
    _colors = colors;
  }

  // OpenCV 平行計算的內部呼叫介面約定
  // 【重點】實現此介面的功能
  // 本填充的range=填充區域(顏色)的個數, 見Step 3中的range
  virtual void operator() (const cv::Range& range) const {
    for (int i = range.start; i < range.end; ++i) {
      _image(_rects[i]).setTo(_colors[i]);
      printf("curr thread: %d, all %d.\r\n", cv::getThreadNum(), cv::getNumThreads());
    }
  }

  // 填充引數
private:
  mutable cv::Mat          _image; // 此處關注 mutable 關鍵字
  std::vector<cv::Rect>    _rects;
  std::vector<cv::Scalar>  _colors;
};

void Test0001() {
  cv::Mat image = cv::Mat::zeros(8000, 12000, CV_8UC3);

  // 劃分不同的填充區域和顏色
  std::vector<cv::Rect> vec_rects;
  ocv_geom::SubRectangle(vec_rects,
    image.cols, image.rows,
    100, 100, 100, 100);
  std::cout << "subrect size=" << vec_rects.size() << std::endl;

  std::vector<cv::Scalar> vec_colors(vec_rects.size());
  for (int i = 0; i < vec_colors.size(); ++i) {
    vec_colors[i][0] = (32 * i) & 0xFF;
    vec_colors[i][1] = (48 * (i + 1)) & 0xFF;
    vec_colors[i][2] = 255 - MIN(vec_colors[i][0], vec_colors[i][1]);
  }

  // Step 2: 例項化子類(FillParallel)的物件(取名為 fill) ;
  FillParallel fill(image, vec_rects, vec_colors);

  double tick = cv::getTickCount();
  for (int i = 0; i < vec_colors.size(); ++i) {
    image(vec_rects[i]).setTo(vec_colors[i]);
  }
  tick = cv::getTickCount() - tick;
  std::cout << "0 time: " << TICK2TIME(tick) << " ms." << std::endl;

  tick = cv::getTickCount();
  // Step 3: 呼叫 cv::parallel_for_()方式進行平行計算。
  cv::parallel_for_(cv::Range(0, vec_rects.size()), fill);
  tick = cv::getTickCount() - tick;
  std::cout << "1 time: " << TICK2TIME(tick) << " ms." << std::endl;

  cv::imwrite("image.png", image);
}

// mylaf unit test entry-point
int main(int argc, const char* argv[]) {

  Test0001();

  //
  return 0;
}

圖片:

Mylaf 

廈門 2020-12-09 0020

相關文章