2012-12-18 51 views
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是我的原始图像和是我要检测的标志。

如果我的问题不清楚,请让我知道。

回答

1

您需要使用分析来确定代码的哪一部分是最慢的。
由于您使用的XCode,你有一个内置分析器在双手前伸:

  1. 在他你左上角按下并按住“运行”按钮,然后选择“配置文件”。
  2. 点击配置文件并选择时间分析器。
  3. 过了一会儿,您在探查器中按“停止”,然后选择“隐藏缺失符号”,“隐藏系统库”和“顶级函数”,取消选择“按线程分隔”。
  4. 现在查看函数main,并在它后面有一个隐藏的右箭头。点击那个箭头,你可以看到时间百分比和calltree呼叫统计。

这就是你如何开始。

总的来说,我有以下几点建议了profiling

  • 避免产生新的图像和记忆储存尽可能多的,你可以。 (您可以将临时使用的图像传递给您的功能,并将这些图像保存到外部,以便稍后可以重复使用它们。)
  • 缩小图像(和您的徽标)以表现图像的主要部分
  • 使用更少的描述符

拇指的两个规则:

  • 你需要决定剖析后什么来改善,作为分析常常产生令人惊讶的结果。
  • 您尝试改善您拥有的较少潜在收益的较快部分。