Ask Your Question
2

Optimizing split/merge for clahe

asked 2016-11-02 17:11:06 -0600

jakir gravatar image

updated 2018-10-06 06:40:41 -0600

Hi,

I am trying to squeeze the last ms from a tracking loop. One of the time consuminig parts is doing adaptive contrast enhancement (clahe), which is a necessary part. The results are great, but I am wondering whether I could avoid some copying/splitting/merge or apply other optimizations.

Basically I do the following in tight loop:

cv::cvtColor(rgb, hsv, cv::COLOR_BGR2HSV);
std::vector<cv::Mat> hsvChannels;
cv::split(hsv, hsvChannels);
m_clahe->apply(hsvChannels[2], hsvChannels[2]); /* m_clahe constructed outside loop */
cv::merge(hsvChannels, hsvOut);
cv::cvtColor(hsvOut, rgbOut, cv::COLOR_HSV2BGR);

On the test machine, the above snippet takes about 8ms (on 1Mpix images), The actual clahe part takes only 1-2 ms.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
2

answered 2016-11-02 18:33:30 -0600

Tetragramm gravatar image

updated 2018-10-06 06:29:31 -0600

You can save quite a bit. First, get rid of the vector. Then, outside the loop, create a Mat for the V channel only.

Then use extractChannel and insertChannel to access the channel you're using. It only accesses the one channel, instead of all three like split does.

The reason you put the Mat outside the loop is to avoid reallocating it every pass through the loop. Right now you're allocating and deallocating three Mats every pass.

test code:

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    TickMeter tm;
    Ptr<CLAHE> clahe = createCLAHE();
    clahe->setClipLimit(4);

    vector<Mat> hsvChannels;
    Mat img, hsv1, hsv2, hsvChannels2, diff;
    img = imread("lena.jpg");

    cvtColor(img, hsv1, COLOR_BGR2HSV);
    cvtColor(img, hsv2, COLOR_BGR2HSV);

    tm.start();
    for (int i = 0; i < 1000; i++)
    {
        split(hsv2, hsvChannels);
        clahe->apply(hsvChannels[2], hsvChannels[2]);
        merge(hsvChannels, hsv2);
    }
    tm.stop();
    cout << tm << endl;

    tm.reset();
    tm.start();
    for (int i = 0; i < 1000; i++)
    {
        extractChannel(hsv1, hsvChannels2, 2);
        clahe->apply(hsvChannels2, hsvChannels2);
        insertChannel(hsvChannels2, hsv1, 2);
    }
    tm.stop();
    cout << tm;

    absdiff(hsv1, hsv2, diff);
    imshow("diff", diff*255);
    waitKey();
}
edit flag offensive delete link more

Comments

1

4.63716sec 3.80283sec in my PC,great work!

jsxyhelu gravatar imagejsxyhelu ( 2018-10-06 08:58:45 -0600 )edit

0.794282sec 0.743891sec :(

sturkmen gravatar imagesturkmen ( 2018-10-06 10:58:08 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2016-11-02 17:11:06 -0600

Seen: 2,069 times

Last updated: Oct 06 '18