def main(serial):
    # Read camera parameters
    image_width, image_height, camera_matrix, dist_coeffs = utils.get_camera_params(serial)

    # Set up webcam
    cap = utils.get_video_cap(serial, image_width, image_height)

    # Set up aruco dict
    aruco_dict = cv2.aruco.Dictionary_get(utils.get_marker_dict_id())

    while True:
        if cv2.waitKey(1) == 27:  # Esc key
            break

        image = None
        while image is None:
            _, image = cap.read()

        # Undistort image and detect markers
        image = cv2.undistort(image, camera_matrix, dist_coeffs)
        corners, ids, _ = cv2.aruco.detectMarkers(image, aruco_dict)

        # Show detections
        image_copy = image.copy()
        if ids is not None:
            cv2.aruco.drawDetectedMarkers(image_copy, corners, ids)
        cv2.imshow('out', image_copy)

    cap.release()
    cv2.destroyAllWindows()
 def __init__(self, serial):
     image_width, image_height, camera_matrix, dist_coeffs = utils.get_camera_params(serial)
     self._map_x, self._map_y = cv2.initUndistortRectifyMap(camera_matrix, dist_coeffs, None, camera_matrix, (image_width, image_height), cv2.CV_32FC1)
     self._cap = utils.get_video_cap(serial, image_width, image_height)
     self._queue = Queue(maxsize=1)
     self._thread = Thread(target=self._worker)
     self._thread.start()
def main(args):
    # Read camera parameters
    camera_params_file_path = utils.get_camera_params_file_path(
        args.camera_name)
    image_width, image_height, camera_matrix, dist_coeffs = utils.get_camera_params(
        camera_params_file_path)

    # Set up webcam
    cap = utils.get_video_cap(image_width, image_height, args.camera_id)

    # Set up aruco dict
    params = utils.get_marker_parameters()
    aruco_dict = cv2.aruco.Dictionary_get(params['dict_id'])

    # Enable corner refinement
    #detector_params = cv2.aruco.DetectorParameters_create()
    #detector_params.cornerRefinementMethod = cv2.aruco.CORNER_REFINE_SUBPIX

    while True:
        if cv2.waitKey(1) == 27:  # Esc key
            break

        _, image = cap.read()
        if image is None:
            continue

        # Undistort image and detect markers
        image = cv2.undistort(image, camera_matrix, dist_coeffs)
        #corners, ids, _ = cv2.aruco.detectMarkers(image, aruco_dict, parameters=detector_params)
        corners, ids, _ = cv2.aruco.detectMarkers(image, aruco_dict)

        # Show detections
        image_copy = image.copy()
        if ids is not None:
            cv2.aruco.drawDetectedMarkers(image_copy, corners, ids)
        cv2.imshow('out', image_copy)

    cap.release()
    cv2.destroyAllWindows()
Beispiel #4
0
def main(args):
    # Read camera parameters
    camera_params_file_path = utils.get_camera_params_file_path(
        args.camera_name)
    image_width, image_height, camera_matrix, dist_coeffs = utils.get_camera_params(
        camera_params_file_path)

    # Set up webcam
    cap = utils.get_video_cap(image_width, image_height, args.camera_id)

    # Board and marker params
    boards = [{
        'name': 'robots',
        'corner_offset_mm': 36
    }, {
        'name': 'cubes',
        'corner_offset_mm': 12
    }]
    marker_params = utils.get_marker_parameters()
    room_length_mm = 1000 * args.room_length
    room_width_mm = 1000 * args.room_width
    room_length_pixels = int(room_length_mm * marker_params['pixels_per_mm'])
    room_width_pixels = int(room_width_mm * marker_params['pixels_per_mm'])

    # Set up aruco dicts
    for board in boards:
        aruco_dict = cv2.aruco.Dictionary_get(marker_params['dict_id'])
        aruco_dict.bytesList = aruco_dict.bytesList[utils.get_marker_ids(
            'corners_{}'.format(board['name']))]
        board['board_dict'] = aruco_dict
        aruco_dict = cv2.aruco.Dictionary_get(marker_params['dict_id'])
        aruco_dict.bytesList = aruco_dict.bytesList[utils.get_marker_ids(
            board['name'])]
        board['marker_dict'] = aruco_dict

    # Board warping
    for board in boards:
        corner_offset_pixels = board['corner_offset_mm'] * marker_params[
            'pixels_per_mm']
        board['src_points'] = None
        board['dst_points'] = [
            [-corner_offset_pixels, -corner_offset_pixels],
            [room_length_pixels + corner_offset_pixels, -corner_offset_pixels],
            [
                room_length_pixels + corner_offset_pixels,
                room_width_pixels + corner_offset_pixels
            ],
            [-corner_offset_pixels, room_width_pixels + corner_offset_pixels]
        ]

    # Enable corner refinement
    detector_params = cv2.aruco.DetectorParameters_create()
    detector_params.cornerRefinementMethod = cv2.aruco.CORNER_REFINE_SUBPIX

    # Set up server
    address = ('localhost', 6000)
    listener = Listener(address, authkey=b'secret password')
    conn = None

    def process_image(image):
        # Undistort image
        image = cv2.undistort(image, camera_matrix, dist_coeffs)

        data = {}
        for board in boards:
            board_name = board['name']
            data[board_name] = {}

            if board['src_points'] is None:
                # Detect board markers (assumes board won't move since this is only done once)
                #board_corners, board_indices, _ = cv2.aruco.detectMarkers(image, board['board_dict'], parameters=detector_params)
                board_corners, board_indices, _ = cv2.aruco.detectMarkers(
                    image, board['board_dict'])

                # Show detections
                if args.debug:
                    image_copy = image.copy()
                    if board_indices is not None:
                        cv2.aruco.drawDetectedMarkers(image_copy,
                                                      board_corners,
                                                      board_indices)
                    cv2.imshow('{}_board_corners'.format(board_name),
                               image_copy)

                # Ensure board was found
                if board_indices is None or len(board_indices) < 4:
                    data[
                        board_name] = None  # None rather than {} to signify board was not detected
                    continue

                board['src_points'] = []
                for marker_index, corner in sorted(
                        zip(board_indices, board_corners)):
                    board['src_points'].append(
                        corner.squeeze(0).mean(axis=0).tolist())
            else:
                # Warp the board
                M = cv2.getPerspectiveTransform(
                    np.asarray(board['src_points'], dtype=np.float32),
                    np.asarray(board['dst_points'], dtype=np.float32))
                warped_image = cv2.warpPerspective(
                    image, M, (room_length_pixels, room_width_pixels))

                # Detect markers in warped image
                corners, indices, _ = cv2.aruco.detectMarkers(
                    warped_image,
                    board['marker_dict'],
                    parameters=detector_params)

                # Show detections
                if args.debug:
                    image_copy = warped_image.copy()
                    if indices is not None:
                        cv2.aruco.drawDetectedMarkers(image_copy, corners,
                                                      indices)
                    image_copy = cv2.resize(image_copy,
                                            (int(image_copy.shape[1] / 2),
                                             int(image_copy.shape[0] / 2)))
                    cv2.imshow(board_name, image_copy)

                if indices is None:
                    continue

                # Compute poses
                board_data = {}
                for marker_index, corner in zip(indices, corners):
                    marker_index = marker_index.item()
                    marker_corners = corner.squeeze(0)
                    marker_center = marker_corners.mean(axis=0)

                    # Compute heading estimates for each of the four marker corners
                    diffs = [c - marker_center for c in marker_corners]
                    angles = np.array(
                        [np.arctan2(-diff[1], diff[0]) for diff in diffs])
                    angles = angles + np.radians([-135, -45, 45, 135])
                    angles = np.mod(angles + np.pi, 2 * np.pi) - np.pi

                    # If multiple markers are detected on same cube, use the marker on top (which should have the lowest angle_std)
                    angle_std = angles.std()
                    if board_name == 'cubes' and marker_index in board_data and angle_std > board_data[
                            marker_index]['angle_std']:
                        continue

                    # Compute position and heading
                    position = [
                        (marker_center[0] / marker_params['pixels_per_mm'] -
                         room_length_mm / 2) / 1000,
                        (room_width_mm / 2 -
                         (marker_center[1] / marker_params['pixels_per_mm'])) /
                        1000
                    ]
                    heading = angles.mean()
                    marker_data = {'position': position, 'heading': heading}
                    if board_name == 'cubes':
                        marker_data['angle_std'] = angle_std
                    board_data[marker_index] = marker_data
                data[board_name] = board_data

        return data

    while True:
        if cv2.waitKey(1) == 27:  # Esc key
            break

        if conn is None:
            print('Waiting for connection...')
            conn = listener.accept()
            print('Connected!')

        _, image = cap.read()
        if image is None:
            continue

        data = process_image(image)
        try:
            conn.send(data)
        except:
            conn = None

    cap.release()
    cv2.destroyAllWindows()
def main(args):
    # Set up webcam
    image_width = args.image_width
    image_height = args.image_height
    cap = utils.get_video_cap(args.serial, image_width, image_height)

    # Set up aruco dict and board
    aruco_dict = cv2.aruco.Dictionary_get(utils.get_marker_dict_id())
    board_params = utils.get_charuco_board_params()
    board = cv2.aruco.CharucoBoard_create(board_params['squares_x'],
                                          board_params['squares_y'],
                                          board_params['square_length'],
                                          board_params['marker_length'],
                                          aruco_dict)

    # Enable corner refinement
    detector_params = cv2.aruco.DetectorParameters_create()
    detector_params.cornerRefinementMethod = cv2.aruco.CORNER_REFINE_SUBPIX

    # Capture images
    all_corners = []
    all_ids = []
    all_imgs = []
    while True:
        _, image = cap.read()
        if image is None:
            continue

        # Detect markers
        corners, ids, rejected = cv2.aruco.detectMarkers(
            image, aruco_dict, parameters=detector_params)

        # Refine markers
        corners, ids, _, _ = cv2.aruco.refineDetectedMarkers(
            image, board, corners, ids, rejected)

        # Interpolate corners
        if ids is not None:
            _, curr_charuco_corners, curr_charuco_ids = cv2.aruco.interpolateCornersCharuco(
                corners, ids, image, board)

        # Draw results
        image_copy = image.copy()
        if ids is not None:
            cv2.aruco.drawDetectedMarkers(image_copy, corners)

            if curr_charuco_corners is not None:
                cv2.aruco.drawDetectedCornersCharuco(image_copy,
                                                     curr_charuco_corners,
                                                     curr_charuco_ids)

        # Display and wait for keyboard input
        cv2.putText(
            image_copy,
            "Press 'c' to add current frame. 'ESC' to finish and calibrate",
            (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
        cv2.imshow('out', image_copy)
        key = cv2.waitKey(10) & 0xFF
        if key == 27:
            break
        if key == ord('c') and ids is not None and len(ids) > 4:
            print('Frame captured')
            all_corners.append(corners)
            all_ids.append(ids)
            all_imgs.append(image)

    cap.release()
    cv2.destroyAllWindows()

    if len(all_imgs) < 1:
        print('Not enough captures for calibration')
        sys.exit()

    # Aruco calibration
    all_corners_concatenated = []
    all_ids_concatenated = []
    marker_counter_per_frame = []
    for corners, ids in zip(all_corners, all_ids):
        marker_counter_per_frame.append(len(corners))
        all_corners_concatenated.extend(corners)
        all_ids_concatenated.extend(ids)
    all_corners_concatenated = np.asarray(all_corners_concatenated)
    all_ids_concatenated = np.asarray(all_ids_concatenated)
    marker_counter_per_frame = np.asarray(marker_counter_per_frame)
    rep_error_aruco, camera_matrix, dist_coeffs, _, _ = cv2.aruco.calibrateCameraAruco(
        all_corners_concatenated, all_ids_concatenated,
        marker_counter_per_frame, board, (image_width, image_height), None,
        None)

    # Charuco calibration using previous camera params
    all_charuco_corners = []
    all_charuco_ids = []
    for corners, ids, image in zip(all_corners, all_ids, all_imgs):
        _, curr_charuco_corners, curr_charuco_ids = cv2.aruco.interpolateCornersCharuco(
            corners,
            ids,
            image,
            board,
            cameraMatrix=camera_matrix,
            distCoeffs=dist_coeffs)
        all_charuco_corners.append(curr_charuco_corners)
        all_charuco_ids.append(curr_charuco_ids)
    if len(all_charuco_corners) < 4:
        print('Not enough corners for calibration')
        sys.exit()
    rep_error, camera_matrix, dist_coeffs, _, _ = cv2.aruco.calibrateCameraCharuco(
        all_charuco_corners, all_charuco_ids, board,
        (image_width, image_height), camera_matrix, dist_coeffs)

    print('Rep Error:', rep_error)
    print('Rep Error Aruco:', rep_error_aruco)

    # Save camera params
    camera_params_file_path = Path('camera_params') / '{}.yml'.format(
        args.serial)
    camera_params_dir = camera_params_file_path.parent
    if not camera_params_dir.exists():
        camera_params_dir.mkdir()
    fs = cv2.FileStorage(str(camera_params_file_path), cv2.FILE_STORAGE_WRITE)
    fs.write('image_width', image_width)
    fs.write('image_height', image_height)
    fs.write('camera_matrix', camera_matrix)
    fs.write('distortion_coefficients', dist_coeffs)
    fs.write('avg_reprojection_error', rep_error)
    fs.release()
    print('Calibration saved to ', camera_params_file_path)

    # Show interpolated charuco corners
    for image, ids, charuco_corners, charuco_ids in zip(
            all_imgs, all_ids, all_charuco_corners, all_charuco_ids):
        image_copy = image.copy()
        if ids is not None:
            cv2.aruco.drawDetectedCornersCharuco(image_copy, charuco_corners,
                                                 charuco_ids)
        cv2.imshow('out', image_copy)
        key = cv2.waitKey(0)
        if key == 27:  # Esc key
            break