图像拼接小实验开发日志和笔记

图像拼接小实验开发日志和笔记

b y   t i a n . z   D e c by \ tian.z \ Dec by tian.z Dec - 2021 2021 2021

    1. 技术路线
    • 1.1. 开发环境
    • 1.2. 图像配准
      • 1.2.1. 特征提取
      • 1.2.2. 特征匹配
      • 1.2.3. 图像变换
    • 1.3. 图像合成
    • 1.4. 扩展性思考
    1. 具体实现与调试问题
    • 2.1. 总体架构
    • 2.2. opencv读取图像
    • 2.3. CMake链接glog
    • 2.4. 调用opencv的surf实现
    • 2.5. CMake编译多个.cpp文件
    • 2.6. cv::DMatch结构
    • 2.7. cv::Mat类的拷贝
    1. 理论
    • 3.1. SURF特征LiangYP
    • 3.2. FLANN快速最近邻搜索ZhaoB
    • 3.3. RANSAC随机一致性采样LiCK
    • 3.4. 单应矩阵Homography与射影变换
    1. 结果
    1. 参考文献

1. 技术路线

参考了文献1

1.1. 开发环境

系统 Ubuntu 20.04
语言 C++11
编译器 CMake 3.16
库依赖 Opencv 3.4.15 ,opencv-contrib , Glog

1.2. 图像配准

关于图像拼接的两篇综述23给出了几种解决方案:

  • 基于模版匹配的方法
  • 基于变换域的匹配方法
  • 基于特征点的匹配方法
  • 基于轮廓的匹配方法

从计算速度、实现难度和课程内容结合的方面综合考虑,本设计采用基于特征点的匹配方法。

1.2.1. 特征提取

对比主流的特征点提取方法,SIFT4 计算量较大,SURF5 作为SIFT的改进提升了运算速度。而ORB6特征主要面对实时性较强的系统设计牺牲了部分精度。综合考虑本设计提取SRUF特征。

1.2.2. 特征匹配

特征匹配时,若使用暴力匹配不但需要很大的计算量,并且还存在大量的误匹配,效果较差。
故本设计使用FLANN匹配提升精度和速度。
但仍会存在误匹配,本设计筛选汉明距离小于最小距离的四倍的点作为好点去除误匹配,这是一种工程上的做法,不一定有理论依据。

1.2.3. 图像变换

本设计假设两张图片的特征点落在同一平面上,这样则可以通过单应性进行匹配分析。
对应地,二视图几何中有一种常见的矩阵:单应矩阵,它描述了两个平面之间的映射关系。
使用RANSAC提升鲁棒性,计算单应矩阵。

1.3. 图像合成

对于图像重叠区域,直接加权平滑算法处理拼接缝

P i x e l = α × P i x e l L + ( 1 − α ) × P i x e l R Pixel=\alpha×Pixel_L+(1-\alpha)× Pixel_R Pixel=α×PixelL+(1α)×PixelR

1.4. 扩展性思考

  • 多张图片?
  • 噪声图像的预处理?
  • 图像尺度不一致? 事实上这一点在本方案中已经解决,surf特征本省具有尺度不变性,射影变换也考虑了尺度变化.
  • 考虑相机的空间旋转和平移? 这一点笔者觉得很值得注意,本方案使用单应矩阵效果并不理想,
    因为事实上这些特征点并不落在同一平面内,模型假设存在缺陷。
    如果使用相似变换将6个自由度的旋转和平移和1个自由度的缩放考虑进来效果会更好,即把相机运动考虑进来.

2. 具体实现与调试问题

2.1. 总体架构

项目地址:https://gitee.com/ztztt/simple-image-mosaic

scr/ 存放源码
include/ 头文件
lib/ 库文件
log/ glog日志
build/ 编译中间文件
bin/ 可执行文件
dataset/ 测试图片

计划先在master分支基于opencv的算法库把功能实现,如果后面有时间和兴趣,在develop分支把个别算法手写实现一下.
(估计是没有)

2.2. opencv读取图像

小知识,为什么我们都用’opencv2’而不是‘opencv3’呢,因为这个2不是版本号,而是基于C++写成的意思,最初opencv是用C写的.来源

刚一上手编译就报错,提示

undefined reference to `cv::Mat::~Mat()
.........

似乎是opencv没有链接进来,仔细检查,发现在src文件夹中的CMakeLists文件里这一行写错了:

target_link_libraries(ImageMosaic
		${THIRD_PARTY_LIBS})

应该写成

target_link_libraries(run
    ${THIRD_PARTY_LIBS})

run是输出的可执行文件

add_executable(run run_image_mosaic.cpp)

再次编译,问题解决

在显示图像的时候别忘了加上waitKey(0);要不然图像一闪而过就看不到了.

2.3. CMake链接glog

在CMakeList

find_package(Glog REQUIRED)
include_directories(${GLOG_INCLUDE_DIRS})

后面还要加上

link_libraries(glog)

才能正确链接到glog,否则编译器会报错

 undefined reference to `google::........

2.4. 调用opencv的surf实现

fatal error: opencv2/nonfree/nonfree.hpp: No such file or directory

显然是没有nonfree这个库,网上给出的解决方案普遍是

sudo apt-get update  
sudo add-apt-repository --yes ppa:xqms/opencv-nonfree  
sudo apt-get update  
sudo apt-get install libopencv-nonfree-dev 

但我陷入了无尽的递归debug,最终我的大脑栈溢出了。网络上有好哥哥指出安装opencv-contrib库即可。
我顺藤摸瓜,来到了opencv-contrib的github
上按照说明装上了这个库,终于可以用哩.注意,这里要安装对应opencv版本的contrib库.
opencv3.4版本的contrib库里的surf在opencv2/xfeatures2d/nonfree.hpp路径下.而毛神的书里写的

#include 

已经不适用了,缅怀.

实际运行的时候,报错

This algorithm is patented and is excluded in this configuration; Set OPENCV_ENABLE_NONFREE CMake option and rebuild the library in function 'create'

提示我们算法受版权保护,让我们改cmakelists里面一个选项,找到它,吧最后的参数OFF改成ON,再编译一遍opencv

OCV_OPTION(OPENCV_ENABLE_NONFREE "Enable non-free algorithms" ON)
OCV_OPTION(INSTALL_CREATE_DISTRIB   "Change install rules to build the distribution package" ON )

还是不行.
笔者在opencv的社区里找到一篇帖子
,有好哥哥给出解决方案,删除cmakecache,带上参数重新用cmake编译一遍opencv:

  cmake -DOPENCV_ENABLE_NONFREE:BOOL=ON -DOPENCV_EXTRA_MODULES_PATH=/home/tian/libs/opencv-3.4.15/opencv_contrib-3.4/modules ..

cmake结束后,可以看见提示 :

	--   OpenCV modules:
	--     To be built:                 aruco bgsegm bioinspired calib3d ccalib core datasets dnn dnn_objdetect dpm face features2d flann freetype fuzzy hdf hfs highgui img_hash imgcodecs imgproc line_descriptor ml objdetect optflow phase_unwrapping photo plot reg rgbd saliency sfm shape stereo stitching structured_light superres surface_matching text tracking ts video videoio videostab viz xfeatures2d ximgproc xobjdetect xphoto
	--     Disabled:                    world
	--     Disabled by dependency:      -
	--     Unavailable:                 cudaarithm cudabgsegm cudacodec cudafeatures2d cudafilters cudaimgproc cudalegacy cudaobjdetect cudaoptflow cudastereo cudawarping cudev cvv java matlab ovis python2 python3
	--     Applications:                tests perf_tests apps
	--     Documentation:               NO
	--     Non-free algorithms:         YES

最后一行告诉我们nonfree的算法已经可以用了,感谢网络上的好哥哥.

2.5. CMake编译多个.cpp文件

笔者第一次实际进行含有多个文件的项目开发,在此记录一下遇到的问题.
在src/目录下新建了文件match.cpp,希望在里面放一些函数的实现;在include/ImageMosaic目录下新建match.h文件,作为头文件进行函数的声明.同时match.cpp文件中#include "ImageMosaic/match.h",match.h文件中定义:

#pragma once
#ifndef MATCH_H
#define MATCH_H
#include "common_include.h"
......
#endif //MATCH_H

这样两个文件就关联起来了.注意,包含commom_include.h时,两个文件的索引会略有区别.

这时直接编译不会通过,还要在src/下的MakeLists中加入:

target_sources(run PUBLIC "match.cpp")

编译通过,程序运行正常.

2.6. cv::DMatch结构

struct CV_EXPORTS DMatch
{
	DMatch() : queryIdx(-1), trainIdx(-1), imgIdx(-1), distance(std::numeric_limits::max()) {}
	DMatch( int _queryIdx, int _trainIdx, float _distance ) :
			queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(-1), distance(_distance) {}
	DMatch( int _queryIdx, int _trainIdx, int _imgIdx, float _distance ) :
			queryIdx(_queryIdx), trainIdx(_trainIdx), imgIdx(_imgIdx), distance(_distance) {}

	int queryIdx; // query descriptor index
	int trainIdx; // train descriptor index
	int imgIdx;   // train image index

	float distance;

	// less is better
	bool operator<( const DMatch &m ) const
	{
		return distance < m.distance;
	}
};

DMatch结构体中包含了同一关键点在两张图片中的索引,可以用迭代器和原始关键点的cv::keyPoint类进行访问,写出来非常优雅.

2.7. cv::Mat类的拷贝

这里坑了我好长时间

浅拷贝

B = A
B(A)

这类拷贝方法仅创建了新的矩阵头,共用同一个内存空间,在修改新对象的时候,旧对象也会改变。

深拷贝

B = A.clone()
A.copyTo(B)

这类拷贝方法为新的矩阵申请了新的内存空间,在修改新对象的时候,旧对象不会改变。

3. 理论

3.1. SURF特征LiangYP

不赘述,参阅文献5 7 ,课程PPT

3.2. FLANN快速最近邻搜索ZhaoB

FLANN是一个在高维空间内快速最近邻域搜索的算法库,它包含了对于最近邻搜索效果最好的一些算法,和一个能够自动根据数据集选取最优的算法和参数的系统。FLANN基于C++写成并提供C,MATLAB,Python和Ruby的接口。翻译自项目Github地址。

文献8中,介绍了FLANN中使用的算法,包括随机kd树算法、优先搜索k-means树算法等

3.3. RANSAC随机一致性采样LiCK

RANSAC9 是“RANdom SAmple Consensus(随机抽样一致)”的缩写。它可以从一组包含“局外点”的观测数据集中,通过迭代方式估计数学模型的参数。它是一种不确定的算法——它有一定的概率得出一个合理的结果;为了提高概率必须提高迭代次数。
https://blog.csdn.net/robinhjwy/article/details/79174914

3.4. 单应矩阵Homography与射影变换

单应(Homography)是射影几何中的概念,又称为射影变换。它把一个射影平面上的点(三维齐次矢量)映射到另一个射影平面上,并且把直线映射为直线,具有保线性质。总的来说,单应是关于三维齐次矢量的一种线性变换,可以用一个 3 × 3 3×3 3×3的非奇异矩阵 H H H表示

x 1 = H x 2 x_1 = Hx_2 x1=Hx2

这是一个齐次坐标的等式, H H H乘以一个非零的比例因子上述等式仍然成立,即 H H H是一个 3 × 3 3×3 3×3齐次矩阵,具有8个未知量。
假设已经取得了两图像之间的单应,则可单应矩阵H可以将两幅图像关联起来

( u 1 v 1 1 ) = H ( u 2 v 2 1 ) \left(\begin{array}{c}u_1\\v_1\\1\end{array}\right) = H\left(\begin{array}{c}u_2\\v_2\\1\end{array}\right) u1v11=Hu2v21

其中, ( u 1 , v 1 , 1 ) T (u_1,v_1,1)^T (u1,v1,1)T表示图像1中的像点 ( u 2 , v 2 , 1 ) T (u_2,v_2,1)^T (u2,v2,1)T是图像2中的像点,也就是可以通过单应矩阵 H H H将图像2变换到图像1。这有了很多实际的应用,例如图像的校正、对齐以及在SLAM中估计两个相机间的运动。

单应矩阵定义为

H = s ( f x γ u 0 0 f y v 0 0 0 1 ) ( r 1 r 2 t ) H = s\left(\begin{array}{c}f_x & \gamma & u_0\\0 & f_y & v_0\\0 & 0 & 1\end{array}\right)\left(\begin{array}{c}r_1 & r_2 & t\end{array}\right) H=sfx00γfy0u0v01(r1r2t)

由尺度、相机内参、外参相乘,共八个自由度,理论上四对特征点约束可解。

但实际应用中,匹配的特征点往往会远多于四对。这时就可以构建一个过约束的方程组,把问题转换为一个最小二乘的优化问题。

4. 结果

终端运行可执行文件,输出特征点匹配的数量和求取的单应矩阵
图像拼接小实验开发日志和笔记_第1张图片

输出特征点匹配的结果
图像拼接小实验开发日志和笔记_第2张图片

输出未处理接缝直接拼接的结果
图像拼接小实验开发日志和笔记_第3张图片

输出平滑接缝的最终结果
图像拼接小实验开发日志和笔记_第4张图片

5. 参考文献


  1. 徐启文, 唐振民, 姚亚洲. 基于改进SURF算法的图像拼接研究[J]. 南京理工大学学报, 2021, 45(2):8. ↩︎

  2. 裴红星, 刘金达, 葛佳隆,等. 图像拼接技术综述[J]. 郑州大学学报:理学版, 2019, 51(4):11. ↩︎

  3. 王娟, 师军, 吴宪祥. 图像拼接技术综述[J]. 计算机应用研究, 2008, 25(7):5. ↩︎

  4. Lowe D G . Distinctive Image Features from Scale-Invariant Keypoints[J]. International Journal of Computer Vision, 2004, 60(2):91-110. ↩︎

  5. Bay H , Tuytelaars T , Gool L V . SURF: Speeded up robust features[C]// Proceedings of the 9th European conference on Computer Vision - Volume Part I. Springer-Verlag, 2006. ↩︎ ↩︎

  6. Rublee E , Rabaud V , Konolige K , et al. ORB: an efficient alternative to SIFT or SURF[C]// IEEE International Conference on Computer Vision, ICCV 2011, Barcelona, Spain, November 6-13, 2011. IEEE, 2011. ↩︎

  7. R.C.冈萨雷斯, P.温茨. 数字图象处理[M]. 科学出版社, 1981. ↩︎

  8. Muja M , Lowe D G . Fast Approximate Nearest Neighbors with Automatic Algorithm Configuration[C]// International Conference on Computer Vision Theory & Application Vissapp. 2009. ↩︎

  9. Fischler M A , Bolles R C . Random Sample Consensus: A Paradigm for Model Fitting with Applications to Image Analysis and Automated Cartography - ScienceDirect[J]. Readings in Computer Vision, 1987:726-740. ↩︎

你可能感兴趣的:(笔记,计算机视觉,opencv,c++)