EstimateAffinePartial2D: What is required input format?

I’m attempting to find where a “template” image is located in a “target” image.

I’m using the ORB algorithm to find keypoints in both images, then using a brute force matcher to find matches. I filter the matches with Lowe’s ratio test. Then using the filtered matches I’d like to use EstimateAffinePartial2D to find where the template best fits in the target.

I was able to follow this tutorial to get a working prototype in python:https:// www. geeksforgeeks .org/feature-matching-using-orb-algorithm-in-python-opencv/

But when attempting to translate into golang I’m running into troubles with EstimateAffinePartial2D

Here is a working version in python

import sys

import numpy as np
import cv2.cv2 as cv2

img1 = cv2.imread('score_overlay_2021_1280.png')
img2 = cv2.imread('2021/frame-00570.jpg')


# Initialize the ORB detector algorithm
orb = cv2.ORB_create()

kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)

matcher = cv2.BFMatcher()
matches = matcher.knnMatch(des1, des2, k=2)

# Apply ratio test
good = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        good.append(m)

print("found {} matches".format(len(good)))

if len(good) < 7:
    print("Not enough good keypoint matches between template and image")
    sys.exit(1)

src_pts = np.float32([kp1[m.queryIdx].pt for m in good]).reshape(-1, 1, 2)
dst_pts = np.float32([kp2[m.trainIdx].pt for m in good]).reshape(-1, 1, 2)
t = cv2.estimateAffinePartial2D(src_pts, dst_pts)

print(t)

I’m hoping to have the same code working in go(lang)

func main() {

	algo := gocv.NewORB()

	overlay := gocv.IMRead("score_overlay_2021_1280.png", gocv.IMReadColor)
	kp1, des1 := algo.DetectAndCompute(overlay, gocv.NewMat())

	matcher := gocv.NewBFMatcher()

	img := gocv.IMRead("2021/frame-00570.jpg", gocv.IMReadColor)
	kp2, des2 := algo.DetectAndCompute(img, gocv.NewMat())

	matches := matcher.KnnMatch(des1, des2, 4)

	// Store all the good matches as per Lowe's ratio test
	goodMatches := make([]gocv.DMatch, 0)
	for _, submatches := range matches {
		if submatches[0].Distance < 0.7 * submatches[1].Distance {
			goodMatches = append(goodMatches,submatches[0] )
		}
	}
	const MinGoodMatches = 9
	//log.Printf("GoodMatches: %d", len(goodMatches))
	if len(goodMatches) < MinGoodMatches {
		return fmt.Errorf("only found %d matches, need at least %d", len(goodMatches), MinGoodMatches)
	}

	_ = kp1
	_ = kp2

	kp1vec := kp2Point2f(kp1)
	kp2vec := kp2Point2f(kp2)
	
	t := gocv.EstimateAffinePartial2D(kp1vec, kp2vec)

	log.Printf("T: %#v", t)

}

When I run the go code I get this error

terminating with uncaught exception of type cv::Exception: OpenCV(4.5.3) /tmp/opencv-20210728-84579-13worgs/opencv-4.5.3/modules/calib3d/src/ptsetreg.cpp:1108: error: (-215:Assertion failed) count >= 0 && to.checkVector(2) == count in function ‘estimateAffinePartial2D’

So digging into the underlying opencv code, it looks like the vectors I’m passing are failing some sort of check.

https:// sourcegraph. com/github.com/opencv/opencv/-/blob/modules/calib3d/src/ptsetreg.cpp?L1098:5

Here are the two source images referenced in the code above:
frame-00570:
https:// github .com/TechplexEngineer/frc-livescore/blob/orb-test/orbtest/2021/frame-00570.jpg

score_overlay_2021_1280:
https:// github .com/TechplexEngineer/frc-livescore/blob/orb-test/orbtest/score_overlay_2021_1280.png