利用特征匹配定求解单应性矩阵
In [1]:
import cv2
import numpy as np
from matplotlib import pyplot as plt
from arknights_mower.utils.image import cropimg, loadimg, loadres
from arknights_mower.utils.matcher import (
GOOD_DISTANCE_LIMIT,
flann,
keypoints_scale_invariant,
)
In [2]:
2024-07-16 21:01:18,429 - DEBUG - /home/zhao/Documents/arknights-mower/arknights_mower/utils/image.py:44 - loadimg - /home/zhao/Documents/arknights-mower/arknights_mower/resources/sanity.png
In [3]:
sc = loadimg("/home/zhao/Downloads/Screenshot_20240716-180721.png", True)
plt.imshow(sc, cmap="gray", vmin=0, vmax=255)
plt.show()
2024-07-16 21:01:18,783 - DEBUG - /home/zhao/Documents/arknights-mower/arknights_mower/utils/image.py:44 - loadimg - /home/zhao/Downloads/Screenshot_20240716-180721.png
In [4]:
img = cropimg(sc, ((1400, 000), (2000, 800)))
plt.imshow(img, cmap="gray", vmin=0, vmax=255)
plt.show()
In [5]:
kp1, des1 = keypoints_scale_invariant(res)
kp2, des2 = keypoints_scale_invariant(img)
bf = cv2.BFMatcher(cv2.NORM_HAMMING)
matches = flann.knnMatch(des1, des2, k=2)
good = []
for pair in matches:
if (len_pair := len(pair)) == 2:
m, n = pair
if m.distance < GOOD_DISTANCE_LIMIT * n.distance:
good.append(m)
elif len_pair == 1:
good.append(pair[0])
print(len(good))
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)
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
matchesMask = mask.ravel().tolist()
In [6]:
h, w = res.shape
pts = np.float32([[0, 0], [0, h - 1], [w - 1, h - 1], [w - 1, 0]]).reshape(-1, 1, 2)
dst = cv2.perspectiveTransform(pts, M)
disp = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
disp = cv2.polylines(disp, [np.int32(dst)], True, (255, 0, 0), 2, cv2.LINE_AA)
good = sorted(good, key=lambda x: x.distance)
disp = cv2.drawMatches(
res,
kp1,
disp,
kp2,
good[:50],
None,
(0, 255, 0),
flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS,
)
plt.imshow(disp)
plt.show()
In [7]:
Out[7]:
array([[ 5.45219656e-01, -1.40243401e-02, 5.38688840e+01],
[-6.00027151e-02, 6.48058168e-01, 2.06700298e+02],
[-1.17835742e-04, -1.26823789e-05, 1.00000000e+00]])
In [8]:
In [9]:
disp = cv2.warpPerspective(img, M.dot(A), (800, 1100), None, cv2.WARP_INVERSE_MAP)
plt.subplot(1, 2, 1)
plt.imshow(img, cmap="gray", vmin=0, vmax=255)
plt.subplot(1, 2, 2)
plt.imshow(disp, cmap="gray", vmin=0, vmax=255)
plt.show()