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