#include <iostream>
#include <fstream>
#include <string>
#include "opencv2/opencv_modules.hpp"
#include <opencv2/core/utility.hpp>
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/stitching/detail/autocalib.hpp"
#include "opencv2/stitching/detail/blenders.hpp"
#include "opencv2/stitching/detail/timelapsers.hpp"
#include "opencv2/stitching/detail/camera.hpp"
#include "opencv2/stitching/detail/exposure_compensate.hpp"
#include "opencv2/stitching/detail/matchers.hpp"
#include "opencv2/stitching/detail/motion_estimators.hpp"
#include "opencv2/stitching/detail/seam_finders.hpp"
#include "opencv2/stitching/detail/warpers.hpp"
#include "opencv2/stitching/warpers.hpp"
#include "opencv2/xfeatures2d/nonfree.hpp"
using namespace std;
using namespace cv;
using namespace cv::detail;
// Default command line args 默认命令行参数
vector<String> img_names;
bool preview = false;
bool try_cuda = false;
double work_megapix = 0.6;
double seam_megapix = 0.1;
double compose_megapix = -1;
float conf_thresh = 1.f;
#ifdef HAVE_OPENCV_XFEATURES2D
string features_type = "surf";
#else
string features_type = "orb";
#endif
string matcher_type = "homography";
string estimator_type = "homography";
string ba_cost_func = "ray";
string ba_refine_mask = "xxxxx";
bool do_wave_correct = true;
WaveCorrectKind wave_correct = detail::WAVE_CORRECT_HORIZ;
bool save_graph = false;
std::string save_graph_to;
string warp_type = "cylindrical";
int expos_comp_type = ExposureCompensator::GAIN_BLOCKS;
int expos_comp_nr_feeds = 1;
int expos_comp_nr_filtering = 2;
int expos_comp_block_size = 32;
float match_conf = 0.3f;
string seam_find_type = "gc_color";
int blend_type = Blender::MULTI_BAND;
int timelapse_type = Timelapser::AS_IS;
float blend_strength = 5;
string result_name = "result.jpg";
bool timelapse = false;
int range_width = -1;
double seam_work_aspect = 1;
int main(int argc, char* argv[])
{
double work_scale = 1, seam_scale = 1, compose_scale = 1;
bool is_work_scale_set = false, is_seam_scale_set = false, is_compose_scale_set = false;
//获取文件夹图片的路径
cv::String filepath = "C:\\Users\\Lenovo-Gu\\Desktop\\photo\\*.jpg"; //!!!更改为图片所在文件夹路径!!!
glob(filepath, img_names, false);
size_t num_images = img_names.size();
Ptr<Feature2D> finder = xfeatures2d::SIFT::create();
//用数组存储所有的图片以及图片的特征点、尺寸
Mat full_img, img;
vector<ImageFeatures> features(num_images); //声明一个初始大小为num_images的ImageFeatures
vector<Mat> images(num_images); //num_images个图像组成的数组
vector<Size> full_img_sizes(num_images); //num_images个图像的尺寸组成的数组
for (int i = 0; i < num_images; ++i)
{
full_img = imread(samples::findFile(img_names[i])); //cv::samples::findFile(const cv::String & relative_path, bool required = true, bool silentMode = false)
full_img_sizes[i] = full_img.size();
//double work_scale = min(1.0, sqrt(0.6 * 1e6 / full_img.size().area()));
//resize(full_img, img, Size(), work_scale, work_scale, INTER_LINEAR_EXACT);
img = full_img;
computeImageFeatures(finder, full_img, features[i]); //计算图像特征
features[i].img_idx = i;
cout << "Features in image #" << i + 1 << ": " << features[i].keypoints.size() << endl;
images[i] = img.clone();
}
full_img.release();
img.release();
for (int i = 0; i < num_images; ++i)
{
cout << "image #" << i + 1 << "size:" << full_img_sizes[i] << endl;
}
//两两匹配
//vector<MatchesInfo> pairwise_matches; //表示特征匹配信息变量
//BestOf2NearestMatcher matcher(false, 0.3f); //定义特征匹配器,2NN方法
//matcher(features, pairwise_matches); //进行特征匹配
//matcher->collectGarbage();
//
vector<MatchesInfo> pairwise_matches;
Ptr<FeaturesMatcher> matcher = makePtr<BestOf2NearestMatcher>(false, 0.3f, 6, 6);
// BestOf2NearestMatcher matcher;
(*matcher)(features, pairwise_matches);
matcher->collectGarbage();
ofstream f(save_graph_to.c_str()); //ofstream:c++ 写操作
f << matchesGraphAsString(img_names, pairwise_matches, conf_thresh);
vector<int> indices = leaveBiggestComponent(features, pairwise_matches, conf_thresh);
vector<Mat> img_subset; //图像的子集
vector<String> img_names_subset; //图像名字的子集
vector<Size> full_img_sizes_subset;
for (size_t i = 0; i < indices.size(); ++i)
{
img_names_subset.push_back(img_names[indices[i]]);
img_subset.push_back(images[indices[i]]);
full_img_sizes_subset.push_back(full_img_sizes[indices[i]]);
}
images = img_subset; //确信来自同一全景图的图像 重新组成 images
img_names = img_names_subset; //确信来自同一全景图的图像名字 重新组成img_names
full_img_sizes = full_img_sizes_subset; //新的尺寸集合
// Check if we still have enough images
num_images = static_cast<int>(img_names.size());
if (num_images < 2)
{
//LOGLN("Need more images");
return -1;
}
//·························································
Ptr<Estimator> estimator;
if (estimator_type == "affine")
estimator = makePtr<AffineBasedEstimator>();
else
estimator = makePtr<HomographyBasedEstimator>();
vector<CameraParams> cameras; //相机参数
if (!(*estimator)(features, pairwise_matches, cameras))
{
cout << "Homography estimation failed.\n"; //单应性估计失败了。
return -1;
}
for (size_t i = 0; i < cameras.size(); ++i)
{
Mat R;
cameras[i].R.convertTo(R, CV_32F);
cameras[i].R = R;
//LOGLN("Initial camera intrinsics #" << indices[i] + 1 << ":\nK:\n" << cameras[i].K() << "\nR:\n" << cameras[i].R);
}
//·······················································
Ptr<detail::BundleAdjusterBase> adjuster; //光束平差法,精确相机参数
if (ba_cost_func == "reproj") adjuster = makePtr<detail::BundleAdjusterReproj>();
else if (ba_cost_func == "ray") adjuster = makePtr<detail::BundleAdjusterRay>();
else if (ba_cost_func == "affine") adjuster = makePtr<detail::BundleAdjusterAffinePartial>();
else if (ba_cost_func == "no") adjuster = makePtr<NoBundleAdjuster>();
else
{
cout << "Unknown bundle adjustment cost function: '" << ba_cost_func << "'.\n";
return -1;
}
adjuster->setConfThresh(conf_thresh);
Mat_<uchar> refine_mask = Mat::zeros(3, 3, CV_8U);
if (ba_refine_mask[0] == 'x') refine_mask(0, 0) = 1;
if (ba_refine_mask[1] == 'x') refine_mask(0, 1) = 1;
if (ba_refine_mask[2] == 'x') refine_mask(0, 2) = 1;
if (ba_refine_mask[3] == 'x') refine_mask(1, 1) = 1;
if (ba_refine_mask[4] == 'x') refine_mask(1, 2) = 1;
adjuster->setRefinementMask(refine_mask);
if (!(*adjuster)(features, pairwise_matches, cameras))
{
cout << "Camera parameters adjusting failed.\n"; //相机参数调整失败。
return -1;
}
//·························································
// Find median focal length 求中焦距
vector<double> focals;
for (size_t i = 0; i < cameras.size(); ++i)
{
// LOGLN("Camera #" << indices[i] + 1 << ":\nK:\n" << cameras[i].K() << "\nR:\n" << cameras[i].R);
focals.push_back(cameras[i].focal);
}
sort(focals.begin(), focals.end());
float warped_image_scale;
if (focals.size() % 2 == 1)
warped_image_scale = static_cast<float>(focals[focals.size() / 2]);
else
warped_image_scale = static_cast<float>(focals[focals.size() / 2 - 1] + focals[focals.size() / 2]) * 0.5f;
//··························································
if (do_wave_correct) //波形矫正
{
vector<Mat> rmats;
for (size_t i = 0; i < cameras.size(); ++i)
rmats.push_back(cameras[i].R.clone());
waveCorrect(rmats, wave_correct);
for (size_t i = 0; i < cameras.size(); ++i)
cameras[i].R = rmats[i];
}
//LOGLN("Warping images (auxiliary)... "); // 扭曲的图像(辅助)
#if ENABLE_L
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
版本号:OpenCV-4.1.1、opencv_contrib-4.1.1、Visual Studio 2015。 基于OpenCV4.1.1帮助文档内Examples的stitching_detail.cpp改编。 包括提取特征点、特征点匹配、特征点提纯、预估相机参数、全面细化相机参数、图像变换、补偿曝光器、边缘拼接器、图像融合等功能,可对两张以上的图片进行融合,得到效果很好的全景图。 运行结果:https://blog.csdn.net/GIS_feifei/article/details/102875389
资源推荐
资源详情
资源评论
收起资源包目录
quanjing_save.rar (21个子文件)
quanjing_save
quanjing_save.VC.db 13.33MB
quanjing_save.sln 1KB
.vs
quanjing_save
v14
.suo 21KB
x64
Debug
quanjing_save.exe 850KB
quanjing_save.pdb 5.57MB
quanjing_save.ilk 3.18MB
quanjing_save
result.jpg 995KB
x64
Debug
vc140.pdb 1.79MB
vc140.idb 931KB
main.obj 4.53MB
quanjing_save.tlog
CL.read.1.tlog 27KB
link.read.1.tlog 3KB
link.write.1.tlog 470B
CL.write.1.tlog 484B
quanjing_save.lastbuildstate 192B
link.command.1.tlog 1KB
CL.command.1.tlog 614B
quanjing_save.log 194B
main.cpp 19KB
quanjing_save.vcxproj.filters 945B
quanjing_save.vcxproj 7KB
共 21 条
- 1
资源评论
- 清风徐来Groot2021-04-25资料不是很全,只有博客上的代码,也没有库
GIS_飞飞飞
- 粉丝: 458
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功