OpenCV - C++到Java - 模板匹配

Tia*_*goM 6 c++ java templates opencv match

我试图在我的图像中检测到超过正方形(标记),因为我在这里要求检测2D图像中的标记位置

有一个人向我展示了一个C++解决方案,这里是:

#include <iostream>

#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>


//See: http://docs.opencv.org/doc/tutorials/imgproc/histograms/template_matching/template_matching.html
//See: http://answers.opencv.org/question/60382/detect-markers-position-in-2d-images/
int main() {
  cv::Mat img, templateImg, result;
  cv::VideoCapture capture("http://answers.opencv.org/upfiles/14297307634571599.png");
  if(capture.isOpened()) {
    capture >> img;
  } else {
    return -1;
  }

  capture = cv::VideoCapture("http://answers.opencv.org/upfiles/14297308125543022.png");
  if(capture.isOpened()) {
    capture >> templateImg;
  } else {
    return -1;
  }

  /// Reduce the size of the image to display it on my screen
  cv::resize(img, img, cv::Size(), 0.5, 0.5);
  /// Reduce the size of the template image
  /// (first to fit the size used to create the image test, second to fit the size of the reduced image)
  cv::resize(templateImg, templateImg, cv::Size(), 0.25, 0.25);

  cv::Mat img_display;
  img.copyTo(img_display);

  // Create the result matrix
  int result_cols =  img.cols - templateImg.cols + 1;
  int result_rows = img.rows - templateImg.rows + 1;

  result.create(result_rows, result_cols, CV_32FC1);

  /// Do the Matching and Normalize
  cv::matchTemplate(img, templateImg, result, CV_TM_CCORR_NORMED);
  cv::normalize(result, result, 0, 1, cv::NORM_MINMAX, -1, cv::Mat());

  /// Localizing the best match with minMaxLoc
  double minVal; double maxVal; cv::Point minLoc; cv::Point maxLoc;
  cv::Point matchLoc;

  for(;;) {
    cv::minMaxLoc(result, &minVal, &maxVal, &minLoc, &maxLoc, cv::Mat());
    matchLoc = maxLoc;
    std::cout << "Max correlation=" << maxVal << std::endl;
    if(maxVal < 0.8) {
      break;
    }

    /// Show me what you got
    cv::rectangle(img_display, matchLoc, cv::Point(matchLoc.x + templateImg.cols , matchLoc.y + templateImg.rows),
        cv::Scalar::all(0), 2, 8, 0);
    cv::rectangle(result, cv::Point(matchLoc.x - templateImg.cols/2 , matchLoc.y - templateImg.rows/2),
        cv::Point(matchLoc.x + templateImg.cols/2 , matchLoc.y + templateImg.rows/2 ), cv::Scalar::all(0), 2, 8, 0);

    cv::imshow("result", result);
    cv::waitKey(0);

    /// Fill the detected location with a rectangle of zero
    cv::rectangle(result, cv::Point( matchLoc.x - templateImg.cols/2 , matchLoc.y - templateImg.rows/2),
        cv::Point(matchLoc.x + templateImg.cols/2 , matchLoc.y + templateImg.rows/2 ), cv::Scalar::all(0), -1);
  } while (maxVal > 0.9);


  cv::imshow("result", result);
  cv::imshow("img_display", img_display);
  cv::waitKey(0);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

for循环负责查找多个标记并检测它,我正在尝试将其调整为我的java代码,我在这里得到一个无限循环是我的代码:

public void run(String inFile, String templateFile, String outFile, int match_method) {
        System.out.println("\nRunning Template Matching");


    Mat img = Highgui.imread(inFile);
    Mat templ = Highgui.imread(templateFile);

    // / Create the result matrix
    int result_cols = img.cols() - templ.cols() + 1;
    int result_rows = img.rows() - templ.rows() + 1;
    Mat result = new Mat(result_rows, result_cols, CvType.CV_32FC1);

    // / Do the Matching and Normalize
    Imgproc.matchTemplate(img, templ, result, match_method);
    Core.normalize(result, result, 0, 1, Core.NORM_MINMAX, -1, new Mat());

    Point matchLoc;
    Point maxLoc;
    Point minLoc;

    MinMaxLocResult mmr;

    boolean iterate = true;
    while(iterate){

    // / Localizing the best match with minMaxLoc
    mmr = Core.minMaxLoc(result);
    matchLoc = mmr.maxLoc;


    if(mmr.maxVal < 0.8)
    {
        iterate = false;
    }



    // / Show me what you got
    Core.rectangle(img, matchLoc, new Point(matchLoc.x + templ.cols(),
            matchLoc.y + templ.rows()), new Scalar(0, 255, 0));

    }

    // Save the visualized detection.
    System.out.println("Writing "+ outFile);
    Highgui.imwrite(outFile, img);

}
Run Code Online (Sandbox Code Playgroud)

我注意到函数minMaxLoc在c ++中比在java中有更多的参数,也许这就是问题所在?为什么我不能在java中获得相同的行为有人可以帮助我吗?

非常感谢你提前

sri*_*ram 3

正如西里尔所说,你忘记为最大位置填充零,因此你得到了无限循环。可能他忘了向你解释,

   for each iteration
   find the max location
   check if max value is greater than desired threshold
   if true 
   show me what is max
   else
   break // not found anything that matches
   make the existing max to be zero and continue to search for other max// you forgot this and hence infinite loop
   end
Run Code Online (Sandbox Code Playgroud)

为了更深入地了解该问题,您可以在c++代码中注释以下行并运行它,您将遇到类似的问题。(这里cv::Scalar::all(0),-1 args 表示用 0填充现有的最大/找到区域并继续)

// Fill the detected location with a rectangle of zero
    cv::rectangle(result, cv::Point(matchLoc.x - templateImg.cols / 2, matchLoc.y - templateImg.rows / 2),
        cv::Point(matchLoc.x + templateImg.cols / 2, matchLoc.y + templateImg.rows / 2), cv::Scalar::all(0), -1);
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你。