opencv自带的stitching速度很慢,而且对多图容易出错,好象对竖着拍摄的图(高>宽)不能用。
其中一个最大的原因是每一张图都要和其它的图去匹配,如果有10张图,除去自身不用匹配外,
要匹配 10X(10-1) = 90 次。所以慢得不能忍受。(等了很久很久,咚的出错,这感受真的不好)
我们拍摄全景图的时候都是从左到右,或者从右到左,前后两张图一般有部分重合。
所以我们这里只对前后两张图匹配,然后连成一串。
流程:
1。从列表(list.txt)文件装载图像文件名
2。前后匹配
3。计算匹配图像的相对位置
4。以第一张图左上角点为原点,找到所有图的位置(同一坐标系)
5。再计算最小,最大边界,并构建一个大图
6。再把所有图像放到一个大图中
main:
int main ()
{
/* 特征点的提取与匹配 */
vector image_names; // image_names[i]表示第i个图像的名称
LoadImageNamesFromFile("list0.txt",image_names);//从list.txt文件装载图像文件名
vector> image_keypoints; // image_keypoints[i]表示第i个图像的特征点
vector image_descriptor; // image_descriptor[i]表示第i个图像的特征向量描述符
//vector> image_colors; // image_colors[i]表示第i个图像特征点的颜色
vector> image_matches; // image[i]表示第i幅图像和第i+1幅图像特征点匹配的结果
extract_features (image_names, image_keypoints, image_descriptor/*, image_colors*/); // 提取特征点
match_features2 (image_descriptor, image_matches); // 特征点匹配
//gms_match_features(image_keypoints,img0.size(),image_matches);
//单应性过滤特征点
for (unsigned int i=0;i());//匹配完清除内存
Mat img0 = imread(image_names[0]);//读出一个图
img0= mynarrow(img0);//如果太大缩小一点。(>2400*1200的)
//显示匹配
//for (unsigned int i=0;i position_da; // position_da[i]表示第i个图像在大图中的位置(左上角)
Point2f position_s=Point2f(0,0);
position_da.push_back (position_s); // 第1个图像为原点
for (unsigned int i=0;i points1, points2;
get_match_points (image_keypoints[i], image_keypoints[i+1] ,image_matches[i], points1, points2);
unsigned int shi=image_matches[i].size ();
shi=(shi>10)?10:shi;//只取前十个
Point2f a;
for(unsigned int j=0;j>().swap(image_keypoints);//已经用不到了,清除容器并最小化它的容量
//再计算最小,最大边界
int xmin=0,xmax=0,ymin=0,ymax=0;
for (unsigned int i=1;ixmax)?position_da[i].x:xmax;
ymin=(position_da[i].yymax)?position_da[i].y:ymax;
}
//计算大图宽高
int h = img0.rows + ymax-ymin;//拼接图行数(高度)
int w = img0.cols + xmax-xmin;//拼接图列数(宽度)
Mat stitch = Mat::zeros(h, w, CV_8UC3);
//再把所有图像放到一个大图中(拼接)
for (unsigned int i=0;i
用到的函数:
//如果图像太大缩小一半
Mat mynarrow(Mat img)
{
Mat dst ;//读出一个图
if(img.rows*img.cols>2400*1200)
resize(img,dst,Size(),0.5,0.5);
else
dst=img.clone();
return dst;
}
在所有读图的地方都要用上。
过滤函数:
//用单应性过滤匹配
bool refineMatchesWithHomography(const std::vector& queryKeypoints,
const std::vector& trainKeypoints,
float reprojectionThreshold,
std::vector& matches//,
//cv::Mat& homography
)
{ cv::Mat homography;
const int minNumberMatchesAllowed = 4;
if (matches.size() < minNumberMatchesAllowed)
return false;
// 为 cv::findHomography 准备数据
std::vector queryPoints(matches.size());
std::vector trainPoints(matches.size());
for (size_t i = 0; i < matches.size(); i++)
{
queryPoints[i] = queryKeypoints[matches[i].queryIdx].pt;
trainPoints[i] = trainKeypoints[matches[i].trainIdx].pt;
}
// 查找单应矩阵并获取内点掩码
std::vector inliersMask(matches.size());
homography = cv::findHomography(queryPoints,
trainPoints,
CV_FM_RANSAC,
reprojectionThreshold,
inliersMask);
std::vector inliers;
for (size_t i=0; i minNumberMatchesAllowed;
}
其它的在前一个文章中
效果图:
38个图合成
75个图合成
由于原始图像太大,上传是缩小了。虽然效果不是很理想,但速度很快
第一个拍了2圈,第二个拍了3圈,如果分别分成2次和3次合成,可能不一样。
结束
-----------------------分隔线---------------------------------
应有人要完整的程序,现修改一下:
请把-main- "复制" 保存为 “快主main函数.cpp”
再把-mynarrow函数- "复制" 保存为 "mynarrow函数.cpp"
把-过滤函数- "复制" 保存为 "过滤函数.cpp"
最后把下面的函数- "复制" 保存为 "获取匹配点坐标.cpp"
//获取匹配点坐标
/********************************************************************************************************
参数:
keypoints1 第一张图片的特征点; keypoints2 第二张图片的特征点; matches 匹配的结果; (points1[i], points2[i]) 第
i个匹配的特征点对。
功能:
利用两张图片的特征点keypoints1、keypoints2和匹配的结果matches,可以得到两个数组points1和points2,
(points1[i], points2[i])表示第i个匹配的特征点对。
*********************************************************************************************************/
void get_match_points (
vector keypoints1,
vector keypoints2,
vector matches,
vector& points1,
vector& points2
)
{
for (int i = 0; i < matches.size (); i++)
{
points1.push_back (keypoints1[matches[i].queryIdx].pt);
points2.push_back (keypoints2[matches[i].trainIdx].pt);
}
}
完整的程序为:
#include "头包含.cpp"
#include "用到的函数.cpp"
//#include "主main函数.cpp"
//=================分隔线(之前在上一篇中)=======================
#include "mynarrow函数.cpp"
#include "过滤函数.cpp"
#include "获取匹配点坐标.cpp"
#include "快主main函数.cpp"