2013-07-24 5 views
0

Функция поворачивает изображение шаблона от 0 до 180 (или до 360 градусов) для поиска всех соответствующих совпадений (по всем углам) в исходном изображении даже с разным масштабом.Угловое и масштабное инвариантное совпадение шаблонов с использованием OpenCV

Эта функция была написана в интерфейсе OpenCV C. Когда я попытался перенести его на openCV C++-интерфейс, я получаю много ошибок. Кто-нибудь, пожалуйста, помогите мне перенести его на интерфейс OpenCV C++.

void TemplateMatch() 
    { 

    int i, j, x, y, key; 
    double minVal; 
    char windowNameSource[] = "Original Image"; 
    char windowNameDestination[] = "Result Image"; 
    char windowNameCoefficientOfCorrelation[] = "Coefficient of Correlation Image"; 
    CvPoint minLoc; 
    CvPoint tempLoc; 

    IplImage *sourceImage = cvLoadImage("template_source.jpg", CV_LOAD_IMAGE_ANYDEPTH   | CV_LOAD_IMAGE_ANYCOLOR); 
    IplImage *templateImage = cvLoadImage("template.jpg", CV_LOAD_IMAGE_ANYDEPTH | CV_LOAD_IMAGE_ANYCOLOR); 


    IplImage *graySourceImage = cvCreateImage(cvGetSize(sourceImage), IPL_DEPTH_8U, 1); 
    IplImage *grayTemplateImage =cvCreateImage(cvGetSize(templateImage),IPL_DEPTH_8U,1); 
    IplImage *binarySourceImage = cvCreateImage(cvGetSize(sourceImage), IPL_DEPTH_8U, 1); 
    IplImage *binaryTemplateImage = cvCreateImage(cvGetSize(templateImage), IPL_DEPTH_8U, 1); 
    IplImage *destinationImage = cvCreateImage(cvGetSize(sourceImage), IPL_DEPTH_8U, 3); 

    cvCopy(sourceImage, destinationImage); 

    cvCvtColor(sourceImage, graySourceImage, CV_RGB2GRAY); 
    cvCvtColor(templateImage, grayTemplateImage, CV_RGB2GRAY); 

    cvThreshold(graySourceImage, binarySourceImage, 200, 255, CV_THRESH_OTSU); 
    cvThreshold(grayTemplateImage, binaryTemplateImage, 200, 255, CV_THRESH_OTSU); 

    int templateHeight = templateImage->height; 
    int templateWidth = templateImage->width; 

float templateScale = 0.5f; 

    for(i = 2; i <= 3; i++) 
    { 

    int tempTemplateHeight = (int)(templateWidth * (i * templateScale)); 
    int tempTemplateWidth = (int)(templateHeight * (i * templateScale)); 

    IplImage *tempBinaryTemplateImage = cvCreateImage(cvSize(tempTemplateWidth,     tempTemplateHeight), IPL_DEPTH_8U, 1); 

    // W - w + 1, H - h + 1 

    IplImage *result = cvCreateImage(cvSize(sourceImage->width - tempTemplateWidth + 1,  sourceImage->height - tempTemplateHeight + 1), IPL_DEPTH_32F, 1); 

    cvResize(binaryTemplateImage, tempBinaryTemplateImage, CV_INTER_LINEAR); 
    float degree = 20.0f; 
    for(j = 0; j <= 9; j++) 
    { 

    IplImage *rotateBinaryTemplateImage = cvCreateImage(cvSize(tempBinaryTemplateImage- >width, tempBinaryTemplateImage->height), IPL_DEPTH_8U, 1); 

     //cvShowImage(windowNameSource, tempBinaryTemplateImage); 
     //cvWaitKey(0);    

     for(y = 0; y < tempTemplateHeight; y++) 
      { 

     for(x = 0; x < tempTemplateWidth; x++) 
      { 
      rotateBinaryTemplateImage->imageData[y * tempTemplateWidth + x] = 255; 

      }   
      } 


     for(y = 0; y < tempTemplateHeight; y++) 
     { 

     for(x = 0; x < tempTemplateWidth; x++) 
      { 

     float radian = (float)j * degree * CV_PI/180.0f; 
     int scale = y * tempTemplateWidth + x; 

     int rotateY = - sin(radian) * ((float)x - (float)tempTemplateWidth/2.0f) + cos(radian) * ((float)y - (float)tempTemplateHeight/2.0f) + tempTemplateHeight/2; 

     int rotateX = cos(radian) * ((float)x - (float)tempTemplateWidth/2.0f) + sin(radian) * ((float)y - (float)tempTemplateHeight/2.0f) + tempTemplateWidth/2; 


     if(rotateY < tempTemplateHeight && rotateX < tempTemplateWidth && rotateY >= 0 && rotateX >= 0) 

     rotateBinaryTemplateImage->imageData[scale] = tempBinaryTemplateImage->imageData[rotateY * tempTemplateWidth + rotateX]; 

    } 
    } 

    //cvShowImage(windowNameSource, rotateBinaryTemplateImage); 
    //cvWaitKey(0); 

    cvMatchTemplate(binarySourceImage, rotateBinaryTemplateImage, result, CV_TM_SQDIFF_NORMED); 

    //cvMatchTemplate(binarySourceImage, rotateBinaryTemplateImage, result, CV_TM_SQDIFF); 

    cvMinMaxLoc(result, &minVal, NULL, &minLoc, NULL, NULL); 
    printf(": %f%%\n", (int)(i * 0.5 * 100), j * 20, (1 - minVal) * 100);  

    if(minVal < 0.065) // 1 - 0.065 = 0.935 : 93.5% 
    { 
     tempLoc.x = minLoc.x + tempTemplateWidth; 
     tempLoc.y = minLoc.y + tempTemplateHeight; 
    cvRectangle(destinationImage, minLoc, tempLoc, CV_RGB(0, 255, 0), 1, 8, 0); 

    } 
    } 

    //cvShowImage(windowNameSource, result); 
    //cvWaitKey(0); 

    cvReleaseImage(&tempBinaryTemplateImage); 
    cvReleaseImage(&result); 

    } 

    // cvShowImage(windowNameSource, sourceImage); 
    // cvShowImage(windowNameCoefficientOfCorrelation, result); 

    cvShowImage(windowNameDestination, destinationImage); 
    key = cvWaitKey(0); 

    cvReleaseImage(&sourceImage); 
    cvReleaseImage(&templateImage); 
    cvReleaseImage(&graySourceImage); 
    cvReleaseImage(&grayTemplateImage); 
    cvReleaseImage(&binarySourceImage); 
    cvReleaseImage(&binaryTemplateImage); 
    cvReleaseImage(&destinationImage); 

    cvDestroyWindow(windowNameSource); 
    cvDestroyWindow(windowNameDestination); 
    cvDestroyWindow(windowNameCoefficientOfCorrelation); 

    } 

РЕЗУЛЬТАТ:

изображение шаблона:

enter image description here

изображение Результата:

Функция выше ставит прямоугольники вокруг прекрасных матчей (угол и масштаб инвариант) в этом изображении .....

enter image description here

Теперь я пытаюсь перенести код в C++-интерфейс. Если кому-то нужна дополнительная информация, пожалуйста, дайте мне знать.

+0

Вы можете использовать logpolar преобразования, чтобы иметь масштаб и поворот инвариантность http://stackoverflow.com/questions/16294700/fft-based-image-registration-in-python – mrgloom

+0

@mrgloom .... Я не использовал лог-полярное преобразование раньше для сопоставления шаблонов. пожалуйста, дайте мне какой-нибудь примерный код для сопоставления шаблонов для нескольких вхождений шаблона в исходное изображение с использованием логарифмического полярного преобразования. – Sharath

ответ

0

C++ Порт выше кода:

Mat TemplateMatch(Mat sourceImage, Mat templateImage){ 

    double minVal; 
    Point minLoc; 
    Point tempLoc; 

    Mat graySourceImage = Mat(sourceImage.size(),CV_8UC1); 
    Mat grayTemplateImage = Mat(templateImage.size(),CV_8UC1); 
    Mat binarySourceImage = Mat(sourceImage.size(),CV_8UC1); 
    Mat binaryTemplateImage = Mat(templateImage.size(),CV_8UC1); 
    Mat destinationImage = Mat(sourceImage.size(),CV_8UC3); 

    sourceImage.copyTo(destinationImage); 

    cvtColor(sourceImage, graySourceImage, CV_BGR2GRAY); 
    cvtColor(templateImage, grayTemplateImage, CV_BGR2GRAY); 

    threshold(graySourceImage, binarySourceImage, 200, 255, CV_THRESH_OTSU); 
    threshold(grayTemplateImage, binaryTemplateImage, 200, 255, CV_THRESH_OTSU); 

    int templateHeight = templateImage.rows; 
    int templateWidth = templateImage.cols; 

    float templateScale = 0.5f; 

    for(int i = 2; i <= 3; i++){ 

     int tempTemplateHeight = (int)(templateWidth * (i * templateScale)); 
     int tempTemplateWidth = (int)(templateHeight * (i * templateScale)); 

     Mat tempBinaryTemplateImage = Mat(Size(tempTemplateWidth,tempTemplateHeight),CV_8UC1); 
     Mat result = Mat(Size(sourceImage.cols - tempTemplateWidth + 1,sourceImage.rows - tempTemplateHeight + 1),CV_32FC1); 

     resize(binaryTemplateImage,tempBinaryTemplateImage,Size(tempBinaryTemplateImage.cols,tempBinaryTemplateImage.rows),0,0,INTER_LINEAR); 

     float degree = 20.0f; 

     for(int j = 0; j <= 9; j++){ 

      Mat rotateBinaryTemplateImage = Mat(Size(tempBinaryTemplateImage.cols, tempBinaryTemplateImage.rows), CV_8UC1); 

      for(int y = 0; y < tempTemplateHeight; y++){ 
       for(int x = 0; x < tempTemplateWidth; x++){ 
        rotateBinaryTemplateImage.data[y * tempTemplateWidth + x] = 255; 
       } 
      } 


      for(int y = 0; y < tempTemplateHeight; y++){ 
       for(int x = 0; x < tempTemplateWidth; x++){ 

        float radian = (float)j * degree * CV_PI/180.0f; 
        int scale = y * tempTemplateWidth + x; 

        int rotateY = - sin(radian) * ((float)x - (float)tempTemplateWidth/2.0f) + cos(radian) * ((float)y - (float)tempTemplateHeight/2.0f) + tempTemplateHeight/2; 
        int rotateX = cos(radian) * ((float)x - (float)tempTemplateWidth/2.0f) + sin(radian) * ((float)y - (float)tempTemplateHeight/2.0f) + tempTemplateWidth/2; 

        if(rotateY < tempTemplateHeight && rotateX < tempTemplateWidth && rotateY >= 0 && rotateX >= 0) 
         rotateBinaryTemplateImage.data[scale] = tempBinaryTemplateImage.data[rotateY * tempTemplateWidth + rotateX]; 
       } 
      } 

      matchTemplate(binarySourceImage, rotateBinaryTemplateImage, result, CV_TM_SQDIFF_NORMED); 

      minMaxLoc(result, &minVal, 0, &minLoc, 0, Mat()); 

      cout<<(int)(i * 0.5 * 100)<<" , "<< j * 20<<" , "<< (1 - minVal) * 100<<endl; 

      if(minVal < 0.065){ // 1 - 0.065 = 0.935 : 93.5% 
       tempLoc.x = minLoc.x + tempTemplateWidth; 
       tempLoc.y = minLoc.y + tempTemplateHeight; 
       rectangle(destinationImage, minLoc, tempLoc, CV_RGB(0, 255, 0), 1, 8, 0); 
      } 
     } 
    } 
    return destinationImage; 
} 
+0

, как бы вы сделали эту работу в режиме реального времени, а также с различными масштабами не только несколько? –

+1

Предоставленный код представляет собой только порт C-кода с оригинального сообщения. Я предлагаю вам передать реализацию Logpolar в OpenCV, которая поддерживает шаблон RSI, соответствующий этому [LINK] (http://docs.opencv.org/trunk/da/d54/group__imgproc__transform.html#gaec3a0b126a85b5ca2c667b16e0ae022d) –