你如何使用它在其他图像中的位置来三角测量图像中像素的位置?

How do you triangulate the location of a pixel in an image using it's location in other images?

我有四张来自略微不同位置的场景航拍图。每个图像在每个图像中都有一个相同的可见十字。我知道其中 3 张图像中十字的确切位置(像素 x 和 y)以及所有图像对之间的单应性和基本矩阵。

是否可以使用此信息精确地三角测量第四张图片中十字架的位置?不幸的是,如果我只是将十字的位置从任何图像映射到具有单应性的第四张图像,就会出现一些错误。它在附近但不准确,我希望有一种方法可以限制搜索,也许使用对极线?

假设img0包含你要定位的目标,img1img2img3的目标位置在(x1, y1)、[=分别为 18=]、(x3, y3)。如果您知道所有图像对之间的单应性(例如,H1H2H3 是来自 img1img2img3img0),那么你可以简单地将这些像素位置乘以单应性来获得 img0 中的估计坐标。你不能精确地三角测量,但你可以从所有三个图像和单应性中找到估计的扭曲点,然后取平均值,或者按照你喜欢的方式组合它们,这应该会给你一个很好的估计,只要你的单应性是准确的够了。

单应矩阵是 3x3 矩阵,您的点是 2 向量。为了应用您的变​​换(或乘以矩阵和向量),您需要齐次坐标;您的积分格式为 (x, y, 1)。然后,要从 img1 中获取像素在 img0 中的位置,乘法如下:

[s*x0]        [x1]   [h00 h01 h02]   [x1]
[s*y0] = H1 * [y1] = [h10 h11 h12] * [y1]
[s   ]        [ 1]   [h20 h21 h22]   [ 1]

您的输出将是一个向量,但不是齐次的。结果点将有一个比例因子,s;除以 s 以获得最终坐标 (x0, y0)。只需对您拥有的三个目标位置和那些相应的单应性执行此操作,您最终将得到三个估计位置,然后您可以对它们进行平均。


完整示例。

这是使用一些提供了地面实况数据的图像,可用 here

Here's my results.

在第一张图片中,鸡眼中间十字的位置是通过了解其他三张图片中的位置以及数据集中给出的地面实况单应性来估计的。我输出每个单应性的估计值、它们的平均值和四舍五入的像素值,结果证明四舍五入的估计像素值是准确的(因为单应性非常准确)。

Estimations:
2 -> 1:    [ 527.15670903  222.57196904] 
3 -> 1:    [ 527.21339222  221.86819147] 
4 -> 1:    [ 527.63122722  222.30614892] 
Avg loc:   [ 527.33377616  222.24876981] 
Est loc:   [527 222] 
True loc:  [527 222]

这是一个完整的编码示例,只需从该数据集中下载图像并将其弹出到该文件夹​​中的脚本中,然后 运行。

import numpy as np
import cv2

# read images, taken from http://kahlan.eps.surrey.ac.uk/featurespace/web/
img1 = cv2.imread("img1.png", 1)
img2 = cv2.imread("img2.png", 1)
img3 = cv2.imread("img3.png", 1)
img4 = cv2.imread("img4.png", 1)

# true locations of the chicken's crossed eye (labeled myself)
loc1 = np.array([527, 222, 1])
loc2 = np.array([449, 241, 1])
loc3 = np.array([476, 275, 1])
loc4 = np.array([385, 236, 1])

# define ground truth homographies, also from http://kahlan.eps.surrey.ac.uk/featurespace/web/
H12 = np.array([
    [8.7976964e-01,   3.1245438e-01,  -3.9430589e+01],
    [-1.8389418e-01,   9.3847198e-01,   1.5315784e+02],
    [1.9641425e-04,  -1.6015275e-05,   1.0000000e+00]])

H13 = np.array([
   [7.6285898e-01,  -2.9922929e-01,   2.2567123e+02],
   [3.3443473e-01,   1.0143901e+00,  -7.6999973e+01],
   [3.4663091e-04,  -1.4364524e-05,   1.0000000e+00]])

H14 = np.array([
   [6.6378505e-01,   6.8003334e-01,  -3.1230335e+01],
   [-1.4495500e-01,   9.7128304e-01,   1.4877420e+02],
   [4.2518504e-04,  -1.3930359e-05,   1.0000000e+00]])

# need the homographies going the other direction
H21 = np.linalg.inv(H12)
H31 = np.linalg.inv(H13)
H41 = np.linalg.inv(H14)

# ensure they are homogeneous by dividing by the last entry
H21 = H21/H21[-1,-1]
H31 = H31/H31[-1,-1]
H41 = H41/H41[-1,-1]

# warp the locations loc2, loc3, loc4 to the coordinates of img1
est21 = np.matmul(H21, loc2)
est31 = np.matmul(H31, loc3)
est41 = np.matmul(H41, loc4)

# make homogeneous, toss the final 1
est21 = est21[:-1]/est21[-1]
est31 = est31[:-1]/est31[-1]
est41 = est41[:-1]/est41[-1]

# remove the last coordinate, take an average
avgest = (est21 + est31 + est41)/3
estloc = np.around(avgest).astype(int)

# output
print("Estimations:"
    "\n2 -> 1:   ", est21,
    "\n3 -> 1:   ", est31,
    "\n4 -> 1:   ", est41,
    "\nAvg loc:  ", avgest, 
    "\nEst loc:  ", estloc,
    "\nTrue loc: ", loc1[:-1])

# show images
cv2.circle(img1, (estloc[0], estloc[1]), 2, (0,0,255), -1) # filled
cv2.circle(img1, (estloc[0], estloc[1]), 20, (255,255,255)) # outline
cv2.imshow('img1-est', img1)
cv2.waitKey(0)

cv2.circle(img2, (loc2[0], loc2[1]), 2, (0,0,255), -1) # filled
cv2.circle(img2, (loc2[0], loc2[1]), 20, (255,255,255)) # outline
cv2.imshow('img2-loc', img2)
cv2.waitKey(0)

cv2.circle(img3, (loc3[0], loc3[1]), 2, (0,0,255), -1) # filled
cv2.circle(img3, (loc3[0], loc3[1]), 20, (255,255,255)) # outline
cv2.imshow('img3-log', img3)
cv2.waitKey(0)

cv2.circle(img4, (loc4[0], loc4[1]), 2, (0,0,255), -1) # filled
cv2.circle(img4, (loc4[0], loc4[1]), 20, (255,255,255)) # outline
cv2.imshow('img4-log', img4)
cv2.waitKey(0)

cv2.destroyAllWindows()