Ask Your Question
1

cvFindContours is faster than cv::findcontours

asked 2016-11-17 10:17:13 -0600

andreadc gravatar image

updated 2016-11-18 05:20:49 -0600

Hi, I'm using 2.4.13 opencv in a VS application and I have just updated source code changing old C functions with new C++ functions. In particular I have verified that cv::findcontours is slower than cvFindContours.

For example I have tried with that code:

for( i=0; i<10000; i++ ) {
    cvThreshold(gray, tmp, 225, 255, CV_THRESH_BINARY);
    cvFindContours(tmp, storage, &contours, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

    cvInitTreeNodeIterator(&iterator, contours, 2);
    while( src_cc= (CvSeq*)cvNextTreeNode(&iterator) ) {
        for( approxParam=1.5; approxParam<=10.0; approxParam+=0.5 )
            dst_cc = cvApproxPoly(src_cc, sizeof(CvContour), temp_storage, CV_POLY_APPROX_DP, approxParam);
    }
}

vs

for( i=0; i<10000; i++ )
{
    cv::threshold(mat_gray, mat_tmp, 225, 255, CV_THRESH_BINARY);
    cv::findContours(mat_tmp, mat_contours, hierarchy, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

    for( ic=0; ic<mat_contours.size(); ic++ ) {
        for( approxParam=1.5; approxParam<=10.0; approxParam+=0.5 )
            cv::approxPolyDP(mat_contours[ic], dst_contour, approxParam, true);
    }
}

C++ source has a RELEASE execution time nearly 1 second greater than C source. Is it possible? Is it only C++ overhead? I have used an opencv sample image (baboon.jpg) and C source needs thereabouts 4 seconds while C++ source 5 seconds

regards Andrea

edit retag flag offensive close merge delete

Comments

nice find, but please add test code to your question. so that other folks can try to reproduce it.

(also, just saying, - 2.4.8 is before-last-years-model (not really relevant any more))

berak gravatar imageberak ( 2016-11-17 10:22:58 -0600 )edit
1

I have checked it with a complex application, I need to isolate some code to post it. Let me try with 2.4.13 version, then I'll give you another feedback

andreadc gravatar imageandreadc ( 2016-11-17 10:29:11 -0600 )edit

Hi, I have just tried with 2.4.13 version but nothing changes. I have verified that isn't only cv::findcontours to slow down, but in general all c++ function are a little slower. For example after finding contours I use several cv::approxPolyDP to try other contours approximation and also them are slower.

How could attach a source code file I have used to test it? Anyway, doing 10000 cv::findcountours over a generic sample image and then running each contour several approximations take nearly 1 seconds more than doing it with C functions. Is it possible? Is it only C++ overhead?

andreadc gravatar imageandreadc ( 2016-11-18 04:57:13 -0600 )edit
1

After checking the source code I think it is because the cv::findContours not just calls cvFindContours, but after that it also copies the whole contour array from the C structure to a C++ array which has an additional overhead.

matman gravatar imagematman ( 2016-11-18 11:44:31 -0600 )edit

And also cv::approxPolyDP allocate each time a CvMemStorage. I think I need to upgrade to 3.0 version to solve that issue, am I wrong?

andreadc gravatar imageandreadc ( 2016-11-21 01:18:14 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
0

answered 2019-07-09 04:50:06 -0600

I am using 3.4.6 and cvFindContours is way faster than cv::findContours.

I checked the code on cv::fincContours and don't really understand where the time goes: On the c++ call I just measure the time of:

 cv::findContours(img1, contours, cv::RETR_CCOMP, cv::CHAIN_APPROX_SIMPLE);

For the c call I measure the time of cvFindContours and the copy of contours to a c++ vector of vectors:

IplImage * img_stub = cvCreateImageHeader(cvSize(img1.cols, img1.rows), 8, 1);
cvSetData(img_stub, img1.data, (int)img1.step);

CvMemStorage* storage = cvCreateMemStorage(0);
CvSeq* _contours = nullptr;
cvFindContours( img_stub, storage, &_contours, sizeof(CvContour), CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);

cv::Seq<CvSeq*> all_contours(cvTreeToNodeSeq( _contours, sizeof(CvSeq), storage ));
int i, total = (int)all_contours.size();
out.create(total, 1, 0, -1, true);
cv::SeqIterator<CvSeq*> it = all_contours.begin();
for( i = 0; i < total; i++, ++it )
{
    CvSeq* c = *it;
    ((CvContour*)c)->color = (int)i;
    out.create((int)c->total, 1, CV_32SC2, i, true);
    cv::Mat ci = out.getMat(i);
    CV_Assert( ci.isContinuous() );
    cvCvtSeqToArray(c, ci.ptr());
}

cvClearMemStorage( storage );
cvReleaseMemStorage(&storage);
cvReleaseImageHeader(&img_stub);

(I have copied the code from the cv::findContours implementation)

There is a big different between each calls:

cv::findContours : 25.6760 ms 
cv::findContours : 12.5560 ms 
cv::findContours : 12.4280 ms 
cv::findContours : 12.3370 ms 
cv::findContours : 13.2180 ms 
cv::findContours : 12.0600 ms 
cv::findContours : 12.7090 ms 
cv::findContours : 12.0270 ms 

cvFindContours : 4.9750 ms 
cvFindContours : 5.1180 ms 
cvFindContours : 4.9960 ms 
cvFindContours : 4.9750 ms 
cvFindContours : 5.4470 ms 
cvFindContours : 4.8460 ms 
cvFindContours : 5.1010 ms 
cvFindContours : 4.9200 ms

I ran the same code a few times with the same image.

Any idea why the difference?

edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-11-17 10:17:13 -0600

Seen: 3,319 times

Last updated: Nov 18 '16