Python 与 C++ OpenCV matchTemplate

标签 python c++ opencv template-matching

我在使用 OpenCV 时遇到了一个奇怪的问题。我在 Python 和 C++ 上使用 OpenCV 进行模板匹配,但是,即使 Python 在底层使用了 C++ 方法,我也得到了非常不同的结果。 Python 方法给了我非常准确的位置,C++ 还差得很远。这是什么原因呢?是我的 C++ 代码还是其他代码?

我使用 Python 2.7.11、Apple LLVM 版本 7.3.0 (clang-703.0.29) 和 OpenCV3.0。

我的Python代码:

def toGray(img):
    _, _, channels = img.shape
    if channels == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    else:
        gray = img
    return gray

def template_match(img, template):
    w, h = template.shape[::-1]
    res = cv2.matchTemplate(img,template,cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)
    top_left = max_loc

    bottom_right = (top_left[0] + w, top_left[1] + h)
    cv2.rectangle(img,top_left, bottom_right, 255, 2)
    plt.subplot(121),plt.imshow(res,cmap = 'gray')
    plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
    plt.subplot(122),plt.imshow(img,cmap = 'gray')
    plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
    plt.suptitle("TM_CCOEFF_NORMED")

    plt.show()

if __name__ == "__main__":
    img_name = sys.argv[1]
    img_name2 = sys.argv[2]
    img_rgb = cv2.imread(img_name)
    img_rgb2 = cv2.imread(img_name2)
    gimg1 = toGray(img_rgb)
    gimg2 = toGray(img_rgb2)

    template_match(gimg1, gimg2)

我的C++代码(与OpenCV文档完全相同):

Mat img; Mat templ; Mat result;
char* image_window = "Source Image";
char* result_window = "Result window";

int match_method;
int max_Trackbar = 5;

/// Function Headers
void MatchingMethod( int, void* );

/** @function main */
int main( int argc, char** argv )
{
  /// Load image and template
  img = imread( argv[1], 1 );
  templ = imread( argv[2], 1 );

  /// Create windows
  namedWindow( image_window, CV_WINDOW_AUTOSIZE );
  namedWindow( result_window, CV_WINDOW_AUTOSIZE );

  /// Create Trackbar
  char* trackbar_label = "Method: \n 0: SQDIFF \n 1: SQDIFF NORMED \n 2: TM CCORR \n 3: TM CCORR NORMED \n 4: TM COEFF \n 5: TM COEFF NORMED";
  createTrackbar( trackbar_label, image_window, &match_method, max_Trackbar, MatchingMethod );

  MatchingMethod( 0, 0 );

  waitKey(0);
  return 0;
}

/**
 * @function MatchingMethod
 * @brief Trackbar callback
 */
void MatchingMethod( int, void* )
{
  /// Source image to display
  Mat img_display;
  img.copyTo( img_display );

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

  result.create( result_rows, result_cols, CV_32FC1 );

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

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

  minMaxLoc( result, &minVal, &maxVal, &minLoc, &maxLoc, Mat() );

  /// For SQDIFF and SQDIFF_NORMED, the best matches are lower values. For all the other methods, the higher the better
  if( match_method  == CV_TM_SQDIFF || match_method == CV_TM_SQDIFF_NORMED )
    { matchLoc = minLoc; }
  else
    { matchLoc = maxLoc; }

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

  imshow( image_window, img_display );
  imshow( result_window, result );

  cv::imwrite("rec.jpg", img_display);
  return;
}

原始图片: Original Image Template

Python 输出: Python Output

C++ 输出 C++ Output

最佳答案

纵观这两种实现,它们之间最明显的区别是所使用图像的颜色格式。

在 Python 版本中,您可以“按原样”加载图像。由于您的输入图像是 RGB(正如变量名称所暗示的那样),您将在彩色图像上进行模板匹配。

img_rgb = cv2.imread(img_name)
img_rgb2 = cv2.imread(img_name2)

但是在 C++ 中,您将图像加载为灰度,因为您将 1 作为第二个参数传递。

img = imread( argv[1], 1 );
templ = imread( argv[2], 1 );

根据cv::matchTemplate文档:

In case of a color image, template summation in the numerator and each sum in the denominator is done over all of the channels and separate mean values are used for each channel. That is, the function can take a color template and a color image. The result will still be a single-channel image, which is easier to analyze.

这表明,将其应用于 3 channel 图像时,与将其应用于同一图像的单 channel 版本时,很可能会得到不同的结果。

关于Python 与 C++ OpenCV matchTemplate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36876142/

相关文章:

python - 在 Django 中,如何在 Model.save() 期间引发非验证错误?

C++与嵌套私有(private)类的友元

c++ - 构建 OpenCV 时出错 : "recompile with -fPIC"

python - 使用 python opencv 进行 Blob 检测

Python CV2 提取带字幕的视频帧

python - 使用 python 读取优化 cassandra

Python 在嵌套列表中搜索以查找值并将值插入到新列表中

c++ - 使用 QMathGL 绘制实时数据?

c++ - VC++6中如何跟踪某个对象

python - 我如何从一个类访问另一个类?