MIT-SPARK / TEASER-plusplus

A fast and robust point cloud registration library
MIT License
1.76k stars 340 forks source link

[QUESTION] The certification algorithm doesn't work well on my own data, and the suboptimal gap is very large. #180

Open zouxianghong opened 8 months ago

zouxianghong commented 8 months ago

Have you read the documentation?

Post your theoretical questions / usage questions here.

The default sub_optimality is 0.001, while the best suboptimal value obtained by the certification algorithm is very large. Here are two cases: case1: registration result is good while the best suboptimal value is so large (419.4077). Screenshot from 2024-01-26 16-38-48

case2: registration result is bad while the best suboptimal value is less than case1 (4.6976) Screenshot from 2024-01-26 16-40-40 Note: The ground truth rotations of the above cases are Identity, so the lines of correspondences should be parallel.

The best suboptimal values of two cases above are much larger than the default threshold (0.001) in TEASER++. Looking forward to your reply, thank you so much!

Here are the params and code:

# solver / certifier params
cbar2: 1
noise_bound: 1.0
estimate_scaling: False
rotation_gnc_factor: 1.4
rotation_max_iterations: 100
rotation_cost_threshold: 1e-6
sub_optimality: 100  # 1e-3

# code
def reg_with_teaser(self, q_kpts, m_kpts):
    ''' @Input: q_kpts: N x 3, m_kpts: N x 3
        @Return: est_R, est_t, est_theta
    '''
    self.solver.reset(self.solver_params)
    self.solver.solve(q_kpts.T, m_kpts.T)  # src: 3 x N, dst: 3 x N
    solution = self.solver.getSolution()
    mac_inliers = self.solver.getInlierMaxClique()
    rotation_inlier_mask = self.solver.getRotationInliersMask()
    translation_inlier_mask = self.solver.getTranslationInliersMask()
    mask = rotation_inlier_mask & translation_inlier_mask
    inliers = np.array(mac_inliers)[mask]
    est_theta = np.ones(len(q_kpts), dtype=int) * -1
    est_theta[inliers] = 1  # inliers
    return solution.rotation, solution.translation, est_theta

def certify(self, q_kpts, m_kpts, est_R, est_theta):
    ''' @Input: q_kpts: N x 3, m_kpts: N x 3,
                theta: N ({1, -1}, 1: inlier, -1: outlier),
                est_R: 3 x 3
        @Return: is_optimal: bool, True if best_suboptimality < sub_optimality, else False
                 best_suboptimality: double
    '''
    certify_res = self.certifier.certify(est_R, q_kpts.T, m_kpts.T, est_theta.reshape(1, -1))
    return certify_res.is_optimal, certify_res.best_suboptimality
jingnanshi commented 6 months ago

Hi @zouxianghong Thanks for the report unfortunately I currently do not have the bandwidth to investigate this issue. I'm leaving this open in case anyone will be interested in taking a look.

zouxianghong commented 6 months ago

谢谢,收到

LimHyungTae commented 6 months ago

Could you more elaborate what does "while the best suboptimal value is so large " mean, please?