Skip to content

cv::parallel_for_を使ってみる

atinfinity edited this page Jul 27, 2016 · 25 revisions

cv::parallel_for_を使ってみる

はじめに

OpenCVは以下の並列処理フレームワークを利用可能にするための共通APIとしてcv::parallel_for_を提供しています.
※どの並列処理フレームワークが使われるかはOpenCVのビルド設定で決まります.

  • Intel TBB
  • C=
  • OpenMP
  • GCD
  • Concurrency
  • pthread

OpenCVにて提供されるcv::parallel_for_を利用することで並列処理を行うコードを容易に実装できます.このページではサンプルコードを用いてcv::parallel_for_の利用方法を紹介します.

使い方

cv::parallel_for_の大まかな使い方は以下の通りです.

  1. cv::ParallelLoopBodyを継承したクラス,クラスメソッドを作成する
  2. cv::parallel_for_の第2引数に1.で作成したクラスメソッドを指定する

サンプルコード

cv::parallel_for_を使って二値化を行うサンプルです.

#include <opencv2/core.hpp>
#include <iostream>

// 自作二値化関数
void my_threshold
(
    const cv::Mat& src, cv::Mat& dst,
    double thresh, double max_value
)
{
    int x, y = 0;
    unsigned char intensity = 0;
    for (y = 0; y < src.rows; y++)
    {
        for (x = 0; x < src.cols; x++)
        {
            intensity = src.at<unsigned char>(y, x);
            if (intensity < (unsigned char)thresh)
            {
                dst.at<unsigned char>(y, x) = 0;
            }
            else
            {
                dst.at<unsigned char>(y, x) = (unsigned char)max_value;
            }
        }
    }
}

// cv::parallel_for_利用コード
class TestParallelLoopBody : public cv::ParallelLoopBody
{
private:
    cv::Mat _src;
    cv::Mat _dst;
    double _thresh;
    double _max_value;
public:
    TestParallelLoopBody
    (
        const cv::Mat& src, cv::Mat& dst,
        double thresh, double max_value
    )
    : _src(src), _dst(dst), _thresh(thresh), _max_value(max_value) { }
    void operator() (const cv::Range& range) const
    {
        int row0 = range.start;
        int row1 = range.end;
        cv::Mat srcStripe = _src.rowRange(row0, row1);
        cv::Mat dstStripe = _dst.rowRange(row0, row1);
        my_threshold(srcStripe, dstStripe, _thresh, _max_value);
    }
};

int main(int argc, char *argv[])
{
    cv::Mat src(cv::Size(5000, 5000), CV_8UC1, cv::Scalar(255));
    cv::Mat dst = cv::Mat::zeros(src.size(), src.type());
    double f = 1000.0f / cv::getTickFrequency();

    int64 start = cv::getTickCount();

    // 自作二値化関数の実行
    my_threshold(src, dst, 100, 255);

    int64 end = cv::getTickCount();
    std::cout << "my_threshold: " << 
        (end - start) * f << "[ms]" << std::endl;

    start = cv::getTickCount();

    // cv::parallel_for_を使って自作二値化関数を並列化
    cv::parallel_for_
    (
        cv::Range(0, dst.rows),
        TestParallelLoopBody(src, dst, 100, 255)
    );

    end = cv::getTickCount();
    std::cout << "my_threshold(parallel_for_): " 
        << (end - start) * f << "[ms]" << std::endl;

    return 0;
}

実行結果

my_threshold: 42.6608[ms]
my_threshold(parallel_for_): 9.04392[ms]

※実行環境によって結果は異なります.

備考

筆者はOpenCV 3.0.0で動作確認しました.


Menu

Computer Vision

GPGPU

AR

ROS

Docker

Jetson

ARM

プログラミング言語

開発環境

勉強会

Clone this wiki locally