標籤:des ar io color os 使用 sp for on
#include <iostream>#include <fstream>#include <string>#include "opencv2/opencv_modules.hpp"#include "opencv2/highgui/highgui.hpp"#include "opencv2/stitching/detail/autocalib.hpp"#include "opencv2/stitching/detail/blenders.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/util.hpp"#include "opencv2/stitching/detail/warpers.hpp"#include "opencv2/stitching/warpers.hpp"#include<time.h>using namespace std;using namespace cv;using namespace cv::detail;//定義參數vector<string> img_names;bool try_gpu = false;double work_megapix = 0.6;//映像匹配的解析度大小,映像的面積尺寸變為work_megapix*100000double seam_megapix = 0.1;//拼接縫像素的大小double compose_megapix =0.6;//拼接解析度float conf_thresh = 1.f;//兩幅圖來自同一全景的信賴度WaveCorrectKind wave_correct = detail::WAVE_CORRECT_HORIZ;//波形校正,水平int expos_comp_type = ExposureCompensator::GAIN_BLOCKS;//光照補償方法,預設是gain_blocksfloat match_conf = 0.3f;//特徵點檢測置信等級,最近鄰匹配距離與次近鄰匹配距離的比值,surf預設為0.65int blend_type = Blender::MULTI_BAND;//融合方法,預設是多頻段融合float blend_strength = 5;//融合強度,0 - 100.預設是5.string result_name = "result.jpg";//輸出映像的檔案名稱int main(){clock_t start,finish; double totaltime; start=clock();int argc = 10;char* argv[] = {"1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg", "6.jpg", "7.jpg", "8.jpg", "9.jpg", "10.jpg"};for (int i = 0; i < argc; ++i)img_names.push_back(argv[i]);int num_images = static_cast<int>(img_names.size());double work_scale = 1, seam_scale = 1, compose_scale = 1;//特徵點檢測以及對映像進行預先處理(尺寸縮放),然後計算每幅圖形的特徵點,以及特徵點描述子cout<<"Finding features..."<<endl;Ptr<FeaturesFinder> finder;finder = new SurfFeaturesFinder();///採用Surf特徵點檢測Mat full_img1,full_img, img;vector<ImageFeatures> features(num_images);vector<Mat> images(num_images);vector<Size> full_img_sizes(num_images);double seam_work_aspect = 1;for (int i = 0; i < num_images; ++i){full_img1 = imread(img_names[i]);resize(full_img1,full_img, Size(400,300));full_img_sizes[i] = full_img.size();//計算work_scale,將映像resize到面積在work_megapix*10^6以下work_scale = min(1.0, sqrt(work_megapix * 1e6 / full_img.size().area()));resize(full_img, img, Size(), work_scale, work_scale);//將映像resize到面積在work_megapix*10^6以下seam_scale = min(1.0, sqrt(seam_megapix * 1e6 / full_img.size().area()));seam_work_aspect = seam_scale / work_scale;// 計算映像特徵點,以及計算特徵點描述子,並將img_idx設定為i(*finder)(img, features[i]);features[i].img_idx = i;cout<<"Features in image #" << i+1 << ": " << features[i].keypoints.size()<<endl;//將源映像resize到seam_megapix*10^6,並存入image[]中resize(full_img, img, Size(), seam_scale, seam_scale);images[i] = img.clone();}finder->collectGarbage();full_img.release();img.release();//對映像進行兩兩匹配cout<<"Pairwise matching"<<endl;//使用最近鄰和次近鄰匹配,對任意兩幅圖進行特徵點匹配vector<MatchesInfo> pairwise_matches;BestOf2NearestMatcher matcher(try_gpu, match_conf);//最近鄰和次近鄰法matcher(features, pairwise_matches); //對每兩個圖片進行匹配matcher.collectGarbage();//將信賴度高於門限的所有匹配合并到一個集合中///只留下確定是來自同一全景的圖片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;img_names = img_names_subset;full_img_sizes = full_img_sizes_subset;// 檢查圖片數量是否依舊滿足要求num_images = static_cast<int>(img_names.size());if (num_images < 2){cout<<"Need more images"<<endl;return -1;}HomographyBasedEstimator estimator;//基於單應性的估計量vector<CameraParams> cameras;//相機參數estimator(features, pairwise_matches, cameras);for (size_t i = 0; i < cameras.size(); ++i){Mat R;cameras[i].R.convertTo(R, CV_32F);cameras[i].R = R;cout<<"Initial intrinsics #" << indices[i]+1 << ":\n" << cameras[i].K()<<endl;}Ptr<detail::BundleAdjusterBase> adjuster;//光束調整器參數adjuster = new detail::BundleAdjusterRay();//使用Bundle Adjustment(光束法平差)方法對所有圖片進行相機參數校正adjuster->setConfThresh(conf_thresh);//設定配置閾值Mat_<uchar> refine_mask = Mat::zeros(3, 3, CV_8U);refine_mask(0,0) = 1;refine_mask(0,1) = 1;refine_mask(0,2) = 1;refine_mask(1,1) = 1;refine_mask(1,2) = 1;adjuster->setRefinementMask(refine_mask);(*adjuster)(features, pairwise_matches, cameras);//進行矯正// 求出的焦距取中值和所有圖片的焦距並構建camera參數,將矩陣寫入cameravector<double> focals;for (size_t i = 0; i < cameras.size(); ++i){cout<<"Camera #" << indices[i]+1 << ":\n" << cameras[i].K()<<endl;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]);elsewarped_image_scale = static_cast<float>(focals[focals.size() / 2 - 1] + focals[focals.size() / 2]) * 0.5f;///波形矯正vector<Mat> rmats;for (size_t i = 0; i < cameras.size(); ++i)rmats.push_back(cameras[i].R);waveCorrect(rmats, wave_correct);////波形矯正for (size_t i = 0; i < cameras.size(); ++i)cameras[i].R = rmats[i];cout<<"Warping images ... "<<endl;vector<Point> corners(num_images);//統一座標後的頂點vector<Mat> masks_warped(num_images);vector<Mat> images_warped(num_images);vector<Size> sizes(num_images);vector<Mat> masks(num_images);//融合掩碼// 準備映像融合掩碼for (int i = 0; i < num_images; ++i){masks[i].create(images[i].size(), CV_8U);masks[i].setTo(Scalar::all(255));}//彎曲映像和融合掩碼Ptr<WarperCreator> warper_creator;warper_creator = new cv::SphericalWarper();Ptr<RotationWarper> warper = warper_creator->create(static_cast<float>(warped_image_scale * seam_work_aspect));for (int i = 0; i < num_images; ++i){Mat_<float> K;cameras[i].K().convertTo(K, CV_32F);float swa = (float)seam_work_aspect;K(0,0) *= swa; K(0,2) *= swa;K(1,1) *= swa; K(1,2) *= swa;corners[i] = warper->warp(images[i], K, cameras[i].R, INTER_LINEAR, BORDER_REFLECT, images_warped[i]);//計算統一後座標頂點sizes[i] = images_warped[i].size();warper->warp(masks[i], K, cameras[i].R, INTER_NEAREST, BORDER_CONSTANT, masks_warped[i]);//彎曲當前映像}vector<Mat> images_warped_f(num_images);for (int i = 0; i < num_images; ++i)images_warped[i].convertTo(images_warped_f[i], CV_32F);Ptr<ExposureCompensator> compensator = ExposureCompensator::createDefault(expos_comp_type);//建立補償器以進行關照補償,補償方法是gain_blockscompensator->feed(corners, images_warped, masks_warped);//尋找接縫Ptr<SeamFinder> seam_finder;seam_finder = new detail::GraphCutSeamFinder(GraphCutSeamFinderBase::COST_COLOR); seam_finder->find(images_warped_f, corners, masks_warped);// 釋放未使用的記憶體images.clear();images_warped.clear();images_warped_f.clear();masks.clear();//////映像融合cout<<"Compositing..."<<endl;Mat img_warped, img_warped_s;Mat dilated_mask, seam_mask, mask, mask_warped;Ptr<Blender> blender;double compose_work_aspect = 1;for (int img_idx = 0; img_idx < num_images; ++img_idx){cout<<"Compositing image #" << indices[img_idx]+1<<endl;//由於以前進行處理的圖片都是以work_scale進行縮放的,所以映像的內參//corner(統一座標後的頂點),mask(融合的掩碼)都需要重新計算// 讀取映像和做必要的調整full_img1 = imread(img_names[img_idx]);resize(full_img1,full_img, Size(400,300));compose_scale = min(1.0, sqrt(compose_megapix * 1e6 / full_img.size().area()));compose_work_aspect = compose_scale / work_scale;// 更新彎曲映像比例warped_image_scale *= static_cast<float>(compose_work_aspect);warper = warper_creator->create(warped_image_scale);// 更新corners和sizesfor (int i = 0; i < num_images; ++i){// 更新相機以下特性cameras[i].focal *= compose_work_aspect;cameras[i].ppx *= compose_work_aspect;cameras[i].ppy *= compose_work_aspect;// 更新corners和sizesSize sz = full_img_sizes[i];if (std::abs(compose_scale - 1) > 1e-1){sz.width = cvRound(full_img_sizes[i].width * compose_scale);sz.height = cvRound(full_img_sizes[i].height * compose_scale);}Mat K;cameras[i].K().convertTo(K, CV_32F);Rect roi = warper->warpRoi(sz, K, cameras[i].R);corners[i] = roi.tl();sizes[i] = roi.size();}if (abs(compose_scale - 1) > 1e-1)resize(full_img, img, Size(), compose_scale, compose_scale);elseimg = full_img;full_img.release();Size img_size = img.size();Mat K;cameras[img_idx].K().convertTo(K, CV_32F);// 扭曲當前映像warper->warp(img, K, cameras[img_idx].R, INTER_LINEAR, BORDER_REFLECT, img_warped);// 扭曲當前映像掩模mask.create(img_size, CV_8U);mask.setTo(Scalar::all(255));warper->warp(mask, K, cameras[img_idx].R, INTER_NEAREST, BORDER_CONSTANT, mask_warped);// 曝光補償compensator->apply(img_idx, corners[img_idx], img_warped, mask_warped);img_warped.convertTo(img_warped_s, CV_16S);img_warped.release();img.release();mask.release();dilate(masks_warped[img_idx], dilated_mask, Mat());resize(dilated_mask, seam_mask, mask_warped.size());mask_warped = seam_mask & mask_warped;//初始化blenderif (blender.empty()){blender = Blender::createDefault(blend_type, try_gpu);Size dst_sz = resultRoi(corners, sizes).size();float blend_width = sqrt(static_cast<float>(dst_sz.area())) * blend_strength / 100.f;if (blend_width < 1.f)blender = Blender::createDefault(Blender::NO, try_gpu);else {MultiBandBlender* mb = dynamic_cast<MultiBandBlender*>(static_cast<Blender*>(blender));mb->setNumBands(static_cast<int>(ceil(log(blend_width)/log(2.)) - 1.));cout<<"Multi-band blender, number of bands: " << mb->numBands()<<endl;}//根據corners頂點和映像的大小確定最終全景的尺寸blender->prepare(corners, sizes);}// // 融合當前映像blender->feed(img_warped_s, mask_warped, corners[img_idx]);}Mat result, result_mask;blender->blend(result, result_mask);imwrite(result_name, result); finish=clock(); totaltime=(double)(finish-start)/CLOCKS_PER_SEC; cout<<"\n此程式的已耗用時間為"<<totaltime<<"秒!"<<endl;return 0;}
任意n張映像拼接_效果很好_電腦視覺大作業1終版