예제 #1
0
def calibrate_extrinsic(config):
    path, videos, vid_indices = get_video_path(config)
    output_filename = 'extrinsics.toml'
    output_path = os.path.join(path, output_filename)

    if os.path.exists(output_path):
        print('\n{} already exists.'.format(output_filename))
        return

    try:
        intrinsics = load_intrinsics(path, vid_indices)
    except:
        print("\nIntrinsic calibration output does not exist.")
        return

    board = get_calibration_board(config)
    cam_align = config['triangulation']['cam_align']

    extrinsics, error = get_extrinsics(vid_indices, videos, intrinsics,
                                       cam_align, board)

    extrinsics_out = {}
    for k, v in extrinsics.items():
        extrinsics_out[k] = v.tolist()
    extrinsics_out['error'] = float(error)

    with open(output_path, 'w') as f:
        toml.dump(extrinsics_out, f)
예제 #2
0
def validate_3d(config, **kwargs):
    path, videos, vid_indices = get_video_path(config)
    bp_interested = config['labeling']['bodyparts_interested']
    reconstruction_threshold = config['triangulation'][
        'reconstruction_threshold']
    if config['triangulation'].get('reconstruction_output_path') is None:
        output_path = kwargs.get('output_path', '')
    else:
        output_path = config['triangulation']['reconstruction_output_path']

    try:
        intrinsics = load_intrinsics(path, vid_indices)
    except:
        print("Intrinsic calibration output does not exist.")
        return

    try:
        extrinsics = load_extrinsics(path)
    except:
        print("Extrinsic calibration output does not exist.")
        return

    cam_mats = []
    cam_mats_dist = []

    for vid_idxs in vid_indices:
        mat = arr(extrinsics[vid_idxs])
        left = arr(intrinsics[vid_idxs]['camera_mat'])
        cam_mats.append(mat)
        cam_mats_dist.append(left)

    cam_mats = arr(cam_mats)
    cam_mats_dist = arr(cam_mats_dist)

    out = load_labeled_2d_data(config, vid_indices, bp_interested)

    all_points_raw = out['points']

    all_points_und = undistort_points(all_points_raw, vid_indices, intrinsics)

    length = all_points_raw.shape[0]
    shape = all_points_raw.shape

    all_points_3d = np.zeros((shape[0], shape[2], 3))
    all_points_3d.fill(np.nan)

    errors = np.zeros((shape[0], shape[2]))
    errors.fill(np.nan)

    scores_3d = np.zeros((shape[0], shape[2]))
    scores_3d.fill(np.nan)

    num_cams = np.zeros((shape[0], shape[2]))
    num_cams.fill(np.nan)

    for i in trange(all_points_und.shape[0], ncols=70):
        for j in range(all_points_und.shape[2]):
            pts = all_points_und[i, :, j, :]
            good = ~np.isnan(pts[:, 0])
            if np.sum(good) >= 2:
                # TODO: make triangulation type configurable
                # p3d = triangulate_optim(pts[good], cam_mats[good])
                p3d = triangulate_simple(pts[good], cam_mats[good])
                all_points_3d[i, j] = p3d[:3]
                errors[i, j] = reprojection_error_und(p3d, pts[good],
                                                      cam_mats[good],
                                                      cam_mats_dist[good])
                num_cams[i, j] = np.sum(good)

    if 'reference_point' in config['triangulation'] and 'axes' in config[
            'triangulation']:
        all_points_3d_adj = correct_coordinate_frame(config, all_points_3d,
                                                     bp_interested)
    else:
        all_points_3d_adj = all_points_3d

    dout = pd.DataFrame()
    for bp_num, bp in enumerate(bp_interested):
        for ax_num, axis in enumerate(['x', 'y', 'z']):
            dout[bp + '_' + axis] = all_points_3d_adj[:, bp_num, ax_num]
        dout[bp + '_error'] = errors[:, bp_num]
        dout[bp + '_ncams'] = num_cams[:, bp_num]

    dout['fnum'] = np.arange(length)

    dout.to_csv(os.path.join(output_path, 'validate_3d_data.csv'), index=False)
예제 #3
0
def reconstruction_validation(config, img_paths):
    images = [cv2.imread(img_path) for img_path in img_paths]
    
    board = get_calibration_board(config)
    (w,h) = board.getChessboardSize()
    num_corners = (w-1)*(h-1)
    
    path, videos, vid_indices = get_video_path(config)
    num_cams = len(vid_indices)
    intrinsics = load_intrinsics(path, vid_indices)
    
    all_detectedCorners = np.zeros((num_corners, num_cams, 2))
    all_detectedCorners.fill(np.nan)
    all_detectedIds = []
    images_with_corners = []
    
    for i, (image, vid_idx) in enumerate(zip(images, vid_indices)):
        gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        intrinsic = intrinsics[vid_idx]
        detectedCorners, detectedIds = detect_aruco(gray, intrinsic, board)
        images_with_corners.append(cv2.aruco.drawDetectedCornersCharuco(image, 
                                                     detectedCorners,
                                                     detectedIds))
        all_detectedIds.append(detectedIds)
        
        for coord, j in zip(detectedCorners, detectedIds):
            all_detectedCorners[j[0]][i] = coord
    
    extrinsics = load_extrinsics(path)
    
    cam_mats = np.array([extrinsics[vid_idx] for vid_idx in vid_indices])
    
    undistorted_corners = undistort_points(all_detectedCorners, vid_indices, intrinsics)
    
    points_3d, _ = triangulate_points(undistorted_corners, cam_mats)
    points_3d = points_3d[:, :3]
    
    points_3d_transform = transform_corners(points_3d, w, h)
    
    square_length = config['calibration']['board_square_side_length']
    
    x = np.linspace((-w/2+1)*square_length, (w/2-1)*square_length, w-1)
    y = np.linspace((-h/2+1)*square_length, (h/2-1)*square_length, h-1)
    xv, yv = np.meshgrid(x, y)
    
    pseudo_real_corners = np.zeros((num_corners, 3))
    pseudo_real_corners[:, 0] = np.reshape(xv, (-1))
    pseudo_real_corners[:, 1] = np.reshape(yv, (-1))

    subplot_w = int(num_cams // np.floor(np.sqrt(num_cams)))
    subplot_h = num_cams / subplot_w
    
    fig = plt.figure()
    
    for i in range(num_cams):
        ax = fig.add_subplot(subplot_w, subplot_h, i+1)
        ax.imshow(images_with_corners[i])
        ax.axis('off')
    
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    
    labels = ['id_'+str(i) for i in range(num_corners)]
    
    for i, (pred, real) in enumerate(zip(points_3d_transform, pseudo_real_corners)):
        ax.scatter(pred[0], pred[1], pred[2], c='r', alpha=0.5)
        ax.scatter(real[0], real[1], real[2], c='b', alpha=0.5)
        annotate3D(ax, s=labels[i], xyz=pred, fontsize=8, xytext=(-3,3),
               textcoords='offset points', ha='center',va='bottom')
    
    ax_min, ax_max = -np.floor(max(w, h)*square_length)//2, np.floor(max(w, h)*square_length//2)
    ax.set_xlim([ax_min, ax_max])
    ax.set_ylim([ax_min, ax_max])
    ax.set_zlim([ax_min, ax_max])
    ax.view_init(elev=50, azim=-70)
    
    ax.set_xlabel('x (mm)')
    ax.set_ylabel('y (mm)')
    ax.set_zlabel('z (mm)')    
        
    return points_3d, points_3d_transform