Can you explain values of imgIdx and trainIdx in this example of cv.match?

This OpenCV Python script:

import numpy as np, cv2 as cv

bf = cv.BFMatcher(cv.NORM_L1, crossCheck=False)
bf.add(np.array([[0], [1], [2]], dtype='f4'))  # train image 0
bf.add(np.array([[0.1], [1.1], [2.1]], dtype='f4'))  # train image 1
bf.train()

src = np.array([[0], [1.1], [2.1]], dtype='f4')
matches = bf.match(src)

for m in matches:
  print(m.distance, m.queryIdx, m.imgIdx, m.trainIdx)

attempts to match src descriptors of an image, greatly simplified for clarity, with descriptors of image 0 and 1 used to train cv.BFMatcher. Here is the result:

0.0 0 0 0
0.0 1 4 0
0.0 2 5 0

Why m.trainIdx is always zero, despite two train images added with bf.add? Is there a way to have descriptors in BFMatcher separated into groups belonging to individual training images? If so, can match result not cross group boundaries, i.e. all matches have resulting descriptors from a single training image?

The values of m.imgIdx and m.trainIdx seem to be inconsistent with OpenCV documentation at https://docs.opencv.org/4.10.0/dc/dc3/tutorial_py_matcher.html:

  • DMatch.trainIdx - Index of the descriptor in train descriptors
  • DMatch.queryIdx - Index of the descriptor in query descriptors
  • DMatch.imgIdx - Index of the train image.

This is a repost from https://stackoverflow.com/questions/79622206/can-you-explain-values-of-imgidx-and-trainidx-in-this-example-of-cv-match

My question was answered on Wrong order of fields in DMatch. · Issue #27336 · opencv/opencv · GitHub.

The issue was caused by too “shallow” input arrays, they have to be 3D as shown below:

bf.add(np.array([[[0], [1], [2]]], dtype='f4'))  # train image 0
bf.add(np.array([[[0.1], [1.1], [2.1]]], dtype='f4'))  # train image 1

Forcing matches to use variable length descriptor arrays from individual images is not possible in this example.