Beispiel #1
0
def main():
    
    optimizer = g2o.SparseOptimizer()
    # solver = g2o.BlockSolverSE3(g2o.LinearSolverEigenSE3())
    solver = g2o.BlockSolverSE3(g2o.LinearSolverCholmodSE3())
    # solver = g2o.BlockSolverSE3(g2o.LinearSolverCSparseSE3())
    solver = g2o.OptimizationAlgorithmLevenberg(solver)
    optimizer.set_algorithm(solver)

    # Convergence Criterion
    terminate = g2o.SparseOptimizerTerminateAction()
    terminate.set_gain_threshold(1e-6)
    optimizer.add_post_iteration_action(terminate)

    # Robust cost Function (Huber function) delta
    delta = np.sqrt(5.991)   

    true_points = np.hstack([
        np.random.random((25, 1)) * 3 - 1.5,
        np.random.random((25, 1)) - 0.5,
        np.random.random((25, 1)) + 3])


    fx = 600.
    fy = 600.
    cx = 320.
    cy = 240.

    principal_point = (cx, cy)
    cam = g2o.CameraParameters(fx, principal_point, 0)
    
    true_poses = []
    num_pose = 10
    for i in range(num_pose):
        # pose here means transform points from world coordinates to camera coordinates
        pose = g2o.SE3Quat(np.identity(3), [i*0.04-1, 0, 0])
            
        true_poses.append(pose)

        v_se3 = g2o.VertexSE3Expmap()
        v_se3.set_id(i)
        v_se3.set_estimate(pose)
        if i < 2:
            v_se3.set_fixed(True)
        optimizer.add_vertex(v_se3)

    print(optimizer.vertices())

    point_id = num_pose
    inliers = dict()
    sse = defaultdict(float)
    
    vp_edge = []

    for i, point in enumerate(true_points):
        visible = []
        for j, pose in enumerate(true_poses):
            z = cam.cam_map(pose * point)
            if 0 <= z[0] < 640 and 0 <= z[1] < 480:
                visible.append((j, z))
        if len(visible) < 2:
            continue

        vp = g2o.VertexSBAPointXYZ()
        
        vp.set_estimate(point + np.random.randn(3))
        
        vp.set_id(point_id)
        vp.set_marginalized(True)
        
        optimizer.add_vertex(vp)

        inlier = True
        for j, z in visible:
            if np.random.random() < args.outlier_ratio:
                inlier = False
                z = np.random.random(2) * [640, 480]
            z += np.random.randn(2) * args.pixel_noise

            e = g2o.EdgeSE3ProjectXYZ()
            
            e.set_vertex(0,vp)
            e.set_vertex(1,optimizer.vertex(j))
            
            e.set_measurement(z)
            
            e.set_information(np.identity(2))
            
            rk = g2o.RobustKernelHuber()
            
            e.set_robust_kernel(rk)
            rk.set_delta(delta)
            
            e.fx = fx
            e.fy = fy
            e.cx = cx
            e.cy = cy

            optimizer.add_edge(e)
            
            vp_edge.append(e)

        if inlier:
            inliers[point_id] = i
            error = vp.estimate() - true_points[i]
            sse[0] += np.sum(error**2)
        point_id += 1

    print('num vertices:', len(optimizer.vertices()))
    print('num edges:', len(optimizer.edges()))

    print(optimizer.vertices())
    
    print()

    print('Performing full BA:')
    
    
    optimizer.initialize_optimization()
    optimizer.set_verbose(True)
    optimizer.optimize(5)

    for i in inliers:
        vp = optimizer.vertex(i)
        error = vp.estimate() - true_points[inliers[i]]
        sse[1] += np.sum(error**2)

    print('\nRMSE (inliers only):')
    print('before optimization:', np.sqrt(sse[0] / len(inliers)))
    print('after  optimization:', np.sqrt(sse[1] / len(inliers)))
    
    # print(optimizer.vertices())

    print()
    
    for i in xrange(num_pose):
        print(optimizer.vertex(i).estimate().inverse().matrix())
        
        
    j = num_pose
    for i in xrange(len(inliers)):
        print(optimizer.vertex(j).estimate().shape)
        j += 1
        
    i = 0
    """
Beispiel #2
0
def bundle_adjustment(keyframes, points, local_window, fixed_points=False, verbose=False, rounds=10, use_robust_kernel=False, abort_flag=g2o.Flag()):
    if local_window is None:
        local_frames = keyframes
    else:
        local_frames = keyframes[-local_window:]

    # create g2o optimizer
    opt = g2o.SparseOptimizer()
    block_solver = g2o.BlockSolverSE3(g2o.LinearSolverCSparseSE3())
    #block_solver = g2o.BlockSolverSE3(g2o.LinearSolverCholmodSE3())        
    solver = g2o.OptimizationAlgorithmLevenberg(block_solver)
    opt.set_algorithm(solver)
    opt.set_force_stop_flag(abort_flag)

    thHuberMono = math.sqrt(5.991);  # chi-square 2 DOFS 

    graph_keyframes, graph_points = {}, {}

    # add frame vertices to graph
    for kf in (local_frames if fixed_points else keyframes):    # if points are fixed then consider just the local frames, otherwise we need all frames or at least two frames for each point
        if kf.is_bad:
            continue 
        #print('adding vertex frame ', f.id, ' to graph')
        se3 = g2o.SE3Quat(kf.Rcw, kf.tcw)
        v_se3 = g2o.VertexSE3Expmap()
        v_se3.set_estimate(se3)
        v_se3.set_id(kf.kid * 2)  # even ids  (use f.kid here!)
        v_se3.set_fixed(kf.kid==0 or kf not in local_frames) #(use f.kid here!)
        opt.add_vertex(v_se3)

        # confirm pose correctness
        #est = v_se3.estimate()
        #assert np.allclose(pose[0:3, 0:3], est.rotation().matrix())
        #assert np.allclose(pose[0:3, 3], est.translation())

        graph_keyframes[kf] = v_se3

    num_edges = 0
    
    # add point vertices to graph 
    for p in points:
        assert(p is not None)        
        if p.is_bad:  # do not consider bad points   
            continue
        if __debug__:        
            if not any([f in keyframes for f in p.keyframes()]):  
                Printer.red('point without a viewing frame!!')
                continue        
        #print('adding vertex point ', p.id,' to graph')
        v_p = g2o.VertexSBAPointXYZ()    
        v_p.set_id(p.id * 2 + 1)  # odd ids
        v_p.set_estimate(p.pt[0:3])
        v_p.set_marginalized(True)
        v_p.set_fixed(fixed_points)
        opt.add_vertex(v_p)
        graph_points[p] = v_p

        # add edges
        for kf, idx in p.observations():
            if kf.is_bad:
                continue 
            if kf not in graph_keyframes:
                continue
            #print('adding edge between point ', p.id,' and frame ', f.id)
            edge = g2o.EdgeSE3ProjectXYZ()
            edge.set_vertex(0, v_p)
            edge.set_vertex(1, graph_keyframes[kf])
            edge.set_measurement(kf.kpsu[idx])
            invSigma2 = Frame.feature_manager.inv_level_sigmas2[kf.octaves[idx]]
            edge.set_information(np.eye(2)*invSigma2)
            if use_robust_kernel:
                edge.set_robust_kernel(g2o.RobustKernelHuber(thHuberMono))

            edge.fx = kf.camera.fx 
            edge.fy = kf.camera.fy
            edge.cx = kf.camera.cx
            edge.cy = kf.camera.cy

            opt.add_edge(edge)
            num_edges += 1

    if verbose:
        opt.set_verbose(True)
    opt.initialize_optimization()
    opt.optimize(rounds)

    # put frames back
    for kf in graph_keyframes:
        est = graph_keyframes[kf].estimate()
        #R = est.rotation().matrix()
        #t = est.translation()
        #f.update_pose(poseRt(R, t))
        kf.update_pose(g2o.Isometry3d(est.orientation(), est.position()))

    # put points back
    if not fixed_points:
        for p in graph_points:
            p.update_position(np.array(graph_points[p].estimate()))
            p.update_normal_and_depth(force=True)
            
    mean_squared_error = opt.active_chi2()/max(num_edges,1)

    return mean_squared_error
Beispiel #3
0
def local_bundle_adjustment(keyframes, points, keyframes_ref=[], fixed_points=False, verbose=False, rounds=10, abort_flag=g2o.Flag(), map_lock=None):

    # create g2o optimizer
    opt = g2o.SparseOptimizer()
    block_solver = g2o.BlockSolverSE3(g2o.LinearSolverCSparseSE3())
    #block_solver = g2o.BlockSolverSE3(g2o.LinearSolverEigenSE3())  
    #block_solver = g2o.BlockSolverSE3(g2o.LinearSolverCholmodSE3())          
    solver = g2o.OptimizationAlgorithmLevenberg(block_solver)
    opt.set_algorithm(solver)
    opt.set_force_stop_flag(abort_flag)

    #robust_kernel = g2o.RobustKernelHuber(np.sqrt(5.991))  # chi-square 2 DOFs
    thHuberMono = math.sqrt(5.991);  # chi-square 2 DOFS 

    graph_keyframes, graph_points = {}, {}

    # add frame vertices to graph
    for kf in keyframes:    
        if kf.is_bad:
            continue 
        #print('adding vertex frame ', f.id, ' to graph')
        se3 = g2o.SE3Quat(kf.Rcw, kf.tcw)
        v_se3 = g2o.VertexSE3Expmap()
        v_se3.set_estimate(se3)
        v_se3.set_id(kf.kid * 2)  # even ids  (use f.kid here!)
        v_se3.set_fixed(kf.kid==0)  # (use f.kid here!)
        opt.add_vertex(v_se3)
        graph_keyframes[kf] = v_se3     
           
        # confirm pose correctness
        #est = v_se3.estimate()
        #assert np.allclose(pose[0:3, 0:3], est.rotation().matrix())
        #assert np.allclose(pose[0:3, 3], est.translation())
        
    # add reference frame vertices to graph
    for kf in keyframes_ref:    
        if kf.is_bad:
            continue 
        #print('adding vertex frame ', f.id, ' to graph')
        se3 = g2o.SE3Quat(kf.Rcw, kf.tcw)
        v_se3 = g2o.VertexSE3Expmap()
        v_se3.set_estimate(se3)
        v_se3.set_id(kf.kid * 2)  # even ids  (use f.kid here!)
        v_se3.set_fixed(True)
        opt.add_vertex(v_se3)
        graph_keyframes[kf] = v_se3             

    graph_edges = {}
    num_edges = 0
    num_bad_edges = 0

    # add point vertices to graph 
    for p in points:
        assert(p is not None)
        if p.is_bad:  # do not consider bad points             
            continue  
        if not any([f in keyframes for f in p.keyframes()]):  
            Printer.orange('point %d without a viewing keyframe in input keyframes!!' %(p.id))
            #Printer.orange('         keyframes: ',p.observations_string())
            continue
        #print('adding vertex point ', p.id,' to graph')
        v_p = g2o.VertexSBAPointXYZ()    
        v_p.set_id(p.id * 2 + 1)  # odd ids
        v_p.set_estimate(p.pt[0:3])
        v_p.set_marginalized(True)
        v_p.set_fixed(fixed_points)
        opt.add_vertex(v_p)
        graph_points[p] = v_p

        # add edges
        for kf, p_idx in p.observations():
            if kf.is_bad:
                continue 
            if kf not in graph_keyframes:
                continue
            if __debug__:      
                p_f = kf.get_point_match(p_idx)
                if p_f != p:
                    print('frame: ', kf.id, ' missing point ', p.id, ' at index p_idx: ', p_idx)                    
                    if p_f is not None:
                        print('p_f:', p_f)
                    print('p:',p)
            assert(kf.get_point_match(p_idx) is p)            
            #print('adding edge between point ', p.id,' and frame ', f.id)
            edge = g2o.EdgeSE3ProjectXYZ()
            edge.set_vertex(0, v_p)
            edge.set_vertex(1, graph_keyframes[kf])
            edge.set_measurement(kf.kpsu[p_idx])
            invSigma2 = Frame.feature_manager.inv_level_sigmas2[kf.octaves[p_idx]]
            edge.set_information(np.eye(2)*invSigma2)
            edge.set_robust_kernel(g2o.RobustKernelHuber(thHuberMono))

            edge.fx = kf.camera.fx 
            edge.fy = kf.camera.fy
            edge.cx = kf.camera.cx
            edge.cy = kf.camera.cy

            opt.add_edge(edge)

            graph_edges[edge] = (p,kf,p_idx) # one has kf.points[p_idx] == p
            num_edges += 1            

    if verbose:
        opt.set_verbose(True)

    if abort_flag.value:
        return -1,0

    # initial optimization 
    opt.initialize_optimization()
    opt.optimize(5)
    
    if not abort_flag.value:
        chi2Mono = 5.991 # chi-square 2 DOFs

        # check inliers observation 
        for edge, edge_data in graph_edges.items(): 
            p = edge_data[0]
            if p.is_bad:
                continue 
            if edge.chi2() > chi2Mono or not edge.is_depth_positive():
                edge.set_level(1)
                num_bad_edges += 1
            edge.set_robust_kernel(None)

        # optimize again without outliers 
        opt.initialize_optimization()
        opt.optimize(rounds)

    # search for final outlier observations and clean map  
    num_bad_observations = 0  # final bad observations
    outliers_data = []
    for edge, edge_data in graph_edges.items(): 
        p, kf, p_idx = edge_data
        if p.is_bad:
            continue         
        assert(kf.get_point_match(p_idx) is p) 
        if edge.chi2() > chi2Mono or not edge.is_depth_positive():         
            num_bad_observations += 1
            outliers_data.append(edge_data)       

    if map_lock is None: 
        map_lock = RLock() # put a fake lock 
        
    with map_lock:      
        # remove outlier observations 
        for d in outliers_data:
            p, kf, p_idx = d
            p_f = kf.get_point_match(p_idx)
            if p_f is not None:
                assert(p_f is p)
                p.remove_observation(kf,p_idx)
                # the following instruction is now included in p.remove_observation()
                #f.remove_point(p)   # it removes multiple point instances (if these are present)   
                #f.remove_point_match(p_idx) # this does not remove multiple point instances, but now there cannot be multiple instances any more

        # put frames back
        for kf in graph_keyframes:
            est = graph_keyframes[kf].estimate()
            #R = est.rotation().matrix()
            #t = est.translation()
            #f.update_pose(poseRt(R, t))
            kf.update_pose(g2o.Isometry3d(est.orientation(), est.position()))

        # put points back
        if not fixed_points:
            for p in graph_points:
                p.update_position(np.array(graph_points[p].estimate()))
                p.update_normal_and_depth(force=True)

    active_edges = num_edges-num_bad_edges
    mean_squared_error = opt.active_chi2()/active_edges

    return mean_squared_error, num_bad_observations/max(num_edges,1)
Beispiel #4
0
def optimization(frames,
                 points,
                 local_window,
                 fixed_points=False,
                 verbose=False,
                 rounds=40,
                 use_robust_kernel=False):
    if local_window is None:
        local_frames = frames
    else:
        local_frames = frames[-local_window:]

    # create g2o optimizer
    opt = g2o.SparseOptimizer()
    solver = g2o.BlockSolverSE3(g2o.LinearSolverCSparseSE3())
    solver = g2o.OptimizationAlgorithmLevenberg(solver)
    opt.set_algorithm(solver)

    thHuberMono = math.sqrt(5.991)
    # chi-square 2 DOFS

    graph_frames, graph_points = {}, {}

    # add frame vertices to graph
    for f in (
            local_frames if fixed_points else frames
    ):  # if points are fixed then consider just the local frames, otherwise we need all frames or at least two frames for each point
        #print('adding vertex frame ', f.id, ' to graph')
        pose = f.pose
        se3 = g2o.SE3Quat(pose[0:3, 0:3], pose[0:3, 3])
        v_se3 = g2o.VertexSE3Expmap()
        v_se3.set_estimate(se3)
        v_se3.set_id(f.id * 2)  # even ids
        v_se3.set_fixed(f.id < 1 or f not in local_frames)
        opt.add_vertex(v_se3)

        # confirm pose correctness
        #est = v_se3.estimate()
        #assert np.allclose(pose[0:3, 0:3], est.rotation().matrix())
        #assert np.allclose(pose[0:3, 3], est.translation())

        graph_frames[f] = v_se3

    # add point vertices to graph
    for p in points:
        if p.is_bad and not fixed_points:
            continue
        if not any([f in local_frames for f in p.frames]):
            continue
        #print('adding vertex point ', p.id,' to graph')
        v_p = g2o.VertexSBAPointXYZ()
        v_p.set_id(p.id * 2 + 1)  # odd ids
        v_p.set_estimate(p.pt[0:3])
        v_p.set_marginalized(True)
        v_p.set_fixed(fixed_points)
        opt.add_vertex(v_p)
        graph_points[p] = v_p

        # add edges
        for f, idx in zip(p.frames, p.idxs):
            if f not in graph_frames:
                continue
            #print('adding edge between point ', p.id,' and frame ', f.id)
            edge = g2o.EdgeSE3ProjectXYZ()
            edge.set_vertex(0, v_p)
            edge.set_vertex(1, graph_frames[f])
            edge.set_measurement(f.kpsu[idx])
            invSigma2 = Frame.detector.inv_level_sigmas2[f.octaves[idx]]
            edge.set_information(np.eye(2) * invSigma2)
            if use_robust_kernel:
                edge.set_robust_kernel(g2o.RobustKernelHuber(thHuberMono))

            edge.fx = f.fx
            edge.fy = f.fy
            edge.cx = f.cx
            edge.cy = f.cy

            opt.add_edge(edge)

    if verbose:
        opt.set_verbose(True)
    opt.initialize_optimization()
    opt.optimize(rounds)

    # put frames back
    for f in graph_frames:
        est = graph_frames[f].estimate()
        R = est.rotation().matrix()
        t = est.translation()
        f.pose = poseRt(R, t)

    # put points back
    if not fixed_points:
        for p in graph_points:
            p.pt = np.array(graph_points[p].estimate())

    return opt.active_chi2()
Beispiel #5
0
def localOptimization(frames,
                      points,
                      frames_ref=[],
                      fixed_points=False,
                      verbose=False,
                      rounds=10):

    # create g2o optimizer
    opt = g2o.SparseOptimizer()
    solver = g2o.BlockSolverSE3(g2o.LinearSolverCSparseSE3())
    solver = g2o.OptimizationAlgorithmLevenberg(solver)
    opt.set_algorithm(solver)

    #robust_kernel = g2o.RobustKernelHuber(np.sqrt(5.991))  # chi-square 2 DOFs
    thHuberMono = math.sqrt(5.991)
    # chi-square 2 DOFS

    graph_frames, graph_points = {}, {}

    all_frames = frames + frames_ref

    # add frame vertices to graph
    for f in all_frames:
        #print('adding vertex frame ', f.id, ' to graph')
        pose = f.pose
        se3 = g2o.SE3Quat(pose[0:3, 0:3], pose[0:3, 3])
        v_se3 = g2o.VertexSE3Expmap()
        v_se3.set_estimate(se3)
        v_se3.set_id(f.id * 2)  # even ids
        v_se3.set_fixed(f.id < 1 or f in frames_ref)
        opt.add_vertex(v_se3)
        graph_frames[f] = v_se3
        # confirm pose correctness
        #est = v_se3.estimate()
        #assert np.allclose(pose[0:3, 0:3], est.rotation().matrix())
        #assert np.allclose(pose[0:3, 3], est.translation())

    graph_edges = {}
    num_point_edges = 0

    # add point vertices to graph
    for p in points:
        assert (p is not None)
        if p.is_bad and not fixed_points:  # do not consider bad points unless they are fixed
            continue
        if not any([f in frames for f in p.frames]):  # this is redundant now
            continue
        #print('adding vertex point ', p.id,' to graph')
        v_p = g2o.VertexSBAPointXYZ()
        v_p.set_id(p.id * 2 + 1)  # odd ids
        v_p.set_estimate(p.pt[0:3])
        v_p.set_marginalized(True)
        v_p.set_fixed(fixed_points)
        opt.add_vertex(v_p)
        graph_points[p] = v_p

        # add edges
        for f, p_idx in zip(p.frames, p.idxs):
            assert (f.points[p_idx] == p)
            if f not in graph_frames:
                continue
            #print('adding edge between point ', p.id,' and frame ', f.id)
            edge = g2o.EdgeSE3ProjectXYZ()
            edge.set_vertex(0, v_p)
            edge.set_vertex(1, graph_frames[f])
            edge.set_measurement(f.kpsu[p_idx])
            invSigma2 = Frame.detector.inv_level_sigmas2[f.octaves[p_idx]]
            edge.set_information(np.eye(2) * invSigma2)
            edge.set_robust_kernel(g2o.RobustKernelHuber(thHuberMono))

            edge.fx = f.fx
            edge.fy = f.fy
            edge.cx = f.cx
            edge.cy = f.cy

            opt.add_edge(edge)

            graph_edges[edge] = (p, f, p_idx)  # f.points[p_idx] == p
            num_point_edges += 1

    if verbose:
        opt.set_verbose(True)

    # initial optimization
    opt.initialize_optimization()
    opt.optimize(5)

    chi2Mono = 5.991  # chi-square 2 DOFs

    # check inliers observation
    for edge, edge_data in graph_edges.items():
        p = edge_data[0]
        if p.is_bad is True:
            continue
        if edge.chi2() > chi2Mono or not edge.is_depth_positive():
            edge.set_level(1)
        edge.set_robust_kernel(None)

    # optimize again without outliers
    opt.initialize_optimization()
    opt.optimize(rounds)

    # clean map observations
    num_bad_observations = 0
    outliers_data = []
    for edge, edge_data in graph_edges.items():
        p, f, p_idx = edge_data
        if p.is_bad is True:
            continue
        assert (f.points[p_idx] == p)
        if edge.chi2() > chi2Mono or not edge.is_depth_positive():
            num_bad_observations += 1
            outliers_data.append((p, f, p_idx))

    for d in outliers_data:
        (p, f, p_idx) = d
        assert (f.points[p_idx] == p)
        p.remove_observation(f, p_idx)
        f.remove_point(p)

    # put frames back
    for f in graph_frames:
        est = graph_frames[f].estimate()
        R = est.rotation().matrix()
        t = est.translation()
        f.pose = poseRt(R, t)

    # put points back
    if not fixed_points:
        for p in graph_points:
            p.pt = np.array(graph_points[p].estimate())

    return opt.active_chi2(), num_bad_observations / num_point_edges
Beispiel #6
0
    v_p.set_estimate(point)
    v_p.set_marginalized(marginalized)
    v_p.set_fixed(fixed)

    super().add_vertex(v_p)
    return v_p

  # @todo : TODO
  def add_edge(self, edge_id, point_id, pose_id,
               measurement,
               information=np.identity(2),
               robust_kernel=g2o.RobustKernelHuber(np.sqrt(5.991))):
    # edge = g2o.EdgeSE3ProjectXYZOnlyPose()
    # edge = g2o.EdgeSE3ProjectXYZ()
    edge = g2o.EdgeProjectXYZ2UV()
    edge.set_id(edge_id)
    edge.set_vertex(0, self.vertex(point_id))
    edge.set_vertex(1, self.vertex(pose_id))
    edge.set_measurement(measurement)
    edge.set_information(information)
    if robust_kernel is not None:
      edge.set_robust_kernel(robust_kernel)
    edge.set_parameter_id(0, 0)
    super().add_edge(edge)
    return edge

if __name__ == "__main__":
    edge = g2o.EdgeSE3ProjectXYZ()
    # edge = g2o.EdgeSE3ProjectXYZOnlyPose()
    # passed!
    print(edge.fx)