首页 > 解决方案 > 3D 重建返回意大利面条结果

问题描述

我目前正在做我的毕业项目,对多张图像进行 3D 重建。我将项目分为两部分,一是使用运动结构恢复点云(我正在从这里学习代码,另一部分是从点云生成表面(我正在从本文中学习)。

我的第一个实现可以在这里看到,第二个在这里

他们两个都是......我猜是可以接受的吗?这是点云恢复的工作结果:

从多个图像恢复点云

这是输入图像:

输入图像

我想这还不错。如果输入数据集不是来自第一个数据集,例如这个兔子,表面重建部分的效果也不错:

兔子

但是,当我将第一个输入插入第二个时,这就是我得到的:

混乱

我完全不知道为什么会这样。我目前的估计是缺少功能,但我不知道真正的原因,也不知道如何增加可用功能。我在 OpenCV 中使用 ORB 并增加功能只会使匹配更加混乱,进而使结果点云更加混乱。

我已经坚持了好几天了,我将永远感激那些提供帮助的人。非常感谢!

代码

代码有点长,所以我将在此处发布摘录:

SfM 部分

Result SfM::run_sfm() {
    if (images.empty()) {
        LOG("There is no image to work on.");
        return ERR;
    }
    
    // Initialize feature matcher
    feature_util.init();
    stereo_util.init();
    
    // Initialize intrinsics
    intrinsics.k = (cv::Mat_<float>(3, 3) << 2500, 0, images[0].cols / 2,
                                             0, 2500, images[0].rows / 2,
                                             0, 0, 1);
    intrinsics.k_inv = intrinsics.k.inv();
    intrinsics.distortion = cv::Mat_<float>::zeros(1, 4);
    
    camera_poses.resize(images.size());
    
    extract_features();
    create_feature_match_matrix();
    find_baseline_triangulation();
    add_more_views_to_reconstruction();
    
    return OK;
}

表面重建部分

auto Hoppe::run() -> bool {
    if (pointcloud.points.size() == 0) {
        HOPPE_LOG("ERR! Can't run without point cloud");
        return false;
    }

    estimate_planes();

    fix_orientations();
    
    cube_march();

    return true;
}

这是cube_march()

auto Hoppe::cube_march() -> void {
    cv::Vec3f bounding_box_min, bounding_box_max;
    calculate_bounds(bounding_box_min, bounding_box_max);
    auto size = bounding_box_max - bounding_box_min;
    HOPPE_LOG("Bounding box size: %f %f %f", size(0), size(1), size(2));

    parameters.density = density_estimation(size);

    cv::Vec3i marching_size(ceilf(size(0) / parameters.density),
                            ceilf(size(1) / parameters.density),
                            ceilf(size(2) / parameters.density));
    auto volume = 0;
    do {
        volume = marching_size(0) * marching_size(1) * marching_size(2);
        if (volume > parameters.max_volume) {
            parameters.density *= 2.0f;
            marching_size = cv::Vec3i(ceilf(size(0) / parameters.density),
                                      ceilf(size(1) / parameters.density),
                                      ceilf(size(2) / parameters.density));
        }
    } while (volume > parameters.max_volume);
    
    HOPPE_LOG("Marching cube size: %d %d %d", marching_size(0),
              marching_size(1), marching_size(2));
    marcher.init(marching_size, parameters.density);
    HOPPE_LOG("Estimated: from %f %f %f to %f %f %f",
              bounding_box_min(0), bounding_box_min(1), bounding_box_min(2),
              bounding_box_max(0), bounding_box_max(1), bounding_box_max(2));

    marcher.march([&] (cv::Point3f p) {
        return sdf(p);
    }, VEC2POINT(bounding_box_min));
}

如果你问,我很乐意提供更多信息。谢谢!

标签: c++opencv3d-reconstruction

解决方案


推荐阅读