gis如何无缝拼接两张图_arcgis多幅影像图拼接

gis如何无缝拼接两张图_arcgis多幅影像图拼接APAP.cpp#include”stdafx.h”#include<iostream>#include<cmath>#include”opencv2/features2d/features2d.hpp”#include”opencv2/highgui/highgui.hpp”#include”opencv2/opencv_modules.hpp”#include”opencv2/calib3d/calib3d.hpp”#include..

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

APAP.cpp

 

#include “stdafx.h”

#include <iostream>
#include <cmath>

#include “opencv2/features2d/features2d.hpp” 
#include “opencv2/highgui/highgui.hpp”
#include “opencv2/opencv_modules.hpp”
#include “opencv2/calib3d/calib3d.hpp”

#include “apap.h”

using namespace std;

APAPWarper::APAPWarper()
{

    cell_height_ = 15;
    cell_width_ = 20;
    gamma_ = 0.05;
    sigma_ = 8.5;

    H_s_ = NULL;
}

/*
 *    
 */
int APAPWarper::buildMaps(Mat src_img, ImageFeatures src_features, ImageFeatures dst_features, 
    MatchesInfo matches_info, Mat &xmap, Mat &ymap, Point &corner )
{

    int matches_size = matches_info.matches.size();

    /*
     * 初始化矩阵A
     */
    InitA(src_features, dst_features, matches_info);
    
    /*
     * 每一个cell做一次DLT
     */
    int inliner_nums = matches_info.num_inliers;
    // 初始化W_
    W_ = Mat_<apap_float>::zeros(2 * inliner_nums, 2 * inliner_nums);

    // 存放每一个cell对应的H
    if(H_s_ != NULL)
    {

        for(int i = 0; i < cell_rows_; i++)
            delete []H_s_[i];
        delete []H_s_;
        H_s_ = NULL;
    }
    int src_rows = src_img.rows;
    int src_cols = src_img.cols;
    cell_rows_ = cvCeil((double)(src_rows) / cell_height_);
    cell_cols_ = cvCeil((double)(src_cols) / cell_width_);

    H_s_ = new Mat_<apap_float> *[cell_rows_];
    for(int i = 0; i < cell_rows_; i++)
        H_s_[i] = new Mat_<apap_float> [cell_cols_];
    Mat_<apap_float> H(3, 3);

    for(int x = 0; x < src_cols; x += cell_width_)
        for(int y = 0; y < src_rows; y += cell_height_)
            CellDLT(x, y, src_features, dst_features, matches_info, H_s_[y / cell_height_][x / cell_width_]);

    cout << “apap: MDLT completed” << endl;

    /*
     * Remap
     * 反向映射(Reverse mapping,结果图片中的每个点对应src的坐标)
     */
    //    1、计算映射结果图片的尺寸,只需要把四条边映射一下就可以了
    Point2d corner_2d(H_s_[0][0](0, 2) / H_s_[0][0](2, 2), H_s_[0][0](1, 2) / H_s_[0][0](2, 2));
    Point2d br(corner_2d);
    for(int x = 0; x < src_cols; x ++)
    {

        //上面的边
        updateMappedSize(H_s_[0][x / cell_width_], x, 0, corner_2d, br);
        //下面的边
        updateMappedSize(H_s_[(src_rows-1) / cell_height_][x / cell_width_], 
            x, src_rows – 1, corner_2d, br);
    }

    for(int y = 0; y < src_rows; y ++)
    {

        // 左边
        updateMappedSize(H_s_[y / cell_height_][0], 0, y, corner_2d, br);
        // 右边
        updateMappedSize(H_s_[y / cell_height_][(src_cols-1) / cell_width_],
            src_cols – 1, y, corner_2d, br);
    }

    cout << corner_2d << endl;

    //    2、反向映射
    corner.x = cvFloor(corner_2d.x);
    corner.y = cvFloor(corner_2d.y);
    int result_width = cvCeil(br.x) + 1 – corner.x;
    int result_height = cvCeil(br.y) + 1 – corner.y;

    xmap.create(result_height, result_width, CV_32F);
    ymap.create(result_height, result_width, CV_32F);
    float *xmap_rev_ptr = xmap.ptr<float>(0);
    float *ymap_rev_ptr = ymap.ptr<float>(0);
    for(int i = 0; i < result_width * result_height; i++)
        xmap_rev_ptr[i] = ymap_rev_ptr[i] = -1;

    for(int x = 0; x < src_cols; x += cell_width_)
    {

        for(int y = 0; y < src_rows; y += cell_height_)
        {

            int xx_max = std::min(x + cell_width_, src_cols);
            int yy_max = std::min(y + cell_height_, src_rows);
            BuildCellMap(x, y, xx_max, yy_max, H_s_[y / cell_height_][x / cell_width_], corner, 
                xmap, ymap);
        }
    }

    cout << “apap: build map completed” << endl;

    return 0;
}

int APAPWarper::buildMaps( vector<Mat> imgs, vector<ImageFeatures> features, 
    vector<MatchesInfo> pairwise_matches, vector<Mat> &xmaps, vector<Mat> &ymaps, vector<Point> &corners )
{

    int n = imgs.size();

    int mid_idx = n / 2;

    // 基准图片的map
    int mid_img_width = imgs[mid_idx].cols;
    int mid_img_height = imgs[mid_idx].rows;
    xmaps[mid_idx].create(imgs[mid_idx].size(), CV_32F);
    ymaps[mid_idx].create(imgs[mid_idx].size(), CV_32F);
    float *xmap_rev_ptr = xmaps[mid_idx].ptr<float>(0);
    float *ymap_rev_ptr = ymaps[mid_idx].ptr<float>(0);
    for(int y = 0; y < mid_img_height; y++)
    {

        for(int x = 0; x < mid_img_width; x++)
        {

            int idx = y * mid_img_width + x;
            xmap_rev_ptr[idx] = (float)x;
            ymap_rev_ptr[idx] = (float)y;
        }
    }
    corners[mid_idx].x = 0;
    corners[mid_idx].x = 0;

    for(int i = mid_idx+1; i >= (mid_idx-1); i–)
    {

        if(i == mid_idx)
            continue;
        int pair_idx = i * n + mid_idx;
        buildMaps(imgs[i], features[i], features[mid_idx], pairwise_matches[pair_idx], 
            xmaps[i], ymaps[i], corners[i]);
    }

    if(n < 4)
        return 0;

    ImageFeatures features_warped;
    int feat_num = features[1].keypoints.size();
    features_warped.keypoints.resize(feat_num);
    features_warped.img_idx = features[1].img_idx;
    features_warped.img_size = features[1].img_size;
    Mat_<apap_float> tmp_X(3, 1), tmp_res_X;
    for(int i = 0; i < feat_num; i++)
    {

        tmp_X(0, 0) = features[1].keypoints[i].pt.x;
        tmp_X(1, 0) = features[1].keypoints[i].pt.y;
        tmp_X(2, 0) = 1;
        int x = cvRound(tmp_X(0, 0));
        int y = cvRound(tmp_X(1, 0));
        tmp_res_X = H_s_[(int)(y / cell_height_)][(int)(x / cell_width_)] * tmp_X;
        features_warped.keypoints[i].pt.x = (double)(tmp_res_X(0, 0) / tmp_res_X(2, 0) – corners[1].x);
        features_warped.keypoints[i].pt.y = (double)(tmp_res_X(1, 0) / tmp_res_X(2, 0) – corners[1].y);
    }
    buildMaps(imgs[0], features[0], features_warped, pairwise_matches[1],
        xmaps[0], ymaps[0], corners[0]);
    corners[0].x += corners[1].x;
    corners[0].y += corners[1].y;

    return 0;
}

/*
 * src_img向dst_img配准
 *
 */
int APAPWarper::warp( Mat src_img, ImageFeatures src_features, ImageFeatures dst_features, 
    MatchesInfo matches_info, Mat &result_img, Point &corner )
{

    Mat xmap_rev, ymap_rev;

    //    1、建立映射
    buildMaps(src_img, src_features, dst_features, matches_info,
        xmap_rev, ymap_rev, corner);

    //    2、remap(TODO)
    remap(src_img, result_img, xmap_rev, ymap_rev, INTER_LINEAR);

    return 0;
}

int APAPWarper::CellDLT( int offset_x, int offset_y, ImageFeatures src_features, 
    ImageFeatures dst_features, MatchesInfo matches_info, Mat_<apap_float> &H )
{

    int matches_size = matches_info.matches.size();
    int inliner_nums = matches_info.num_inliers;
    
    double center_x = offset_x + cell_width_ / 2;
    double center_y = offset_y + cell_height_ / 2;

    for(int j = 0, inliner_idx = 0; j < matches_size; j ++)
    {

        if (!matches_info.inliers_mask[j])
            continue;

        const DMatch& m = matches_info.matches[j];
        Point2f p1 = src_features.keypoints[m.queryIdx].pt;
        Point2f p2 = dst_features.keypoints[m.trainIdx].pt;

        double weight = exp((-1 / (sigma_ * sigma_)) * 
            ((center_x-p1.x) * (center_x-p1.x) + (center_y-p1.y) * (center_y-p1.y)) );
        int i = inliner_idx * 2;
        W_(i, i) = W_(i+1, i+1) = std::max(weight, gamma_);
        inliner_idx ++;
    }

    Mat WA = W_ * A_;
    Mat_<apap_float> h(9, 1);
    SVD::solveZ(WA, h);
    
    /*
    printf(“(“);
    for(int i = 0; i < 9; i++)
        printf(“%lf, “, H(i, 0) / H(8, 0));
    printf(“)\n”);
    */
    if(H.empty())
        H.create(3, 3);
    apap_float *H_ptr = H.ptr<apap_float>(0);
    apap_float *h_ptr = h.ptr<apap_float>(0);
    for(int i = 0; i < 9; i++)
        H_ptr[i] = h_ptr[i];
    
    return 0;
}

void APAPWarper::InitA( ImageFeatures src_features, ImageFeatures dst_features, MatchesInfo matches_info )
{

    printf(“init A\n”);
    int matches_size = matches_info.matches.size();
    int inliner_nums = matches_info.num_inliers;
    A_ = Mat_<apap_float>::zeros(2 * inliner_nums, 9);

    Mat src_points(1, inliner_nums, CV_32FC2);
    Mat dst_points(1, inliner_nums, CV_32FC2);

    for(int j = 0, inliner_idx = 0; j < matches_size; j++)
    {

        if (!matches_info.inliers_mask[j])
            continue;

        const DMatch& m = matches_info.matches[j];
        Point2f p1 = src_features.keypoints[m.queryIdx].pt;
        Point2f p2 = dst_features.keypoints[m.trainIdx].pt;
        src_points.at<Point2f>(0, inliner_idx) = p1;
        dst_points.at<Point2f>(0, inliner_idx) = p2;
        
        int i = inliner_idx * 2;

        A_(i, 0) = A_(i, 1) = A_(i, 2) = 0;
        A_(i, 3) = -p1.x;
        A_(i, 4) = -p1.y;
        A_(i, 5) = -1;
        A_(i, 6) = p2.y * p1.x;
        A_(i, 7) = p2.y * p1.y;
        A_(i, 8) = p2.y;
        
        A_(i + 1, 0) = p1.x;
        A_(i + 1, 1) = p1.y;
        A_(i + 1, 2) = 1;
        A_(i + 1, 3) = A_(i + 1, 4) = A_(i + 1, 5) = 0;
        A_(i + 1, 6) = -p2.x * p1.x;
        A_(i + 1, 7) = -p2.x * p1.y;
        A_(i + 1, 8) = -p2.x;

        inliner_idx ++;
    }
}

void APAPWarper::testh( ImageFeatures src_features, ImageFeatures dst_features, 
    MatchesInfo matches_info, Mat h )
{

    int matches_size = matches_info.matches.size();
    double *h_ptr = h.ptr<double>(0);
    for(int i = 0; i < matches_size; i ++)
    {

        if (!matches_info.inliers_mask[i])
            continue;
        const DMatch& m = matches_info.matches[i];
        Point2f p1 = src_features.keypoints[m.queryIdx].pt;
        Point2f p2 = dst_features.keypoints[m.trainIdx].pt;

        double _z = h_ptr[6] * p1.x + h_ptr[7] * p1.y + h_ptr[8];
        double _y = h_ptr[3] * p1.x + h_ptr[4] * p1.y + h_ptr[5];
        double _x = h_ptr[0] * p1.x + h_ptr[1] * p1.y + h_ptr[2];

        _x = _x / _z;
        _y = _y / _z;

        if(i < 20)
            printf(“%.7lf, %.7lf => %.7lf, %.7lf\n”, p2.x, p2.y, _x, _y);
    }
    printf(“\n”);
}

void APAPWarper::updateMappedSize( Mat_<apap_float> H, double x, double y, 
    Point2d &corner, Point2d &br )
{

    double _z = H(2, 0) * x + H(2, 1) * y + H(2, 2);
    double _y = (H(1, 0) * x + H(1, 1) * y + H(1, 2)) / _z;
    double _x = (H(0, 0) * x + H(0, 1) * y + H(0, 2)) / _z;

    corner.x = std::min(corner.x, _x);
    corner.y = std::min(corner.y, _y);
    br.x = std::max(br.x, _x);
    br.y = std::max(br.y, _y);
}

void APAPWarper::BuildCellMap( int x_1, int y_1, int x_2, int y_2, Mat H, Point corner, Mat &xmap, Mat &ymap )
{

    float *xmap_rev_ptr = xmap.ptr<float>(0);
    float *ymap_rev_ptr = ymap.ptr<float>(0);
    int res_width = xmap.size().width;
    int res_height = xmap.size().height;

    Mat_<apap_float> tmp_corner_X[4], tmp_corner_res_X[4];    // 四个角的坐标
    for(int i = 0; i < 4; i++)
        tmp_corner_X[i] = Mat_<apap_float>::ones(3, 1);
    tmp_corner_X[0](0, 0) = tmp_corner_X[3](0, 0) = x_1;
    tmp_corner_X[0](1, 0) = tmp_corner_X[1](1, 0) = y_1;
    tmp_corner_X[1](0, 0) = tmp_corner_X[2](0, 0) = x_2;
    tmp_corner_X[2](1, 0) = tmp_corner_X[3](1, 0) = y_2;

    for(int i = 0; i < 4; i++)
    {

        tmp_corner_res_X[i] = H * tmp_corner_X[i];
        tmp_corner_res_X[i] = tmp_corner_res_X[i] / tmp_corner_res_X[i](2, 0);
    }
    //cout << “1” << endl;
    // 先找到x和y的范围
    double y_min_d, y_max_d;
    double x_min_d, x_max_d;
    y_min_d = y_max_d = tmp_corner_res_X[0](1, 0);
    x_min_d = x_max_d = tmp_corner_res_X[0](0, 0);
    for(int i = 1; i < 4; i++)
    {

        double y = tmp_corner_res_X[i](1, 0);
        double x = tmp_corner_res_X[i](0, 0);
        y_min_d = std::min(y, y_min_d);
        y_max_d = std::max(y, y_max_d);
        x_min_d = std::min(x, x_min_d);
        x_max_d = std::max(x, x_max_d);
    }

    //cout << “2” << endl;
    // 扫描线
    int y_min = cvFloor(y_min_d), y_max = cvCeil(y_max_d);
    double x1, x2, y1, y2, x_start_d, x_end_d;
    int x_start, x_end;
    Mat_<apap_float> H_inv = H.inv(), tmp_X = Mat_<apap_float>::ones(3, 1), tmp_mapped_X(3, 1);
    double delta = 1.2;
    for(int y = y_min; y <= y_max; y++)
    {

        // 与4条线的交点
        x_start_d = x_max_d;
        x_end_d = x_min_d;
        for(int i = 0; i < 4; i++)
        {

            x2 = tmp_corner_res_X[i](0, 0);
            y2 = tmp_corner_res_X[i](1, 0);
            x1 = tmp_corner_res_X[(i+1) % 4](0, 0);
            y1 = tmp_corner_res_X[(i+1) % 4](1, 0);
            if(std::abs(y1 – y2) < 0.2)
                continue;

            if((y > (y1+delta) && y > (y2+delta)) || (y < (y1-delta) && y < (y2-delta)))
                continue;
            double p_x = x1 + (y – y1) * (x2 – x1) / (y2 – y1);
            x_start_d = std::min(x_start_d, p_x);
            x_end_d = std::max(x_end_d, p_x);
        }
        x_start = cvFloor(x_start_d);
        x_end = cvCeil(x_end_d);
        tmp_X(1, 0) = y;
        //cout << “3” << endl;
        for(int x = x_start; x <= x_end; x++)
        {

            int x_idx = x – corner.x;
            int y_idx = y – corner.y;
            if(x_idx >= res_width || y_idx >= res_height || x_idx < 0 || y_idx < 0)
                continue;
            tmp_X(0, 0) = x;
            tmp_mapped_X = H_inv * tmp_X;
            int idx = y_idx * res_width + x_idx;
            xmap_rev_ptr[idx] = (float)(tmp_mapped_X(0, 0) / tmp_mapped_X(2, 0));
            ymap_rev_ptr[idx] = (float)(tmp_mapped_X(1, 0) / tmp_mapped_X(2, 0));
        }
    }

}

APAPWarper::~APAPWarper()
{

    if(H_s_ != NULL)
    {

        for(int i = 0; i < cell_rows_; i++)
            delete []H_s_[i];
        delete []H_s_;
        H_s_ = NULL;
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/190655.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 分享一键群发各大博客社区平台的工具

    分享一键群发各大博客社区平台的工具文章目录1.BlogHelper2.OpenWrite随着自媒体越来越流行,一篇文章或一个视频分别要在几个平台上发布…

  • SpringBoot异步调用

    SpringBoot异步调用除了异步请求,一般上我们用的比较多的应该是异步调用。通常在开发过程中,会遇到一个方法是和实际业务无关的,没有紧密性的。比如记录日志信息等业务。这个时候正常就是启一个新线程去做一些业务处理,让主线程异步的执行其他业务。何为异步调用说异步调用前,我们说说它对应的同步调用。通常开发过程中,一般上我们都是同步调用,即:程序按定义的顺序依次执行的过程,每一行代码执行过程必须等待上一行代码执行完毕后才…

  • MySQL数据库:索引的实现原理

    MySQL数据库:索引的实现原理

  • [解决]Invalid configuration `aarch64-linux’: machine `aarch64′ not recognize「建议收藏」

    [解决]Invalid configuration `aarch64-linux’: machine `aarch64′ not recognize「建议收藏」在TX1板卡上移植开源库出现如下错误checkingbuildsystemtype…Invalidconfiguration`aarch64-linux’:machine`aarch64’notrecognized系统环境ubuntu@tegra-ubuntu:/$file/bin/busybox/bin/busybox:ELF64-bitLS…

    2022年10月17日
  • java浅拷贝和深拷贝的区别_python的浅拷贝和深拷贝

    java浅拷贝和深拷贝的区别_python的浅拷贝和深拷贝Java中的对象拷贝(ObjectCopy)指的是将一个对象的所有属性(成员变量)拷贝到另一个有着相同类类型的对象中去。举例说明:比如,对象A和对象B都属于类S,具有属性a和b。那么对对象A进行拷贝操作赋值给对象B就是:B.a=A.a;B.b=A.b;在程序中拷贝对象是很常见的,主要是为了在新的上下文环境中复用现有对象的部分或全部数据。Java中的对象拷贝主要分为:浅拷贝(ShallowCopy)、深拷贝(DeepCopy)。先介绍一点铺垫知识:Java中的数据类型分为基本数据类型和.

  • 惠普服务器磁盘阵列配置及故障修复「建议收藏」

    惠普服务器磁盘阵列配置及故障修复「建议收藏」设备上电开机,按键盘F10.稍等片刻进入开机界面》》》》》》惠普服务器磁盘阵列配置Raid1/Raid0惠普服务器磁盘阵列的设置是安装操作系统的先决条件。只有完成了磁盘阵列的设置才能正常使用。HPDL388Gen9系列,配两块HDD硬盘。步骤如下:https://jingyan.baidu.com/article/e3c78…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号