cv2.KeyPoint 和 cv2.DMatch

一、cv2.Keypoint 数据结构

AttributeDescriptionsComments
.pt点的坐标
.size点邻域大小
.angle特征点方向
.response特征点响应程度指数响应越强,关键点越好
.octave特征点所在的金字塔组从哪一层得到的数据
.class_id类型
Input:
left_kps, left_dess = detector.detectAndCompute(image, None)
print("数据类型", type(left_kps[0]))
print("position", left_kps[0].pt)
print("radius", left_kps[0].size)
print("angle", left_kps[0].angle)
print("response", left_kps[0].response)
print("octave", left_kps[0].octave)
print("class_id", left_kps[0].class_id)

Result:
数据类型 <class 'cv2.KeyPoint'>
position (6.578876972198486, 274.11456298828125)
radius 6.09220027923584
angle 90.25723266601562
response 0.04461445286870003
octave 4784896
class_id -1

二、cv2.DMatch数据结构

AttributeDescriptionsComments
.distance两个描述符的距离越小匹配度越高
.trainIdx目标图像(train)中的索引值
.queryIdx训练图像(query)中的索引值原图
.imgIdx目标图像的索引值多图匹配时用到
Input:
    knn_matchers = matcher.knnMatch(img1, img2, 2)
    print("数据类型:", type(knn_matchers[0]))
    print("distance=", knn_matchers[0].distance)
    print("trainIdx=", knn_matchers[0]trainIdx)
    print("queryIdx=", knn_matchers[0].queryIdx)
    print("imgIdx=", knn_matchers[0].imgIdx)

Result:
数据类型: <class 'cv2.DMatch'>
distance= 32.15586853027344
trainIdx= 121
queryIdx= 10
imgIdx= 0
import cv2 import numpy as np import matplotlib.pyplot as plt # 基础配置参数 width, height = 288, 512 # 图像尺寸 max_matches = 40 # 最大显示匹配数(防止图像过密) # 1. 读取图像文件 img_i = cv2.imread('f1_1.png', cv2.IMREAD_COLOR) img_j = cv2.imread('kf_1.png', cv2.IMREAD_COLOR) # 2. 读取匹配索引有效性文件 idx_i2j = np.loadtxt('idx_i2j.txt', dtype=np.float32) valid = np.loadtxt('valid_match.txt', dtype=bool) # 3. 坐标转换函数 def index_to_coord(index): x = int(index) % width y = int(index) // width return (x, y) # 4. 提取有效匹配点对 valid_indices = np.where(valid)[0] np.random.shuffle(valid_indices) # 随机打乱顺序 selected = valid_indices[:min(max_matches, len(valid_indices))] # 5. 创建关键点与匹配关系 kp1, kp2, matches = [], [], [] for i, k in enumerate(selected): # 原始图像坐标 x_i, y_i = index_to_coord(k) # 目标图像坐标 x_j, y_j = index_to_coord(idx_i2j[k]) # 创建关键点对象 kp1.append(cv2.KeyPoint(x_i, y_i, 1)) kp2.append(cv2.KeyPoint(x_j, y_j, 1)) # 创建匹配关系 matches.append(cv2.DMatch(i, i, 0)) # 6. 可视化配置 out_img = np.empty((max(height, height), width*2, 3), dtype=np.uint8) # 7. 绘制匹配结果 cv2.drawMatches(img_i, kp1, img_j, kp2, matches, outImg=out_img, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS, matchColor=(0, 255, 0), # 绿色连线 singlePointColor=(255, 0, 0)) # 蓝色关键点 # 8. 显示结果(Matplotlib优化显示) plt.figure(figsize=(20, 10)) plt.imshow(cv2.cvtColor(out_img, cv2.COLOR_BGR2RGB)) plt.axis('off') plt.title(f'Keypoint Matches Visualization ({len(selected)}/{len(valid_indices)} valid matches)') plt.show() 现在我编写了以上代码,实现了从四个输入文件(这四个文件是由一个匹配算法从两张图像中获取的,四个文件中的其中两个为png图像输入,图像名为image_i与image_j,输入图像image_i与image_j的宽都为288像素,高度都为512像素;另外两个输入文件为txt文件,其一为idx_i2j.txt文件,是一个包含147456个float元素的图相匹配索引文件,表示image_i到image_j的匹配索引;另一个txt文件名为valid_match_j.txt文件,是一个对应包含147456个布尔值元素的指示匹配索引有效性的文件,以上两个txt文件中的元素都是通过换行分隔的)中可视化点图匹配的功能,能否帮助编写一个代码帮我保存可视化结果?
04-02
import cv2 import numpy as np import matplotlib.pyplot as plt width, height = 288, 512 max_matches = 60 img_i = cv2.imread('f1_1.png', cv2.IMREAD_COLOR) img_j = cv2.imread('kf_1.png', cv2.IMREAD_COLOR) idx_i2j = np.loadtxt('idx_i2j.txt', dtype=np.float32) input_file = "valid_match_j.txt" output_file = "./logs/valid_matchs_j.txt" with open(input_file, "r") as f_in, open(output_file, "w") as f_out: for line in f_in: value = line.strip() if value == "True": f_out.write("1\n") elif value == "False": f_out.write("0\n") valid = np.loadtxt('./logs/valid_matchs_j.txt', dtype=bool) def index_to_coord(index): x = int(index) % width y = int(index) // width return (x, y) valid_indices = np.where(valid)[0] np.random.shuffle(valid_indices) selected = valid_indices[:min(max_matches, len(valid_indices))] kp1, kp2, matches = [], [], [] for i, k in enumerate(selected): x_i, y_i = index_to_coord(k) x_j, y_j = index_to_coord(idx_i2j[k]) kp1.append(cv2.KeyPoint(x_i, y_i, 1)) kp2.append(cv2.KeyPoint(x_j, y_j, 1)) matches.append(cv2.DMatch(i, i, 0)) out_img = np.empty((max(height, height), width*2, 3), dtype=np.uint8) cv2.drawMatches(img_i, kp1, img_j, kp2, matches, outImg=out_img, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS, matchColor=(0, 255, 0), singlePointColor=(255, 0, 0)) plt.figure(figsize=(20, 10)) plt.imshow(cv2.cvtColor(out_img, cv2.COLOR_BGR2RGB)) plt.axis('off') plt.title(f'({len(selected)}/{len(valid_indices)} valid matches)') save_path = './logs/mast3r_match.png' plt.savefig(save_path, bbox_inches='tight', dpi=150, pad_inches=0.1) plt.show() 分析以上代码,能否帮助在以上代码的基础上实现一个新的计算匹配对中存在的误匹配数量模块?误匹配的计算规则如下:首先对于每个匹配对,计算它们像素空间上的欧几里德距离,再统计所有匹配对欧几里德距离之来计算它们的平均值标准差,之后对于每个匹配对,如果它们像素空间上的欧几里德距离与距离平均值的差距大于两倍标准差,则将它们视为可能的误匹配点。计算出误匹配对后,用print函数输出误匹配对数量。
最新发布
04-02
解释如下代码:def draw_matches(img1, kp1, img2, kp2, matches, color=None): """Draws lines between matching keypoints of two images. Keypoints not in a matching pair are not drawn. Args: img1: An openCV image ndarray in a grayscale or color format. kp1: A list of cv2.KeyPoint objects for img1. img2: An openCV image ndarray of the same format and with the same element type as img1. kp2: A list of cv2.KeyPoint objects for img2. matches: A list of DMatch objects whose trainIdx attribute refers to img1 keypoints and whose queryIdx attribute refers to img2 keypoints. """ # We're drawing them side by side. Get dimensions accordingly. # Handle both color and grayscale images. if len(img1.shape) == 3: new_shape = (max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1], img1.shape[2]) elif len(img1.shape) == 2: new_shape = (max(img1.shape[0], img2.shape[0]), img1.shape[1]+img2.shape[1]) new_img = np.zeros(new_shape, type(img1.flat[0])) # Place images onto the new image. new_img[0:img1.shape[0],0:img1.shape[1]] = img1 new_img[0:img2.shape[0],img1.shape[1]:img1.shape[1]+img2.shape[1]] = img2 # Draw lines between matches. Make sure to offset kp coords in second image appropriately. r = 2 thickness = 1 print(len(kp1),len(kp2), len(matches) ) if color: c = color for m in matches[0:20]: # Generate random color for RGB/BGR and grayscale images as needed. if not color: c = np.random.randint(0,256,3) if len(img1.shape) == 3 else np.random.randint(0,256) # So the keypoint locs are stored as a tuple of floats. cv2.line(), like most other things, # wants locs as a tuple of ints. c = [255,255,255] end1 = tuple(np.round(kp1[m.queryIdx].pt).astype(int)) end2 = tuple(np.round(kp2[m.trainIdx].pt).astype(int) + np.array([img1.shape[1], 0])) cv2.line(new_img, end1, end2, c, thickness) cv2.circle(new_img, end1, r, c, thickness) cv2.circle(new_img, end2, r, c, thickness) plt.figure(figsize=(15,15)) plt.imshow(new_img) plt.show()
06-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值