• 图像拼接3


    #include <opencv2/opencv.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 <iostream>
    #include <fstream> 
    #include <string>
    #include <iomanip> 
    using namespace cv;
    using namespace std;
    using namespace detail;
    int main(int argc, char** argv)
    {
        vector<Mat> imgs;    //输入图像
        vector<String>names;
        glob("./pic/*.jpg", names,false);
        for (int i = 0; i < names.size(); i++)
        {
            imgs.push_back(imread(names[i]));
        }
        
        Ptr<FeaturesFinder> finder;    //特征检测
        finder = new OrbFeaturesFinder();
        vector<ImageFeatures> features(2);
        (*finder)(imgs[0], features[0]);
        (*finder)(imgs[1], features[1]);
    
        vector<MatchesInfo> pairwise_matches;    //特征匹配
        Ptr<FeaturesMatcher> matcher;
        //BestOf2NearestMatcher matcher(false, 0.3f, 6, 6);
    
        matcher = makePtr<BestOf2NearestRangeMatcher>(5, false, 0.3);
        (*matcher)(features, pairwise_matches);
        matcher->collectGarbage();
        //HomographyBasedEstimator estimator;    //相机参数评估
        Ptr<Estimator> estimator;
        vector<CameraParams> cameras;
        estimator = makePtr<HomographyBasedEstimator>();
    
        (*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;
        }
    
        Ptr<detail::BundleAdjusterBase> adjuster;    //相机参数精确评估
        adjuster = new detail::BundleAdjusterReproj();
        adjuster->setConfThresh(1);
        (*adjuster)(features, pairwise_matches, cameras);
    
        vector<Mat> rmats;
        for (size_t i = 0; i < cameras.size(); ++i)
            rmats.push_back(cameras[i].R.clone());
        waveCorrect(rmats, WAVE_CORRECT_HORIZ);    //波形校正
        for (size_t i = 0; i < cameras.size(); ++i)
            cameras[i].R = rmats[i];
    
        //图像映射变换
        vector<Point> corners(2);
        vector<UMat> masks_warped(2);
        vector<UMat> images_warped(2);
        vector<Size> sizes(2);
        vector<Mat> masks(2);
        for (int i = 0; i < 2; ++i)
        {
            masks[i].create(imgs[i].size(), CV_8U);
            masks[i].setTo(Scalar::all(255));
        }
        Ptr<WarperCreator> warper_creator;
        warper_creator = new cv::PlaneWarper();
        Ptr<RotationWarper> warper = warper_creator->create(static_cast<float>(cameras[0].focal));
        for (int i = 0; i < 2; ++i)
        {
            Mat_<float> K;
            cameras[i].K().convertTo(K, CV_32F);
            corners[i] = warper->warp(imgs[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]);
        }
    
        //曝光补偿
        Ptr<ExposureCompensator> compensator =
            ExposureCompensator::createDefault(ExposureCompensator::GAIN);
        compensator->feed(corners, images_warped, masks_warped);
        for (int i = 0; i<2; ++i)
        {
            compensator->apply(i, corners[i], images_warped[i], masks_warped[i]);
        }
    
        //在后面,我们还需要用到映射变换图的掩码masks_warped,因此这里为该变量添加一个副本masks_seam
        vector<UMat> masks_seam(2);
        for (int i = 0; i<2; i++)
            masks_warped[i].copyTo(masks_seam[i]);
    
        //寻找接缝线
        Ptr<SeamFinder> seam_finder;
        seam_finder = new GraphCutSeamFinder(GraphCutSeamFinder::COST_COLOR_GRAD);
        vector<UMat> images_warped_f(2);
        for (int i = 0; i < 2; ++i)
            images_warped[i].convertTo(images_warped_f[i], CV_32F);
        seam_finder->find(images_warped_f, corners, masks_seam);
    
        //图像融合
        Ptr<Blender> blender;    //定义图像融合器
    
         //blender = Blender::createDefault(Blender::NO, false);    //简单融合方法
         /****羽化融合方法*********
         blender = Blender::createDefault(Blender::FEATHER, false);
        FeatherBlender* fb = dynamic_cast<FeatherBlender*>(static_cast<Blender*>(blender));
        fb->setSharpness(0.005);    //设置羽化锐度
        **************/
        blender = Blender::createDefault(Blender::MULTI_BAND, false);    //多频段融合
        MultiBandBlender* mb = dynamic_cast<MultiBandBlender*>(static_cast<Blender*>(blender));
        //设置频段数,即金字塔层数,原则上频段越多越好
        mb->setNumBands(8);
    
        blender->prepare(corners, sizes);    //生成全景图像区域
    
        //在融合的时候,最重要的是在接缝线两侧进行处理,而上一步在寻找接缝线后得到的掩码的边界就是接缝线处,因此我们还需要在接缝线两侧开辟一块区域用于融合处理,这一处理过程对羽化方法尤为关键
        //应用膨胀算法缩小掩码面积
        vector<Mat> dilate_img(2);
        Mat element = getStructuringElement(MORPH_RECT, Size(20, 20));    //定义结构元素
        vector<Mat> images_warped_s(2);
        for (int k = 0; k<2; k++)    //遍历所有图像
        {
    
            images_warped_f[k].convertTo(images_warped_s[k], CV_16S);    //改变数据类型
            dilate(masks_seam[k], masks_seam[k], element);    //膨胀运算
             //映射变换图的掩码和膨胀后的掩码相“与”,从而使扩展的区域仅仅限于接缝线两侧,其他边界处不受影响
            //masks_seam[k] = masks_seam[k] & masks_warped[k];
            Mat wap1, wap2;
            masks_seam[k].copyTo(wap1);
            masks_warped[k].copyTo(wap2);
            wap1 = wap1&wap2;
            wap1.copyTo(masks_seam[k]);
    
            blender->feed(images_warped_s[k], masks_seam[k], corners[k]);    //初始化数据
        }
    
        Mat result, result_mask;
        //完成融合操作,得到全景图像result和它的掩码result_mask
        blender->blend(result, result_mask);
        result.convertTo(result,CV_8UC3);
        imwrite("pano.jpg", result);    //存储全景图像
        return 0;
    }
  • 相关阅读:
    Django01
    WEB框架介绍
    前端插件介绍
    JQuery
    DOM
    js
    css
    HTML
    图片懒加载
    js中style,currentStyle和getComputedStyle的区别
  • 原文地址:https://www.cnblogs.com/hsy1941/p/14507796.html
Copyright © 2020-2023  润新知