CVPR:A Two-point Method for PTZ Camera Calibration in Sports的C++程序分析(2)

CVPR:A Two-point Method for PTZ Camera Calibration in Sports的C++程序分析(2)

首先声明一些变量,

    const char * model_file = "/Users/jimmy/Desktop/BTDT_ptz_soccer/model/seq2_model.txt";
    const char * ptz_feature_folder = "/Users/jimmy/Desktop/BTDT_ptz_soccer/soccer_data/train_data/seq1_ptz_sift_inlier/*.mat";
    const int max_check =  8;
    const double reprojection_error_threshold = 2.0;
    const double distance_threshold = 0.2;
    const int sample_number = 32;
    const char * save_file = "result.mat";

其中,model_file指txt文件seq2_model的存放路径,该文档记录了随机森林的训练结果。ptz_feature_folder指用来做预测的图片的存放路径。然后加载随机森林模型model。

    BTDTRegressor model;
    bool is_read = model.load(model_file);
    assert(is_read);
    
    if (maxTreeNum == -1) {
        maxTreeNum = model.treeNum();
    }
    printf("use %d trees in the test\n", maxTreeNum);

做初始化操作,把用来做预测的图片路径存放到vector<string>型的feature_files中。MatrixXd型变量gt_ptz_all指测试集所有图像对应的Pan,Tilt,focal的真值,而MatrixXd型变量estimated_ptz_all指测试集所有图像对应的Pan,Tilt,focal的估计值。最后我们要计算真值和估计值之间的偏差。

    // read testing examples
    vector<string> feature_files;
    CvxUtil::readFilenames(ptz_feature_folder, feature_files);
    
    Eigen::Vector2d pp(1280.0/2.0, 720.0/2.0);
    ptz_pose_opt::PTZPreemptiveRANSACParameter param;
    param.reprojection_error_threshold_ = reprojection_error_threshold;
    param.sample_number_ = sample_number;
    printf("principal point is fixed at %lf %lf\n", pp.x(), pp.y());
    printf("inlier reprojection error is %lf pixels\n", param.reprojection_error_threshold_);
    
    Eigen::MatrixXd gt_ptz_all(feature_files.size(), 3);
    Eigen::MatrixXd estimated_ptz_all(feature_files.size(), 3);

接下来进入一个循环,即对测试集的每一帧图像都会做预测评估的处理。

    int index = 0;
  for (const string &file_name: feature_files){ //.. }

先看这个循环的第一块,

        vector<btdtr_ptz_util::PTZSample> samples;
        Eigen::Vector3f ptz;
        btdtr_ptz_util::generatePTZSampleWithFeature(file_name.c_str(), pp.cast<float>(), ptz, samples);
        Eigen::Vector3d ptz_gt(ptz.x(), ptz.y(), ptz.z());
        printf("feature number is %lu\n", samples.size());
        
        vector<Eigen::Vector2d> image_points;
        vector<vector<Eigen::Vector2d> > candidate_pan_tilt;
        Eigen::Vector3d estimated_ptz(0, 0, 0);
首先应该弄清楚samples是什么。它是vector<btdtr_ptz_util::PTZSample>型的变量,刚刚被初始化。那么PTZSample是什么呢?根据btdtr_ptz_util的头文件,可以看见PTZSample的定义,发现它分为,像素点位置,相机拍摄像素点所在的图像时的Pan,以及Tilt角(这是真值,待会要与估计值向减求误差的),以及像素点SIFT描述子信息。
class PTZSample
{
public:
    Eigen::Vector2f  loc_;     // 2D location (x, y)
    Eigen::VectorXf  pan_tilt_;       //  Pan, tilt parameter in world coordinate, label
    Eigen::VectorXf  descriptor_; // image patch descriptor, feature
    
    PTZSample() {
        pan_tilt_ = Eigen::VectorXf::Zero(2, 1);
    }
    
};
那么函数generatePTZSampleWithFeature作用是什么?
    void generatePTZSampleWithFeature(const char * feature_ptz_file_name,
                                      const Eigen::Vector2f& pp,
                                      Eigen::Vector3f & ptz,
                                      vector<PTZSample> & samples)
    {
        assert(feature_ptz_file_name);
        
        vector<Eigen::VectorXf> locations;
        vector<Eigen::VectorXf> features;
        readPTZFeatureLocationAndDescriptors(feature_ptz_file_name, ptz, locations, features);
        for (int i = 0; i<locations.size(); i++) {
            PTZSample s;
            Eigen::Vector2f pan_tilt;
            s.loc_[0] = locations[i][0];
            s.loc_[1] = locations[i][1];
            EigenX::pointPanTilt(pp, ptz, s.loc_, pan_tilt);
            s.pan_tilt_[0] = pan_tilt[0];
            s.pan_tilt_[1] = pan_tilt[1];
            s.descriptor_ = features[i];
            samples.push_back(s);
        }
    }
    

从上述代码可以发现这个非常简单。从feature_ptz_file_name这个文件读取像素点的相关信息。一共有location.size()个像素点。而每一个像素点都有它们的PT角信息,SIFT描述子信息。而它们一一存入vector<btdtr_ptz_util::PTZSample>类型的变量samples中。而readPTZFeatureLocationAndDescriptors这个函数的意义非常直接,不必分析。

函数generatePTZSampleWithFeature已经分析清楚了(说白了就是把真值ground truth罗列出来,与之后的估计值向减,把估计误差算出来)。再来分析for循环第一块的其他声明变量。为了方便观看,再次抄在下面。

        Eigen::Vector3d ptz_gt(ptz.x(), ptz.y(), ptz.z());
        printf("feature number is %lu\n", samples.size());
        
        vector<Eigen::Vector2d> image_points;
        vector<vector<Eigen::Vector2d> > candidate_pan_tilt;
        Eigen::Vector3d estimated_ptz(0, 0, 0);

Vector3d型变量ptz_gt(即ground truth)指相机拍摄这一帧图画的pan角,tilt角,focal的真值。

vector<Vector2d>型变量image_points指这一帧图像中选中的像素点的像素位置。

至于vector<vector<Vector2d>>型变量candidate_pan_tilt指随机森林的预测值,在上一讲也提及过,并不是惟一的。所以要列出一个候补名单,然后用RANSAC做筛选,得到最后的估计值estimated_ptz。

最后罗嗦一句,变量的命名尤为重要,不仅方便看代码的人,也方便写代码的人!


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值