diff --git a/doc/tutorials/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.markdown b/doc/tutorials/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.markdown index f2a511fc21..f37b81e060 100644 --- a/doc/tutorials/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.markdown +++ b/doc/tutorials/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.markdown @@ -153,7 +153,7 @@ The first thing is to declare a custom class that inherits from @ref cv::Paralle `virtual void operator ()(const cv::Range& range) const`. The range in the `operator ()` represents the subset of pixels that will be treated by an individual thread. -This splitting is done automatically to distribuate equally the computation load. We have to convert the pixel index coordinate +This splitting is done automatically to distribute equally the computation load. We have to convert the pixel index coordinate to a 2D `[row, col]` coordinate. Also note that we have to keep a reference on the mat image to be able to modify in-place the image. @@ -167,6 +167,11 @@ nstripes parameter in @ref cv::parallel_for_. For instance, if your processor ha or setting `nstripes=2` should be the same as by default it will use all the processor threads available but will split the workload only on two threads. +@note +C++ 11 standard allows to simplify the parallel implementation by get rid of the `ParallelMandelbrot` class and replacing it with lambda expression: + +@snippet how_to_use_OpenCV_parallel_for_.cpp mandelbrot-parallel-call-cxx11 + Results ----------- diff --git a/modules/core/include/opencv2/core/utility.hpp b/modules/core/include/opencv2/core/utility.hpp index 8a923c9f42..411fc013dc 100644 --- a/modules/core/include/opencv2/core/utility.hpp +++ b/modules/core/include/opencv2/core/utility.hpp @@ -56,6 +56,10 @@ #include "opencv2/core.hpp" #include +#if __cplusplus >= 201103L +#include +#endif + namespace cv { @@ -478,6 +482,28 @@ public: */ CV_EXPORTS void parallel_for_(const Range& range, const ParallelLoopBody& body, double nstripes=-1.); +#if __cplusplus >= 201103L +class ParallelLoopBodyLambdaWrapper : public ParallelLoopBody +{ +private: + std::function m_functor; +public: + ParallelLoopBodyLambdaWrapper(std::function functor) : + m_functor(functor) + { } + + virtual void operator() (const cv::Range& range) const + { + m_functor(range); + } +}; + +inline void parallel_for_(const Range& range, std::function functor, double nstripes=-1.) +{ + parallel_for_(range, ParallelLoopBodyLambdaWrapper(functor), nstripes); +} +#endif + /////////////////////////////// forEach method of cv::Mat //////////////////////////// template inline void Mat::forEach_impl(const Functor& operation) { diff --git a/samples/cpp/tutorial_code/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.cpp b/samples/cpp/tutorial_code/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.cpp index c661b919b3..59dcb69954 100644 --- a/samples/cpp/tutorial_code/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.cpp +++ b/samples/cpp/tutorial_code/core/how_to_use_OpenCV_parallel_for_/how_to_use_OpenCV_parallel_for_.cpp @@ -101,10 +101,35 @@ int main() //! [mandelbrot-transformation] double t1 = (double) getTickCount(); + + #if __cplusplus >= 201103L + + //! [mandelbrot-parallel-call-cxx11] + parallel_for_(Range(0, mandelbrotImg.rows*mandelbrotImg.cols), [&](const Range& range){ + for (int r = range.start; r < range.end; r++) + { + int i = r / mandelbrotImg.cols; + int j = r % mandelbrotImg.cols; + + float x0 = j / scaleX + x1; + float y0 = i / scaleY + y1; + + complex z0(x0, y0); + uchar value = (uchar) mandelbrotFormula(z0); + mandelbrotImg.ptr(i)[j] = value; + } + }); + //! [mandelbrot-parallel-call-cxx11] + + #else + //! [mandelbrot-parallel-call] ParallelMandelbrot parallelMandelbrot(mandelbrotImg, x1, y1, scaleX, scaleY); parallel_for_(Range(0, mandelbrotImg.rows*mandelbrotImg.cols), parallelMandelbrot); //! [mandelbrot-parallel-call] + + #endif + t1 = ((double) getTickCount() - t1) / getTickFrequency(); cout << "Parallel Mandelbrot: " << t1 << " s" << endl;