当前位置:   article > 正文

python opencv 拼接失败_使用OpenCV + Python拼接四个图像

python opencv 图像匹配不准

目标:

在过去的两周中,我一直在尝试找出如何转换以下图像:

对于看起来像这样的人(可能不完全匹配,因为此图像是在其他时间拍摄的):

镜头校正(必要吗?):

我注意到的第一件事是,仅将图像切片并覆盖这四个部分并不能完美地工作,因为某些线条的曲率不匹配。例如,中线在第二个切片中向左弯曲,在第三个切片中向右弯曲。这种弯曲看起来像是桶形失真,因此我尝试同时使用参数化的镜头校正功能(将k1,k2和k3传递给OpenCV)并使用lensfun。由于lensfun数据库不包含我的相机品牌或型号(它是AXIS相机),并且我不知道镜头的品牌或型号(它是作为相机的一部分制造的),因此我编写了一个小脚本来使用具有各种参数的各种镜头,然后浏览数千种输出图像,直到我发现一个看起来像相对直线的图像为止:

使用“ samyang 12mm f / 2.8 Fish-Eye ED AS NCS”镜头和镜头乐趣中的“ Canon EOS 10D”相机进行了校正。它可能并不完美,但是我认为它已经足够接近第二步了。

校正镜头畸变后,第二个问题是两个切片中的同一条线指向不同的方向,应使用简单的透视变换对其进行校正。因此,我开始了漫长的探索,以找出用于此透视图转换的适当参数。

失败的尝试:

1.使用SciPy

我首先编写一个成本函数来判断给定参数集(重叠像素应匹配)的“质量”,然后应用SciPy的求解器进行求解。我对成本函数进行了一些调整(应用高斯模糊,按比例缩小图像,对图像进行灰度缩放,使用Sobel运算符获得渐变),在重叠后仅查看“接缝”两侧的像素,而不是整个重叠区域等),但始终找不到好的解决方案。在大多数情况下,结果看上去都比原始相机图像差:

2.使用数学

当失败时,我尝试应用数学计算正确的透视变换。我知道相机的FOV(根据规格表),我知道图像的宽度和高度,我知道传感器的尺寸(根据规格表),并使用量角器测量了镜头之间的角度。然后,我使用针孔模型计算了图像平面上点的预期(x,y)值,以及需要进行哪些变换才能对其进行校正。结果看起来比SciPy好,但仍然令人沮丧。

3.使用OpenCVStitcher

之后,我尝试使用OpenCV的内置Stitcher类。但是,由于图像之间的重叠不足,无法将切片2和3缝合在一起(大约10%的时间甚至无法将切片1和2缝合在一起,大概是由于RANSAC的不确定性)。即使成功了,缝线也不是那么好:

4.使用ORB和OpenCVfindHomography

最近,我尝试使用带遮罩的ORB(仅在重叠区域中查找特征)和OpenCV的findHomography功能来创建自定义版本的Stitcher。尽管比赛看起来很有希望,但最终的缝制仍然不是最佳的:

我开始怀疑我的方法(切片->镜头校正->透视变换->覆盖)存在缺陷,并且有更好的方法可以做到这一点。

5.更新了ORB /findHomography

我更新了特征检测,以消除Y坐标显着不同的任何匹配项(例如,将表的白色与灯光的白色进行匹配)。完成此操作后,我的匹配特征数量从〜110降至〜55,但是单应性得到了显着改善。这是切片1/2和2/3更新后的针迹:

除非有人能告诉我我要解决所有这些错误,否则我将继续执行此策略,并增加以下步骤:

切片图像

镜头校正每一片

透视变换切片2或3,以使侧面线为水平,而球场中线为垂直

使用ORB +匹配过滤+ findHomography迭代对齐并拼接相邻切片

最终说完了,我想尝试计算从输入像素到输出像素的映射,这样我们就不会每帧进行所有这些复杂的工作(镜头校正,ORB,findHomography等)。我们将为每个摄像机执行一次,将映射保存到文件中的某个位置,然后我们可以使用以下命令将输入​​视频实时地逐帧映射到输出视频cv2.remap

注意:

我发布的第二张图片显示了“预期的输出”,直接来自相关的相机。它可以配置为以30 fps返回第一张图像,或以10 fps返回第二张图像。我们希望在功能更强大的计算机上执行离机拼接,因此我们可以获取30 fps,但仍具有单张图像。

AXIS提供了一个用于在相机外进行拼接的SDK,但是该SDK仅适用于Windows,我们的大多数技术堆栈都是Linux,而我们的大多数开发计算机都是Mac OS。我曾经使用Windows计算机尝试研究它们提供的拼接SDK,但是我没有运气来编译和运行它。他们的示例代码不断抛出错误,而且我从来没有遇到过让Visual Studio或C ++对我很好玩的运气。

解决方案

我的建议是训练自动编码器。使用第一个图像作为输入,第二个图像作为输出,如去噪自动编码器:

请注意,如果在中间层创建的Botteleneck太小,则可能会失去分辨率。

同样,变分自动编码器提供了一个潜在矢量,但遵循相同的原理工作。

您可以修改以下代码:

denoise=Sequential()denoise.add(Convolution2D(20,3,3,border_mode='valid',input_shape=input_shape))denoise.add(BatchNormalization(mode=2))denoise.add(Activation('relu'))denoise.add(UpSampling2D(size=(2,2)))denoise.add(Convolution2D(20,3,3,init='glorot_uniform'))denoise.add(BatchNormalization(mode=2))denoise.add(Activation('relu'))denoise.add(Convolution2D(20,3,3,init='glorot_uniform'))denoise.add(BatchNormalization(mode=2))denoise.add(Activation('relu'))denoise.add(MaxPooling2D(pool_size=(3,3)))denoise.add(Convolution2D(4,3,3,init='glorot_uniform'))denoise.add(BatchNormalization(mode=2))denoise.add(Activation('relu'))denoise.add(Reshape((28,28,1)))sgd=SGD(lr=learning_rate,momentum=momentum,decay=decay_rate,nesterov=False)denoise.compile(loss='mean_squared_error',optimizer=sgd,metrics=['accuracy'])denoise.summary()denoise.fit(x_train_noisy,x_train,nb_epoch=50,batch_size=30,verbose=1)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/81312
推荐阅读
相关标签
  

闽ICP备14008679号