sri
sri

Reputation: 227

Detecting the Image very very slow in device

I am using this SURF code to detect the logo in my image. It is working fine but it is very slow. Any idea about how can I optimize it?

- (void)findObject
{
    //NSLog(@"%@ %@", self, NSStringFromSelector(_cmd));

    width = 0;

    CvMemStorage* storage = cvCreateMemStorage(0);
    static CvScalar colors[] = 
    {
        {{0,0,255}},
        {{0,128,255}},
        {{0,255,255}},
        {{0,255,0}},
        {{255,128,0}},
        {{255,255,0}},
        {{255,0,0}},
        {{255,0,255}},
        {{255,255,255}}
    };

    if( !objectToFind || !image )
    {
        NSLog(@"Missing object or image");
        return;
    }

    CvSize objSize = cvGetSize(objectToFind);
    IplImage* object_color = cvCreateImage(objSize, 8, 3);
    cvCvtColor( objectToFind, object_color, CV_GRAY2BGR );

    CvSeq *objectKeypoints = 0, *objectDescriptors = 0;
    CvSeq *imageKeypoints = 0, *imageDescriptors = 0;
    int i;
    CvSURFParams params = cvSURFParams(500, 1);

    double tt = (double)cvGetTickCount();
    NSLog(@"Finding object descriptors");
    cvExtractSURF( objectToFind, 0, &objectKeypoints, &objectDescriptors, storage, params );

    NSLog(@"Object Descriptors: %d", objectDescriptors->total);
    cvExtractSURF( image, 0, &imageKeypoints, &imageDescriptors, storage, params );

    NSLog(@"Image Descriptors: %d", imageDescriptors->total);
    tt = (double)cvGetTickCount() - tt;

    NSLog(@"Extraction time = %gms", tt/(cvGetTickFrequency()*1000.));
    CvPoint src_corners[4] = {{0,0}, {objectToFind->width,0}, {objectToFind->width, objectToFind->height}, {0, objectToFind->height}};
    CvPoint dst_corners[4];
    CvSize size = cvSize(image->width > objectToFind->width ? image->width : objectToFind->width,
                         objectToFind->height+image->height);
    output = cvCreateImage(size,  8,  1 );
    cvSetImageROI( output, cvRect( 0, 0, objectToFind->width, objectToFind->height ) );
    //cvCopy( objectToFind, output );
    cvResetImageROI( output );
    cvSetImageROI( output, cvRect( 0, objectToFind->height, output->width, output->height ) );
    cvCopy( image, output );
    cvResetImageROI( output );

    NSLog(@"Locating Planar Object");
#ifdef USE_FLANN
    NSLog(@"Using approximate nearest neighbor search");
#endif
    if( locatePlanarObject( objectKeypoints, objectDescriptors, imageKeypoints,
                           imageDescriptors, src_corners, dst_corners ))
    {
        for( i = 0; i < 4; i++ )
        {
            CvPoint r1 = dst_corners[i%4];
            CvPoint r2 = dst_corners[(i+1)%4];
            //cvLine( output, cvPoint(r1.x, r1.y+objectToFind->height ),
                   //cvPoint(r2.x, r2.y+objectToFind->height ), colors[6] );
            cvLine( output, cvPoint(r1.x, r1.y+objectToFind->height ),
                   cvPoint(r2.x, r2.y+objectToFind->height ), colors[6],4 );
            //if(i==0)
                width = sqrt(((r1.x-r2.x)*(r1.x-r2.x))+((r1.y-r2.y)*(r1.y-r2.y)));
        }
    }
    vector<int> ptpairs;
    NSLog(@"finding Pairs");
#ifdef USE_FLANN
    flannFindPairs( objectKeypoints, objectDescriptors, imageKeypoints, imageDescriptors, ptpairs );
#else
    findPairs( objectKeypoints, objectDescriptors, imageKeypoints, imageDescriptors, ptpairs );
#endif
   /* for( i = 0; i < (int)ptpairs.size(); i += 2 )
    {
        CvSURFPoint* r1 = (CvSURFPoint*)cvGetSeqElem( objectKeypoints, ptpairs[i] );
        CvSURFPoint* r2 = (CvSURFPoint*)cvGetSeqElem( imageKeypoints, ptpairs[i+1] );
        cvLine( output, cvPointFrom32f(r1->pt),
               cvPoint(cvRound(r2->pt.x), cvRound(r2->pt.y+objectToFind->height)), colors[8] );
    }*/

    float dist = 629.0/width;
    [distanceLabel setText:[NSString stringWithFormat:@"%.2f",dist]];


    NSLog(@"Converting Output");
    UIImage *convertedOutput = [OpenCVUtilities UIImageFromGRAYIplImage:output];

    NSLog(@"Opening Stuff");
    [imageView setImage:convertedOutput];
    cvReleaseImage(&object_color);

    [activityView stopAnimating];

}

In the above code image is my original image and objectToFind is the logo which I want to detect.

Please let me know if my question is not clear.

Upvotes: 1

Views: 273

Answers (1)

Barney Szabolcs
Barney Szabolcs

Reputation: 12544

You need to use profiling to decide which part of your code is the slowest.
Since you are using XCode, you have a built-in profiler at hands reach:

  1. in he top-left corner you press-and-hold "Run" button and choose "Profile".
  2. click on Profile and and select Time Profiler.
  3. after a while you press "stop" in the profiler, and select "Hide Missing Symbols", "Hide System Libraries" and "Top Functions", deselect "Separate by Thread".
  4. Now look up function main and there is a hidden right arrow after it. Click on that arrow and you can see time in percent and call statistics by the calltree.

This is how you start.

In general I have the following suggestions without profiling:

  • Avoid creating new images and memory storages as much as you can. (You can pass images for temporary use to your function, and preserve those images outside so that you can reuse them later.)
  • scale down your image (and your logo) to role-out major parts of the image
  • use less descriptors

The two rules of thumb:

  • you need to decide what to improve after the profiling, as profiling often yields surprising results.
  • The quicker part you try to improve the less potential gain you have.

Upvotes: 1

Related Questions