Ask Your Question

Revision history [back]

click to hide/show revision 1
initial version

Why is thresholding so slow?

I am creating a mask from an image with the size: 2000x640, and I'm running this code on a modern powerfull laptop.

I have made a function which is suppose to create binary mask from my input image, the code is quite simple and shown below:

However, when running the code it seems like doing a simple threshold takes a very long time - almost half a second.

ms_allocation: 0.001

ms_converted: 0.001

ms_thresholding: 0.383

ms_median_blur: 0.001

ms_copy_mask: 0

ms_locate_contour: 0.067

This looked very odd, so I implemented my own thresholding which ran in a few ms. However, not suddenly the median_blur became equally slow.

I then completely removed the thresholding part of the code and got this performance result

ms_allocation: 0.0008

ms_converted: 0.002

ms_thresholding: 0.000

ms_median_blur: 0.424

ms_copy_mask: 0

ms_locate_contour: 0.106

Can someone help me understand what is going on here? Why is the first call to openCV so slow, and can I prevent it somehow?

I would really prefer is this code could run in less than 0.1 s, which I think it totally reasonable.

void calculateMask(Mat & pSrc, Mat & pDst)
{

    auto ms_alloc_start = getTickCount();

    // Allocate, just to be sure it's done in advance.
    Mat mask = Mat::zeros(pSrc.size(), CV_8U);
    Mat sharp = Mat::zeros(pSrc.size(), CV_8U);
    Mat filled_mask = Mat::zeros(pSrc.size(), CV_8U);;
    Mat masks = Mat::zeros(pSrc.size(), CV_8U);;

    auto ms_alloc_end = getTickCount();
    auto ms_convert_start = getTickCount();

    pSrc.convertTo(sharp, CV_8U);

    auto ms_convert_end = getTickCount();
    auto ms_threshold_start = getTickCount();

    //threshold(sharp, mask, 20, 255, THRESH_BINARY);

    auto ms_threshold_end = getTickCount();
    auto ms_median_start = getTickCount();

    medianBlur(mask, filled_mask, 5);

    auto ms_median_end = getTickCount();
    auto ms_copy_start = getTickCount();

    filled_mask.copyTo(masks);

    auto ms_copy_end = getTickCount();

    auto ms_find_contour_start = getTickCount();

    locateLargestContour(masks, pDst);

    auto ms_find_contour_end = getTickCount();

    cout << "\n\n\tms_allocation: " << to_string((ms_alloc_end - ms_alloc_start) / getTickFrequency()) << "\n";
    cout << "\tms_converted: " << to_string((ms_convert_end - ms_convert_start) / getTickFrequency()) << "\n";
    cout << "\tms_thresholding: " << to_string((ms_threshold_end - ms_threshold_start)/ getTickFrequency()) << "\n";
    cout << "\tms_median_blur: " << to_string((ms_median_end - ms_median_start) / getTickFrequency()) << "\n";
    cout << "\tms_copy_mask: " << to_string((ms_copy_end - ms_copy_start) / getTickFrequency()) << "\n";
    cout << "\tms_locate_contour: " << to_string((ms_find_contour_end - ms_find_contour_start) / getTickFrequency()) << "\n";
}

Why is thresholding the first openCV API call so slow?

I am creating a mask from an image with the size: 2000x640, and I'm running this code on a modern powerfull laptop.

I have made a function which is suppose to create binary mask from my input image, the code is quite simple and shown below:

However, when running the code it seems like doing a simple threshold takes a very long time - almost half a second.

ms_allocation: 0.001

ms_converted: 0.001

ms_thresholding: 0.383

ms_median_blur: 0.001

ms_copy_mask: 0

ms_locate_contour: 0.067

This looked very odd, so I implemented my own thresholding which ran in a few ms. However, not suddenly the median_blur became equally slow.

I then completely removed the thresholding part of the code and got this performance result

ms_allocation: 0.0008

ms_converted: 0.002

ms_thresholding: 0.000

ms_median_blur: 0.424

ms_copy_mask: 0

ms_locate_contour: 0.106

Can someone help me understand what is going on here? Why is the first call to openCV so slow, and can I prevent it somehow?

I would really prefer is this code could run in less than 0.1 s, which I think it totally reasonable.

void calculateMask(Mat & pSrc, Mat & pDst)
{

    auto ms_alloc_start = getTickCount();

    // Allocate, just to be sure it's done in advance.
    Mat mask = Mat::zeros(pSrc.size(), CV_8U);
    Mat sharp = Mat::zeros(pSrc.size(), CV_8U);
    Mat filled_mask = Mat::zeros(pSrc.size(), CV_8U);;
    Mat masks = Mat::zeros(pSrc.size(), CV_8U);;

    auto ms_alloc_end = getTickCount();
    auto ms_convert_start = getTickCount();

    pSrc.convertTo(sharp, CV_8U);

    auto ms_convert_end = getTickCount();
    auto ms_threshold_start = getTickCount();

    //threshold(sharp, mask, 20, 255, THRESH_BINARY);

    auto ms_threshold_end = getTickCount();
    auto ms_median_start = getTickCount();

    medianBlur(mask, filled_mask, 5);

    auto ms_median_end = getTickCount();
    auto ms_copy_start = getTickCount();

    filled_mask.copyTo(masks);

    auto ms_copy_end = getTickCount();

    auto ms_find_contour_start = getTickCount();

    locateLargestContour(masks, pDst);

    auto ms_find_contour_end = getTickCount();

    cout << "\n\n\tms_allocation: " << to_string((ms_alloc_end - ms_alloc_start) / getTickFrequency()) << "\n";
    cout << "\tms_converted: " << to_string((ms_convert_end - ms_convert_start) / getTickFrequency()) << "\n";
    cout << "\tms_thresholding: " << to_string((ms_threshold_end - ms_threshold_start)/ getTickFrequency()) << "\n";
    cout << "\tms_median_blur: " << to_string((ms_median_end - ms_median_start) / getTickFrequency()) << "\n";
    cout << "\tms_copy_mask: " << to_string((ms_copy_end - ms_copy_start) / getTickFrequency()) << "\n";
    cout << "\tms_locate_contour: " << to_string((ms_find_contour_end - ms_find_contour_start) / getTickFrequency()) << "\n";
}