丐帮二帮主 2016-11-25 06:14 采纳率: 0%
浏览 2639

在opencv的图像拼接stitch_detail.cpp中怎么计算子图像的xyz平移量?

在opencv自带的例子stitch_detail.cpp中,计算出来的CameraParams::R矩阵可以计算出图像的每个坐标的旋转量。但是每一幅图最后的位置(左上原点的坐标)怎么确定?怎么获得图像xyz轴的平移量?(z轴应该是指图像的缩放)
调整图像(透视变换)的代码片段如下:

    is_compose_scale_set = false; // false

    Mat img_warped, img_warped_s; 
    Mat dilated_mask,
    seam_mask,
    mask, 
    mask_warped;
    Ptr<Blender> blender;
    double compose_seam_aspect = 1;
    double compose_work_aspect = 1;

    Mat full_img;

    Ptr<RotationWarper> warper;
    Ptr<WarperCreator> warper_creator;

    #if defined(HAVE_OPENCV_GPU)
    if (try_gpu && gpu::getCudaEnabledDeviceCount() > 0){
        warper_creator = new cv::PlaneWarperGpu();
    }else
    #endif
    {   
        warper_creator = new cv::PlaneWarper();
    }

    for(int img_idx = 0; img_idx < precom_num; ++img_idx){

        full_img = img_OriMat[img_idx];

        if (!is_compose_scale_set)  // 合成等级设定
        {
            if (compose_megapix > 0)
                compose_scale = min(1.0, sqrt(compose_megapix * 1e6 / full_img.size().area())); 
            is_compose_scale_set = true;

            // Compute relative scales
            //compose_seam_aspect = compose_scale / seam_scale;
            compose_work_aspect = compose_scale / work_scale;

            // Update warped image scale

            warped_image_scale *= static_cast<float>(compose_work_aspect);
            warper = warper_creator->create(warped_image_scale);

            // Update corners and sizes
            for (int i = 0; i < precom_num; ++i){
                // Update intrinsics
                cameras[i].focal *= compose_work_aspect;
                cameras[i].ppx *= compose_work_aspect;
                cameras[i].ppy *= compose_work_aspect;

                // Update corner and size
                Size 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();


            }
        }
        Mat img; // 增加
        if (abs(compose_scale - 1) > 1e-1)
            cv::resize(full_img, img, Size(), compose_scale, compose_scale);
        else
            img = 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);


        // Warp the current image mask
        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);


        img_warped.convertTo(img_warped_s, CV_16S);
        img_warped.release();
        img.release();
        mask.release();

        cv::dilate(mask_warped, dilated_mask, Mat()); // 膨胀
        cv::resize(dilated_mask, seam_mask, mask_warped.size());
        mask_warped = seam_mask & mask_warped;

        if (blender.empty())
        {
            blender = Blender::createDefault(0, try_gpu);
            Size dst_sz = resultRoi(corners, sizes).size(); // 获得最终画布的大小
            float blend_width = sqrt(static_cast<float>(dst_sz.area())) * 5 / 100.f;
            if (blend_width < 1.f)
                blender = Blender::createDefault(Blender::NO, try_gpu);
            blender->prepare(corners, sizes);
        }
        // Blend the current image
        blender->feed(img_warped_s, mask_warped, corners[img_idx]);

        char ppa[100] = {0};
        sprintf_s(ppa,100,"img_warped_s_%d.jpg",img_idx);
        imwrite(ppa, img_warped_s);


    } // for end

    Mat result, result_mask;
    blender->blend(result, result_mask);
    // 返回图像
    return result;

查了代码发现,除了R,corners会影响拼接图像的原点坐标,sizes是其大小。在warpers_inl.hpp中又看到:

 template <class P>
Rect RotationWarperBase<P>::warpRoi(Size src_size, const Mat &K, const Mat &R)
{
    projector_.setCameraParams(K, R);

    Point dst_tl, dst_br;
    detectResultRoi(src_size, dst_tl, dst_br);

    return Rect(dst_tl, Point(dst_br.x + 1, dst_br.y + 1));
}

setCameraParams的定义在warpers.cpp中:

 void ProjectorBase::setCameraParams(const Mat &K, const Mat &R, const Mat &T)
{
    CV_Assert(K.size() == Size(3, 3) && K.type() == CV_32F);
    CV_Assert(R.size() == Size(3, 3) && R.type() == CV_32F);
    CV_Assert((T.size() == Size(1, 3) || T.size() == Size(3, 1)) && T.type() == CV_32F);

    Mat_<float> K_(K);
    k[0] = K_(0,0); k[1] = K_(0,1); k[2] = K_(0,2);
    k[3] = K_(1,0); k[4] = K_(1,1); k[5] = K_(1,2);
    k[6] = K_(2,0); k[7] = K_(2,1); k[8] = K_(2,2);

    Mat_<float> Rinv = R.t();
    rinv[0] = Rinv(0,0); rinv[1] = Rinv(0,1); rinv[2] = Rinv(0,2);
    rinv[3] = Rinv(1,0); rinv[4] = Rinv(1,1); rinv[5] = Rinv(1,2);
    rinv[6] = Rinv(2,0); rinv[7] = Rinv(2,1); rinv[8] = Rinv(2,2);

    Mat_<float> R_Kinv = R * K.inv();
    r_kinv[0] = R_Kinv(0,0); r_kinv[1] = R_Kinv(0,1); r_kinv[2] = R_Kinv(0,2);
    r_kinv[3] = R_Kinv(1,0); r_kinv[4] = R_Kinv(1,1); r_kinv[5] = R_Kinv(1,2);
    r_kinv[6] = R_Kinv(2,0); r_kinv[7] = R_Kinv(2,1); r_kinv[8] = R_Kinv(2,2);

    Mat_<float> K_Rinv = K * Rinv;
    k_rinv[0] = K_Rinv(0,0); k_rinv[1] = K_Rinv(0,1); k_rinv[2] = K_Rinv(0,2);
    k_rinv[3] = K_Rinv(1,0); k_rinv[4] = K_Rinv(1,1); k_rinv[5] = K_Rinv(1,2);
    k_rinv[6] = K_Rinv(2,0); k_rinv[7] = K_Rinv(2,1); k_rinv[8] = K_Rinv(2,2);

    Mat_<float> T_(T.reshape(0, 3));
    t[0] = T_(0,0); t[1] = T_(1,0); t[2] = T_(2,0);
}

其中的参数的定义在warpers.hpp中:

 struct CV_EXPORTS ProjectorBase
{
    void setCameraParams(const Mat &K = Mat::eye(3, 3, CV_32F),
                         const Mat &R = Mat::eye(3, 3, CV_32F),
                         const Mat &T = Mat::zeros(3, 1, CV_32F));

    float scale;
    float k[9];
    float rinv[9];
    float r_kinv[9];
    float k_rinv[9];
    float t[3];
};

detectResultRoi的定义在warpers_inl.hpp中:

 template <class P>
void RotationWarperBase<P>::detectResultRoi(Size src_size, Point &dst_tl, Point &dst_br)
{
    float tl_uf = std::numeric_limits<float>::max();
    float tl_vf = std::numeric_limits<float>::max();
    float br_uf = -std::numeric_limits<float>::max();
    float br_vf = -std::numeric_limits<float>::max();

    float u, v;
    for (int y = 0; y < src_size.height; ++y)
    {
        for (int x = 0; x < src_size.width; ++x)
        {
            projector_.mapForward(static_cast<float>(x), static_cast<float>(y), u, v);
            tl_uf = std::min(tl_uf, u); tl_vf = std::min(tl_vf, v);
            br_uf = std::max(br_uf, u); br_vf = std::max(br_vf, v);
        }
    }

    dst_tl.x = static_cast<int>(tl_uf);
    dst_tl.y = static_cast<int>(tl_vf);
    dst_br.x = static_cast<int>(br_uf);
    dst_br.y = static_cast<int>(br_vf);
}

请问大家有知道这之中是用什么算法算的吗?能不能给点资料或者提示?
目前已知的是:
corners的计算和R矩阵有关,但是计算过程不明了。
corners的xy值应该可以对应着图像的原点,但是打印出来是负数,不理解。
sizes应该有缩放的信息,可能对应着z的平移量。

先谢过啦!

  • 写回答

1条回答

  • zqbnqsdsmd 2016-11-26 15:37
    关注
    评论

报告相同问题?

悬赏问题

  • ¥15 maple软件,用solve求反函数出现rootof,怎么办?
  • ¥50 汇编语言除法溢出问题
  • ¥65 C++实现删除N个数据列表共有的元素
  • ¥15 Visual Studio问题
  • ¥15 state显示变量是字符串形式,但是仍然红色,无法引用,并显示类型不匹配
  • ¥20 求一个html代码,有偿
  • ¥100 关于使用MATLAB中copularnd函数的问题
  • ¥20 在虚拟机的pycharm上
  • ¥15 jupyterthemes 设置完毕后没有效果
  • ¥15 matlab图像高斯低通滤波