1

我正在使用此 SURF 代码来检测图像中的徽标。它工作正常,但速度很慢。关于如何优化它的任何想法?

- (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];

}

在上面的代码image中是我的原始图像,objectToFind是我想要检测的标志。

如果我的问题不清楚,请告诉我。

4

1 回答 1

1

您需要使用分析来确定代码的哪一部分最慢。
由于您使用的是 XCode,因此您可以使用内置的分析器:

  1. 在左上角,您按住“运行”按钮并选择“配置文件”。
  2. 单击 Profile,然后选择 Time Profiler。
  3. 过了一会儿,您在分析器中按“停止”,然后选择“隐藏缺失符号”、“隐藏系统库”和“顶级函数”,取消选择“按线程分隔”。
  4. 现在查找 main 函数,它后面有一个隐藏的右箭头。单击该箭头,您可以通过调用树查看时间​​百分比和调用统计信息。

这就是你开始的方式。

一般来说,我有以下建议而无需分析

  • 尽可能避免创建新的图像和内存存储。(您可以将临时使用的图像传递给您的函数,并将这些图像保存在外部,以便您以后可以重用它们。)
  • 缩小您的图像(和您的徽标)以显示图像的主要部分
  • 使用较少的描述符

两条经验法则:

  • 您需要决定在 profiling 之后要改进什么,因为 profiling 通常会产生令人惊讶的结果。
  • 您尝试改进的部分越快,您获得的潜在收益就越少。
于 2012-12-18T13:26:20.380 回答