使用Python在两个图像中查找匹配数据点

5
我有两张图片,分别是图1和图2。它们都来自同一来源,但没有对齐。任务是在这两个图像中找到共同的数据点,并在匹配的数据点之间绘制线条。我希望最终的结果看起来像图4。
目前为止,我使用了OpenCV并编写了以下代码:
import cv2 
import matplotlib.pyplot as plt

img_file1= "Fig_1.png"
img_file2= "Fig_2.png"
img1= cv2.imread(img_file1)
img2= cv2.imread(img_file2)
    
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

figure, ax = plt.subplots(1, 2, figsize=(16, 8))

ax[0].imshow(img1, cmap='gray')
ax[1].imshow(img2, cmap='gray')

#sift
sift = cv2.xfeatures2d.SIFT_create()

keypoints_1, descriptors_1 = sift.detectAndCompute(img1,None)
keypoints_2, descriptors_2 = sift.detectAndCompute(img2,None)

#feature matching
bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)

matches = bf.match(descriptors_1,descriptors_2)
matches = sorted(matches, key = lambda x:x.distance)

img3 = cv2.drawMatches(img1, keypoints_1, img2, keypoints_2, matches[:50], img2, flags=2)
plt.imshow(img3),plt.show()

这个结果出乎意料,见图4。此外,它看起来相当混乱和不清晰。 有人能帮我解决这个问题吗?提前谢谢。 图1。

enter image description here

图2 在此输入图片描述

img3

enter image description here

图3

enter image description here


图3代表什么?你从上面的代码中得到了什么输出? - Kishore Sampath
是的,图3代表我的代码输出(img3)。 - Ravi
我的猜测是,由于要检测的特征只是白色圆圈,所以特征检测器会检测到圆形,而且由于图像中充满了类似的特征(即白色圆圈),所以匹配器无法适当地进行匹配。 - Kishore Sampath
尝试使用不同的示例运行代码,例如在opencv文档(https://docs.opencv.org/master/dc/dc3/tutorial_py_matcher.html)中显示的示例,并检查是否获得类似的结果。 - Kishore Sampath
尝试过了,但结果相似。fig3似乎将图像叠加在一起,我该如何使这两个之间的距离足够大,以便清楚地看到哪些数据点属于哪一个? - Ravi
2个回答

2
基本上,这对我来说似乎是一个注册问题(图像需要注册)。
以下是您可以做的事情:
1. 找到具有连接组件分析的点的位置。 2. 计算所需的移位量以注册两个图像。在这里,您的图像似乎只是平移的,因此简单的基于交叉相关的注册就足够了。

enter image description here

from skimage.registration import phase_cross_correlation
from skimage.io import imread
from skimage.measure import label, regionprops
from skimage.filters import threshold_otsu

from matplotlib.pyplot import imshow, plot, figure
import numpy as np


# Load images
img_a = imread("671OL.jpg", as_gray=True)
img_b = imread("zpevD.jpg", as_gray=True)

# apply threshold
th_img_a = img_a > threshold_otsu(img_a)
th_img_b = img_b > threshold_otsu(img_b)

# measure connected component
img_lable = label(th_img_a)
r_props = regionprops(img_lable)

figure(figsize=(15,7))
rows, cols = img_b.shape

# calculate the registration (shift) of the two images
flow = phase_cross_correlation(th_img_a, th_img_b)

# stack the images and trace the segments that connect the points
d=10
# a vertical white bar between the two pictures
vbar=np.ones((rows,d))
xshift = cols+d
dy,dx = flow[0]
dx=dx + xshift
imshow(np.hstack([img_a, vbar, img_b]), cmap='gray')
for rp in r_props:
    y0,x0 = rp.centroid
    x1 = x0 + dx
    y1 = y0 - dy
    if y1<rows and x1 < 2*cols + d:
        # filter out points that are not in img_b
        plot([x0,x1],[y0,y1], '--', alpha=0.5)


在运行您的代码时,我遇到了这个错误:“无法从'skimage.registration(C:\ Users \ rp603 \ Anaconda3 \ lib \ site-packages \ skimage \ registration \ __ init__.py)'导入名称'optical_flow_ilk'”。 - Ravi
我已经移除了无用的导入。 - MarcoP
如果我能找到每个图像的每个数据点的坐标,然后根据这些坐标尝试找到匹配的数据点,但是我不知道如何做到这一点。 - Ravi
图片需要先对齐,否则图像数据点的坐标会出错。如何解决这个问题?我在你的代码中找不到这个。 - Ravi
让我们在聊天中继续这个讨论 - MarcoP
显示剩余3条评论

2
转换似乎纯粹是平移的。尝试使用标准化灰度相关性进行模板匹配。

如何做到这一点?你能提供一个例子吗? - Ravi
@Ravi:在文档中搜索模板匹配。 - user1196549
@YvesDaoust 他正在尝试找到两个图像之间的公共数据点并将它们匹配。在这种情况下,模板应该是什么? - Kishore Sampath
@Kishore:整个图像减去平移允许。 - user1196549

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接