根据之前视频防抖的代码,重新写了一套。能够输出缩放、旋转的信息。
-
代码
import cv2
import numpy as np
import argparse
import os
import re
import math
import matplotlib.pyplot as plt
import timedef show_image(image):
plt.figure(figsize=(15, 10))
plt.imshow(image)
plt.title('Feature Matching Results')
plt.show()def process_transform(refer_kp, drone_kp, matches, drone_frame):
# 提取匹配点的坐标
refer_pts = np.float32([refer_kp[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2)
drone_pts = np.float32([drone_kp[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2)# 计算单应性矩阵 H, mask = cv2.findHomography(drone_pts, refer_pts, cv2.RANSAC, 5.0) if H is None: print(f"无法计算 {frame_files[i]} 的变换矩阵,使用上一帧的变换") # 如果无法计算,使用恒等变换 H = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) # 从单应性矩阵中提取变换信息 scale = np.sqrt(H[0,0]**2 + H[1,0]** 2) rotation_rad = math.atan2(H[1,0], H[0,0]) rotation_deg = math.degrees(rotation_rad) x_offset = H[0,2] y_offset = H[1,2] print('transform: scale=%.2f, rotation_rad=%.2f, rotation_deg=%.2f, x_offset=%.2f, y_offset=%.2f' % (scale, rotation_rad, rotation_deg, x_offset, y_offset)) # 应用变换矩阵进行修正 # height, width = drone_frame.shape[:2] # adjusted_frame = cv2.warpPerspective(drone_frame, H, (width, height)) # cv2.imwrite(adjusted_frame_path, adjusted_frame)def process_frame(frame):
# 读取第一帧作为初始基准帧
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)# 检测基准帧的特征点和描述符 kp, des = orb.detectAndCompute(gray, None) return frame, gray, kp, desdef map_match(reference, drone):
current_time = time.time() refer_frame, refer_gray, refer_kp, refer_des = process_frame(reference) drone_frame, drone_gray, drone_kp, drone_des = process_frame(drone) # 匹配特征点(当前帧与上一调整后的帧) matches = matcher.match(refer_des, drone_des) # 按匹配距离排序,取前100个最佳匹配 matches = sorted(matches, key=lambda x: x.distance)[:10] process_transform(refer_kp, drone_kp, matches, drone_frame) print('cost time: %.2f ms' % ((time.time()-current_time)*1000)) match_img = cv2.drawMatches(refer_frame, refer_kp, drone_frame, drone_kp, matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS) show_image(match_img)初始化ORB特征检测器和匹配器
orb = cv2.ORB_create(1000)
matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)if name == "main":
for index in range(1, 10):
image1 = ('images/map-%02d.jpg' % ((index-1)*3))
image1 = cv2.imread(image1)
image2 = ('images/map-%02d.jpg' % ( index *3))
image2 = cv2.imread(image2)
map_match(image1, image2) -
效果
准确的计算出旋转角度,90。
transform: scale=0.72, rotation_rad=-1.57, rotation_deg=-89.81, x_offset=184.79, y_offset=737.42
cost time: 45.87 ms
