使用 OpenCV 进行角度和尺度不变模板匹配

2023-12-06

函数将模板图像从 0 度旋转到 180(或最多 360)度,以搜索源图像中所有相关的匹配项(所有角度),即使具有不同的比例。

该函数是用 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);

     }

RESULT :

模板图片:

enter image description here

结果图像:

上面的函数在该图像中的完美匹配(角度和比例不变)周围放置了矩形......

enter image description here

现在,我一直在尝试将代码移植到C++接口中。如果有人需要更多详细信息,请告诉我。


上述代码的 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;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 OpenCV 进行角度和尺度不变模板匹配 的相关文章

  • 在Python中从整个图像中检测表格部分

    我有一张尺寸为 3500x5000 的图像 现在我只想检测整个图像中的表格部分 如果不能直接进行 OCR 处理 则对其进行裁剪和旋转 经过所有搜索后 我想到了使用裁剪图像中的每个单元格的想法https medium com coinmonk
  • 在 opencv 中一次性将旋转和平移结合起来

    我有一段用于旋转和平移图像的代码 Point2f pt 0 in rows double angle atan trans c trans b 180 M PI Mat r getRotationMatrix2D pt angle 1 0
  • 车辆分割和跟踪

    我已经从事一个项目一段时间了 目的是在无人机捕获的视频中检测和跟踪 移动 车辆 目前我正在使用 SVM 该 SVM 接受了从车辆和背景图像中提取的局部特征的特征袋表示的训练 然后 我使用滑动窗口检测方法来尝试定位图像中的车辆 然后我想要跟踪
  • 在openCV内部调用Gstreamer

    我需要在 openCV 代码中调用 Gstremaer 本质上是打开摄像机 当我查看源代码时 modules highgui src cap gstreamer cpp似乎是我正在寻找的文件 我用 Gstreamer 标志编译了 OpenC
  • 在Spyder(Python 3.6)中导入cv2时出现导入错误

    我已经在Windows操作系统中安装了opencv 3 0 0 我已运行该应用程序并已成功将其安装在C 驱动器并还复制了cv2 pyd文件输入C Python27 Lib site packages正如我在几个教程视频中看到的那样 在我的
  • C++ OpenCV imdecode 慢

    我将图像的字节数组从 C 发送到 C 库 我使用 OpenCV 版本 3 3 1 解码图像 BMP 图像解码速度很快 但 JPEG 图像解码速度很慢 如何加快 JPEG 图像的解码时间 多线程 GPU 解码性能 Resolution For
  • opencv不失真图像有一个奇怪的圆圈

    我尝试使用 opencv 针孔模型来计算校准参数 然后使图像不失真 问题是 未失真的图像中有一个奇怪的圆圈 如下所示 代码 原始图像和结果图像是here https github com wennycooper A004 pinhole 任
  • HTC One M8 - 使用第二个后置摄像头

    我有一台 HTC One M8 设备 它有 2 个后置摄像头和一个额外的前置摄像头 我的问题是尝试访问第二个后置摄像头 我已经成功制作了一个应用程序 它同时运行 2 个摄像头 1 个前置摄像头和 1 个后置摄像头 但问题是我无法访问第二个后
  • 使用 Brew 安装 OpenCV 永远不会完成

    所以我尝试使用 Homebrew 安装 opencv 但它不起作用 我用了brew tap homebrew science进而brew install opencv发生的情况是 gt Installing opencv from home
  • 使用 OpenCV 从轮廓获取掩模

    我想从我通过 cv findContours 计算的轮廓 它只存在 1 个轮廓 获取图像掩模 然而 虽然我的轮廓变量不为空 但我无法使用 cv drawContours 检索图像蒙版 我的目标图像始终为空 这是我的代码 img mosaic
  • OpenCV findContours() 仅返回一个外部轮廓

    我试图隔离验证码中的字母 我设法过滤验证码 结果是这个黑白图像 但是当我尝试使用 OpenCV 的 findContours 方法分离字母时 它只是发现了一个包裹整个图像的外部轮廓 从而产生了该图像 图像外部的黑色轮廓 我将此代码与 Pyt
  • 使用 OpenCV 描述符与 findFundamentalMat 匹配

    我之前发布了有关同一程序的问题 但没有收到答案 我已经纠正了当时遇到的问题 但又面临新的问题 基本上 我使用未校准的方法自动校正立体图像对的旋转和平移 我使用 SURF 等特征检测算法来查找两个图像 左右立体图像对 中的点 然后再次使用 S
  • opencv cmake安装的python包路径错误

    我一直在尝试遵循 opencv 安装步骤pyimagesearch com http www pyimagesearch com 2015 06 15 install opencv 3 0 and python 2 7 on osx 与虚拟
  • Python中使用cv2获取当前视频播放位置

    我正在尝试使用 CV2 和 Python 从播放视频中获取当前播放时间位置 如果可能 以毫秒为单位 目前我正在使用此示例代码来播放视频文件 import cv2 import numpy as np file name 2 mp4 wind
  • Opencv - Features2D + 单应性不正确的结果

    我在将检测到的物体的轮廓放置在正确的位置时遇到了一些问题 就好像坐标位于错误的位置一样 我将粗麻布设置为 2000 并过滤了小于最小距离 3 倍的匹配 任何帮助 将不胜感激 运行匹配和单应性的结果 代码示例如下 public static
  • ECC 导致多光谱图像的图像对齐失败

    我正在尝试将 RGB 图像与 IR 图像 单通道 对齐 目标是创建 4 通道图像 R G B IR 为了做到这一点 我正在使用cv2 findTransformECC如中所述这个非常简洁的指南 https learnopencv com i
  • 在 python + openCV 中使用网络摄像头的问题

    我正在使用以下代码使用 openCV python 访问我的网络摄像头 import cv cv NamedWindow webcam feed cv CV WINDOW AUTOSIZE cam cv CaptureFromCAM 1 然
  • 使用 K 均值聚类 OpenCV 进行交通标志分割

    I used K Means Clustering to perform segmentation on this traffic sign as shown below 这些是我的代码 读取图像并模糊 img cv imread 000
  • 从索贝尔确定图像梯度方向?

    我正在尝试使用 openCV 的 Sobel 方法的结果来确定图像梯度方向 我知道这应该是一个非常简单的任务 我从此处复制了许多资源和答案中的方法 但无论我做什么 所得方向始终在 0 57 度之间 我希望范围为 0 360 我相信所有的深度
  • 从视频/图像中提取元数据

    我从 IP 摄像机获取 MJPEG 流 我正在查看该流并将其保存在计算机上 可以找到我的操作代码here https stackoverflow com questions 21702477 how to parse mjpeg http

随机推荐