Opencv並行訪問圖像像素

四種Opencv的元素訪問方式時間對比

  1. 指針訪問方式和 at 方式沒有多大差別
  2. 最快的訪問方式是使用 最新的 forEach 可以調用多核並行
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

#define OPENCV_ORIGINAL 0
#define OPENCV_BLOG 1




// Define a pixel 
typedef Point3_<uchar> Pixel;

// A complicated threshold is defined so 
// a non-trivial amount of computation 
// is done at each pixel. 
void complicatedThreshold(Pixel &pixel)
{
    if (pow(double(pixel.x) / 10, 2.5) > 100)
    {
        pixel.x = 255;
        pixel.y = 255;
        pixel.z = 255;
    }
    else
    {
        pixel.x = 0;
        pixel.y = 0;
        pixel.z = 0;
    }
}

int main()
{




#if OPENCV_ORIGINAL
    Mat image(1920, 1080, CV_8UC3);
    typedef cv::Point3_<uchar> Pixel;
    // first. raw pointer access.
    for (int r = 0; r < image.rows; ++r)
    {
        Pixel* ptr = image.ptr<Pixel>(r, 0);
        const Pixel* ptr_end = ptr + image.cols;
        for (; ptr != ptr_end; ++ptr)
        {
            ptr->x = 255;
        }
    }


    // Using MatIterator. (Simple but there are a Iterator's overhead)
    for (Pixel &p : cv::Mat_<Pixel>(image))
    {
        p.x = 255;
    }


    // Parallel execution with function object.
    struct Operator
    {
        void operator ()(Pixel &pixel, const int * position)
        {
            pixel.x = 255;
        }
    };
    image.forEach<Pixel>(Operator());


    // Parallel execution using C++11 lambda.
    image.forEach<Pixel>([](Pixel &p, const int * position) -> void
    {
        p.x = 255;
    });
#endif // OPENCV_ORIGINAL



    cv::Mat image = cv::imread("D:/testpic/1-1304031A126.jpg");

#if OPENCV_BLOG



    //1. 第一種訪問情況
    double t = (double)getTickCount();
    // Naive pixel access
    // Loop over all rows
    for (size_t i = 0; i < 10; i++)
    {
        for (int r = 0; r < image.rows; r++)
        {
            // Loop over all columns
            for (int c = 0; c < image.cols; c++)
            {
                // Obtain pixel at (r, c)
                Pixel pixel = image.at<Pixel>(r, c);
                // Apply complicatedTreshold
                complicatedThreshold(pixel);
                // Put result back
                image.at<Pixel>(r, c) = pixel;
            }
        }
    }   
    t = (double)getTickCount() - t;
    std::cout << "Naive pixel access time =  " << t*1000. / cv::getTickFrequency() << std::endl;


    //2. 第二種訪問情況
    t = (double)getTickCount();
    // Using pointer arithmetic
    // Get pointer to first pixel
    for (size_t i = 0; i < 10; i++)
    {
        Pixel* pixel = image.ptr<Pixel>(0, 0);

        // Mat objects created using the create method are stored
        // in one continous memory block.
        const Pixel* endPixel = pixel + image.cols * image.rows;
        // Loop over all pixels
        for (; pixel != endPixel; pixel++)
        {
            complicatedThreshold(*pixel);
        }
    }


    t = (double)getTickCount() - t;
    std::cout << "Using pointer arithmetic =  " << t*1000. / cv::getTickFrequency() << std::endl;



    //3. 第三種訪問情況
    t = (double)getTickCount();
    // Parallel execution with function object.
    struct Operator
    {
        void operator ()(Pixel &pixel, const int * position) const
        {
            // Perform a simple threshold operation
            complicatedThreshold(pixel);
        }
    };

    for (size_t i = 0; i < 10; i++)
    {
        // Call forEach
        image.forEach<Pixel>(Operator());
    }


    t = (double)getTickCount() - t;
    std::cout << "Parallel execution with function object. =  " << t*1000. / cv::getTickFrequency() << std::endl;




    //4. 第四種訪問情況
    //Some of you are looking at Method 3, shaking your head in disgust and shouting, “lambda, Lambda, LAMBDA!”
    t = (double)getTickCount();

    for (size_t i = 0; i < 10; i++)
    {
        image.forEach<Pixel>
            (
            [](Pixel &pixel, const int * position) -> void
        {
            complicatedThreshold(pixel);
        }
        );
    }


    t = (double)getTickCount() - t;
    std::cout << "lambda =  " << t*1000. / cv::getTickFrequency() << std::endl;





#endif // OPENCV_BLOG






    return system("pause");
}

這裏寫圖片描述



Reference

http://www.learnopencv.com/parallel-pixel-access-in-opencv-using-foreach/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章