Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Opencv 反转实值索引网格_Opencv_Math_Image Processing_Remap_Bilinear Interpolation - Fatal编程技术网

Opencv 反转实值索引网格

Opencv 反转实值索引网格,opencv,math,image-processing,remap,bilinear-interpolation,Opencv,Math,Image Processing,Remap,Bilinear Interpolation,OpenCV使用实值索引网格通过双线性插值对图像中的值网格进行采样,并将采样网格作为新图像返回 准确地说,让我们: A = an image X = a grid of real-valued X coords into the image. Y = a grid of real-valued Y coords into the image. B = remap(A, X, Y) 然后对于所有像素坐标i,j B[i, j] = A(X[i, j], Y[i, j]) 其中,圆括号表示法

OpenCV使用实值索引网格通过双线性插值对图像中的值网格进行采样,并将采样网格作为新图像返回

准确地说,让我们:

A = an image 
X = a grid of real-valued X coords into the image. 
Y = a grid of real-valued Y coords into the image.
B = remap(A, X, Y)
然后对于所有像素坐标i,j

B[i, j] = A(X[i, j], Y[i, j]) 
其中,圆括号表示法
A(x,y)
表示使用双线性插值,使用浮点值坐标
x
y
求解图像A的像素值

我的问题是:给定索引网格
X
Y
,如何生成“逆网格”
X^-1
Y^-1
,从而:

X(X^-1[i, j], Y^-1[i, j]) = i
Y(X^-1[i, j], Y^-1[i, j]) = j

对于所有整数像素坐标
i,j

FWIW,图像和索引贴图X和Y的形状相同。但是,索引映射X和Y没有先验结构。例如,它们不一定是仿射或刚性变换。它们甚至可能是不可变的,例如,如果
X,Y
A
中的多个像素映射到B中的同一精确像素坐标。我正在寻找一种方法,如果存在一个逆映射,可以找到一个合理的逆映射


解决方案不需要基于OpenCV,因为我没有使用OpenCV,而是使用另一个库,它具有
remap()
实现。尽管欢迎任何建议,但我特别热衷于“数学上正确”的东西,即如果我的地图m是完全可逆的,那么该方法应该在机器精度的小范围内找到完美的逆。

没有任何标准方法可以使用OpenCV实现

如果您正在寻找一个完整的即用解决方案,我不确定我是否能提供帮助,但我至少可以描述一种我几年前用于完成此任务的方法

首先,您应该创建与源图像尺寸相同的重映射贴图。为了简化插值,我创建了尺寸更大的地图,并在最后一步将它们裁剪成合适的大小。然后,您应该使用以前的重新映射贴图中存在的值填充它们(并不是很难:只需对它们进行迭代,如果贴图坐标x和y位于图像的范围内,则将它们的行和列作为新的y和x,并放置到新贴图的旧x和y列和行中)。这是一个相当简单的解决方案,但它给出了相当好的结果。为了达到完美的效果,您应该使用插值方法和相邻像素将旧的x和y插值为整数值

在此之后,您应该手动重新映射像素颜色,或者用像素坐标完全填充重新映射的贴图,并使用OpenCV的版本

您将遇到相当具有挑战性的任务:应该在空白区域内插值像素。换句话说,您应该获取距离最近的非零像素坐标的距离,并根据这些距离混合颜色(如果重新映射颜色)或坐标(如果继续进行完整贴图计算)。实际上,对于线性插值来说也不难,您甚至可以在中查看
remap()
实现。对于NN插值,它将使我更简单-只需取最近邻的颜色/坐标


最后一项任务是从重新映射的像素区域的边界外推区域。OpenCV的算法也可以用作参考。

据我所知,您有一个原始图像和一个变换图像,您希望在不知道的情况下恢复已应用的变换的性质,但假设它是合理的,如旋转或鱼眼扭曲

我要尝试的是在索引图像和普通图像中对图像进行阈值化以将其转换为二进制。然后尝试识别对象。大多数映射至少会保留连接性和Euler数,大多数索引中最大的对象仍然是平原中最大的对象


然后为匹配的图像/索引对花点时间,看看是否可以删除平移、旋转和缩放。这将为您提供几个反向贴图,然后您可以尝试将它们缝合在一起。(如果变换不简单,则很难,但仅重建任何变换的一般问题无法解决)。

如果映射是从单应映射
H
派生的,则可以反转
H
,并直接使用
cv::initundortortymap()
创建逆映射

e、 g.在Python中:

将numpy作为np导入。
地图大小=()填写地图大小
H_inv=np.linalg.inv(H)
map1,map2=cv2.InitUnderdistortyMap(cameraMatrix=np.eye(3),distCoeffs=np.Zero(5),R=H_inv,newCameraMatrix=np.eye(3),size=map_size,m1type=cv2.CV_32FC1)
OpenCV文档说明了关于
initUnderortRectiptyMap()

该函数实际上为逆映射构建映射
remap()
使用的算法。也就是说,对于图像中的每个像素(u,v) 对于目标图像,函数计算相应的 源图像中的坐标

如果你刚刚给了地图,你必须自己做。 Hoewever说,新地图坐标的插值并不简单,因为一个像素的支持区域可能非常大

下面是一个简单的Python解决方案,它通过进行点到点映射来反转映射。这可能会留下一些未指定的坐标,而其他坐标将被更新多次。所以地图上可能有洞

下面是一个小型Python程序,演示了这两种方法:

导入cv2
将numpy作为np导入
def反转贴图(贴图x、贴图y):
断言(map_x.shape==map_y.shape)
行=贴图×形状[0]
cols=map_x.shape[1]
m_x=np.one(映射x.shape,dtype=map_x.dtype)*-1
m_y=np.one(映射y.shape,dtype=map_y.dtype)*-1
对于范围内的i(行):
对于范围内的j(cols):
i=圆形(映射y[i,j])
j_ux=round(map_x[i,j])

如果0OP在这里。我想我找到了答案。我还没有实现它,如果有人提出一个不那么复杂的解决方案
X^-1(X[i, j], Y[i, j]) = i
Y^-1(X[i, j], Y[i, j]) = j
B[k, l, :] == A(M[k, l, 0], M[k, l, 1], :) 
for all k, l in B's coords.
B = A(M)
Find N s.t. A \approx B(N)
Find N = argmin_N || M(N) - I_n ||
I_n[i, j, :] == [i, j]
for all i, j
N[M[k, l, 0], M[k, l, 1], :] = [k, l]
for all k, l
N[M] = I_m
N = zeros(size=(A.shape[0], A.shape[1], 2))
B[i, j] = A(X[i, j], Y[i, j])   
A[x, y] = B(Xinv[x,y],Yinv[x,y])
map_x, map_y = cv2.initUndistortRectifyMap(K, D, None, new_K, image_size, cv2.CV_32FC1)

points =  np.stack([map_x.flatten(), map_y.flatten()], axis=1)
grid = np.mgrid[:map_x.shape[0], :map_y.shape[1]]
values = grid.reshape(2, -1).T[..., ::-1] 

from scipy.interpolate import griddata
grid_y, grid_x = grid
map_back = griddata(points, values, (grid_x, grid_y), method='cubic').astype(map_undistort.dtype)
map_undistort, _ = cv2.initUndistortRectifyMap(K, D, None, new_K, image_size, cv2.CV_32FC2)
points = map_undistort.reshape(-1, 2)