def test_requires_in_range_marker_id(marker_type: MarkerType) -> None:
    MarkerCamera(marker_type.max_id, marker_size=200, marker_type=marker_type)

    with pytest.raises(ValueError) as e:
        MarkerCamera(marker_type.max_id + 1, marker_size=200, marker_type=marker_type)

    assert "must be less than the maximum allowed" in e.value.args[0]
def test_sees_nothing_in_blank_image():
    marker_camera = MarkerCamera(25,
                                 marker_dict=MarkerDict.DICT_6X6_50,
                                 marker_size=200)
    empty_frame = numpy.zeros((200, 200, 3), numpy.uint8)
    markers = list(marker_camera.process_frame(frame=empty_frame))
    assert markers == []
def test_process_eager_frame_without_calibrations(marker_type: MarkerType) -> None:
    marker_camera = MarkerCamera(
        MAX_ALL_ALLOWED_ID, marker_size=200, marker_type=marker_type
    )
    marker_camera.calibration_params = None
    with pytest.raises(MissingCalibrationsError):
        list(marker_camera.process_frame_eager())
Beispiel #4
0
def is_valid_calibration(filename: Path) -> bool:
    if not filename.is_file():
        return False

    # First, Try and parse the file
    try:
        parse_calibration_file(filename)
    except (SystemError, ValueError):
        return False

    with tempfile.NamedTemporaryFile(suffix=".png") as temp_file:
        marker_camera = MarkerCamera(0,
                                     200,
                                     marker_type=MarkerType.APRILTAG_36H11)
        marker_camera.save_frame(Path(temp_file.name))

        image_camera = ImageFileCamera(
            Path(temp_file.name),
            marker_size=200,
            marker_type=MarkerType.APRILTAG_36H11,
            calibration_file=filename,
        )

        # Sanity check the image camera
        if image_camera.get_visible_markers() != [0]:
            return False

        # Then, confirm the detection works
        if len(list(marker_camera.process_frame_eager())) != 1:
            return False

    return True
def test_marker_type_max_id_disallowed(marker_type: MarkerType) -> None:
    camera = MarkerCamera(marker_type.max_id,
                          marker_size=100,
                          marker_type=marker_type)
    camera.marker_id = marker_type.max_id + 1  # There's an assertion in the constructor
    with pytest.raises(cv2.error):
        camera.get_visible_markers()
Beispiel #6
0
 def setUp(self):
     self.marker_camera = MarkerCamera(
         self.MARKER_ID,
         marker_dict=MarkerDict.DICT_6X6_50,
         marker_size=self.MARKER_SIZE,
     )
     self.markers = list(self.marker_camera.process_frame())
     self.marker = self.markers[0]
def test_saved_image(temp_image_file, marker_id):
    marker_camera = MarkerCamera(marker_id,
                                 marker_dict=MarkerDict.DICT_6X6_50,
                                 marker_size=200)
    marker_camera.save_frame(temp_image_file)
    image_file_camera = ImageFileCamera(temp_image_file,
                                        marker_dict=MarkerDict.DICT_6X6_50)
    assert image_file_camera.get_visible_markers() == [marker_id]
Beispiel #8
0
 def setUp(self) -> None:
     self.marker_camera = MarkerCamera(
         self.MARKER_ID,
         marker_size=self.MARKER_SIZE,
         marker_type=MarkerType.ARUCO_6X6,
     )
     self.markers = list(self.marker_camera.process_frame_eager())
     self.marker = self.markers[0]
Beispiel #9
0
 def setUp(self) -> None:
     self.marker_camera = MarkerCamera(
         self.MARKER_ID,
         marker_size=self.MARKER_SIZE,
         marker_type=MarkerType.ARUCO_6X6,
     )
     self.marker_camera.calibration_params = None
     self.markers = list(self.marker_camera.process_frame())
     self.marker = self.markers[0]
def test_saved_image(
    marker_type: MarkerType, temp_image_file: Path, marker_id: int
) -> None:
    marker_camera = MarkerCamera(marker_id, marker_size=200, marker_type=marker_type)
    marker_camera.save_frame(temp_image_file)
    image_file_camera = ImageFileCamera(
        temp_image_file, marker_type=marker_type, marker_size=200
    )
    assert image_file_camera.get_visible_markers() == [marker_id]
def test_detect_at_minimum_size(marker_type: MarkerType) -> None:
    marker_camera = MarkerCamera(
        0,
        marker_size=marker_type.min_marker_image_size,
        marker_type=marker_type,
        border_size=MarkerCamera.MIN_BORDER_SIZE,
    )
    frame = marker_camera.capture_frame()
    assert frame.shape == marker_camera.get_resolution()

    marker = next(marker_camera.process_frame(frame=frame))
    assert marker.id == 0
def test_marker_size(
    marker_type: MarkerType, temp_image_file: Path, marker_id: int
) -> None:
    class TestCamera(ImageFileCamera):
        def get_marker_size(self, inner_marker_id: int) -> int:
            return inner_marker_id * 10

    marker_camera = MarkerCamera(marker_id, marker_size=200, marker_type=marker_type)
    marker_camera.save_frame(temp_image_file)
    image_file_camera = TestCamera(temp_image_file, marker_type=marker_type)
    marker = next(image_file_camera.process_frame())
    assert marker.size == marker_id * 10
    assert marker.id == marker_id
def test_no_markers(temp_image_file: Path) -> None:
    marker_camera = MarkerCamera(
        MAX_ALL_ALLOWED_ID,
        marker_size=100,
        marker_type=MarkerType.ARUCO_4X4,
    )
    marker_camera.save_frame(temp_image_file)

    image_file_camera = ImageFileCamera(
        temp_image_file, marker_type=MarkerType.ARUCO_5X5, marker_size=100
    )

    assert marker_camera.marker_type != image_file_camera.marker_type
    assert image_file_camera.get_visible_markers() == []
Beispiel #14
0
def test_detects_markers(marker_id):
    markers = list(
        MarkerCamera(marker_id,
                     marker_dict=MarkerDict.DICT_6X6_50,
                     marker_size=200).process_frame())
    assert len(markers) == 1
    assert markers[0].id == marker_id
def test_minimum_marker_size(marker_type: MarkerType) -> None:
    camera = MarkerCamera(
        marker_type.max_id,
        marker_size=marker_type.min_marker_image_size,
        marker_type=marker_type,
    )

    assert camera.get_visible_markers() == [marker_type.max_id]

    with pytest.raises(ValueError) as e:
        MarkerCamera(
            marker_type.max_id,
            marker_size=marker_type.min_marker_image_size - 1,
            marker_type=marker_type,
        )
    assert "marker must be at least" in e.value.args[0]
Beispiel #16
0
class UncalibratedMarkerTestCase(MarkerTestCase):
    EXPECTED_DICT_KEYS = {"id", "size", "pixel_corners"}

    def setUp(self) -> None:
        self.marker_camera = MarkerCamera(
            self.MARKER_ID,
            marker_size=self.MARKER_SIZE,
            marker_type=MarkerType.ARUCO_6X6,
        )
        self.marker_camera.calibration_params = None
        self.markers = list(self.marker_camera.process_frame())
        self.marker = self.markers[0]

    def test_is_uncalibrated(self) -> None:
        self.assertIsInstance(self.marker, UncalibratedMarker)
        with self.assertRaises(MissingCalibrationsError):
            self.marker._get_pose_vectors()

    def __getattribute__(self, name: str) -> Any:
        attr = super().__getattribute__(name)
        if name in [
                "test_orientation",
                "test_distance",
                "test_cartesian_coordinates",
                "test_spherical_coordinates",
        ]:

            def test_raises(*args: Any, **kwargs: Any) -> None:
                with self.assertRaises(MissingCalibrationsError):
                    attr(*args, **kwargs)

            return test_raises
        return attr
def test_detects_markers(marker_type: MarkerType, marker_id: int) -> None:
    markers = list(
        MarkerCamera(
            marker_id, marker_size=100, marker_type=marker_type
        ).process_frame()
    )
    assert len(markers) == 1
    assert markers[0].id == marker_id
Beispiel #18
0
def test_eager_capture(marker_id):
    markers = list(
        MarkerCamera(marker_id,
                     marker_dict=MarkerDict.DICT_6X6_50,
                     marker_size=200).process_frame_eager())
    assert len(markers) == 1
    assert markers[0].id == marker_id
    assert markers[0]._is_eager()
Beispiel #19
0
class MarkerFromDictTestCase(EagerMarkerTestCase):
    def setUp(self):
        self.marker_camera = MarkerCamera(
            self.MARKER_ID,
            marker_dict=MarkerDict.DICT_6X6_50,
            marker_size=self.MARKER_SIZE,
        )
        self.markers = list(self.marker_camera.process_frame())
        self.marker = Marker.from_dict(self.markers[0].as_dict())
def test_eager_capture(marker_type: MarkerType, marker_id: int) -> None:
    markers = list(
        MarkerCamera(
            marker_id, marker_size=200, marker_type=marker_type
        ).process_frame_eager()
    )
    assert len(markers) == 1
    assert markers[0].id == marker_id
    assert isinstance(markers[0], EagerMarker)
Beispiel #21
0
class EagerMarkerTestCase(MarkerTestCase):
    def setUp(self):
        self.marker_camera = MarkerCamera(
            self.MARKER_ID,
            marker_dict=MarkerDict.DICT_6X6_50,
            marker_size=self.MARKER_SIZE,
        )
        self.markers = list(self.marker_camera.process_frame_eager())
        self.marker = self.markers[0]

    def test_is_eager(self):
        self.assertTrue(self.marker._is_eager())

    @patch("cv2.aruco.estimatePoseSingleMarkers")
    def test_doesnt_calculate_pose(self, pose_mock):
        assert self.marker._tvec is not None
        assert self.marker._rvec is not None
        pose_mock.assert_not_called()
Beispiel #22
0
class EagerMarkerTestCase(MarkerTestCase):
    def setUp(self) -> None:
        self.marker_camera = MarkerCamera(
            self.MARKER_ID,
            marker_size=self.MARKER_SIZE,
            marker_type=MarkerType.ARUCO_6X6,
        )
        self.markers = list(self.marker_camera.process_frame_eager())
        self.marker = self.markers[0]

    @patch("cv2.aruco.estimatePoseSingleMarkers")
    def test_doesnt_calculate_pose(self, pose_mock: Any) -> None:
        assert self.marker._tvec is not None
        assert self.marker._rvec is not None
        pose_mock.assert_not_called()

    def test_is_eager(self) -> None:
        self.assertIsInstance(self.marker, EagerMarker)
Beispiel #23
0
def main(args: argparse.Namespace) -> None:
    from PIL import Image, ImageDraw

    marker_type = MarkerType[args.type]
    output_dir: Path = args.path.resolve()
    output_dir.mkdir(exist_ok=True, parents=True)

    marker_ids = (parse_ranges(args.range)
                  if args.range != "ALL" else marker_type.marker_ids)

    for marker_id in sorted(marker_ids):
        with MarkerCamera(
                marker_id,
                marker_type=marker_type,
                marker_size=marker_type.min_marker_image_size,
        ) as camera:
            camera.border_size = 1  # HACK: There's validation in the constructor
            print("Saving", marker_id)  # noqa:T001

            if args.raw:
                camera.save_frame(output_dir / "{}.png".format(marker_id))
            else:
                image = Image.fromarray(camera.capture_frame())

                # Resize the image to the required size
                resized_image = image.resize((500, 500), resample=0)

                img_size = resized_image.size[0]

                ImageDraw.Draw(resized_image).text(
                    (25, img_size - 25),
                    args.description_format.format(
                        marker_type=marker_type.name, marker_id=marker_id),
                    anchor="lt",
                )
                resized_image.save(output_dir / "{}.png".format(marker_id))
Beispiel #24
0
def test_camera_as_context_manager():
    with MarkerCamera(25, marker_dict=MarkerDict.DICT_6X6_50,
                      marker_size=200) as marker_camera:
        markers = list(marker_camera.get_visible_markers())
        assert markers == [25]
Beispiel #25
0
class MarkerTestCase(TestCase):
    MARKER_SIZE = 200
    MARKER_ID = MAX_ALL_ALLOWED_ID
    EXPECTED_DICT_KEYS = {"id", "size", "pixel_corners", "rvec", "tvec"}

    def setUp(self) -> None:
        self.marker_camera = MarkerCamera(
            self.MARKER_ID,
            marker_size=self.MARKER_SIZE,
            marker_type=MarkerType.ARUCO_6X6,
        )
        self.markers = list(
            self.marker_camera.process_frame())  # type: List[BaseMarker]
        self.marker = self.markers[0]

    def assertIsType(self, a: Any, b: Any) -> None:
        self.assertEqual(type(a), b)

    def test_marker_size(self) -> None:
        self.assertEqual(self.marker.size, self.MARKER_SIZE)

    def test_marker_id(self) -> None:
        self.assertEqual(self.marker.id, self.MARKER_ID)

    def test_marker_type(self) -> None:
        self.assertEqual(self.marker.marker_type, MarkerType.ARUCO_6X6)

    def test_pixel_corners(self) -> None:
        self.assertEqual(len(self.marker.pixel_corners), 4)
        border_size = self.marker_camera.border_size
        tl, tr, br, bl = self.marker.pixel_corners
        self.assertEqual(tl, (border_size, border_size))
        self.assertEqual(tr, (self.MARKER_SIZE + border_size - 1, border_size))
        self.assertEqual(
            br,
            (self.MARKER_SIZE + border_size - 1,
             self.MARKER_SIZE + border_size - 1),
        )
        self.assertEqual(bl, (border_size, self.MARKER_SIZE + border_size - 1))

    def test_pixel_centre(self) -> None:
        tl, _, br, _ = self.marker.pixel_corners
        self.assertEqual(self.marker.pixel_centre, (139, 139))

    def test_distance(self) -> None:
        self.assertAlmostEqual(self.marker.distance, 900,
                               delta=100)  # HACK: Sometimes it changes

    def test_orientation(self) -> None:
        rot_x, rot_y, rot_z = self.marker.orientation
        self.assertIn(int(rot_x), [3, -3])  # HACK: Sometimes it changes
        self.assertEqual(int(rot_y), 0)
        self.assertEqual(int(rot_z), 0)

    def test_cartesian_coordinates(self) -> None:
        x, y, z = self.marker.cartesian
        self.assertAlmostEqual(int(x), 52,
                               delta=10)  # HACK: Sometimes it changes
        self.assertAlmostEqual(int(y), 15,
                               delta=20)  # HACK: Sometimes it changes
        self.assertAlmostEqual(int(z), 910,
                               delta=100)  # HACK: Sometimes it changes

    def test_spherical_coordinates(self) -> None:
        rot_x, rot_y, dist = self.marker.spherical
        self.assertEqual(dist, self.marker.distance)
        self.assertAlmostEqual(rot_x, 0, delta=0.1)
        self.assertAlmostEqual(rot_y, 0, delta=0.1)

    def test_as_dict(self) -> None:
        marker_dict = self.marker.as_dict()
        self.assertIsInstance(marker_dict, dict)
        self.assertEqual(self.EXPECTED_DICT_KEYS, set(marker_dict.keys()))
        self.assertEqual(marker_dict["size"], self.MARKER_SIZE)
        self.assertEqual(marker_dict["id"], self.MARKER_ID)

    def test_as_dict_json(self) -> None:
        marker_dict = self.marker.as_dict()
        created_marker_dict = json.loads(json.dumps(self.marker.as_dict()))
        self.assertEqual(marker_dict, created_marker_dict)
        self.assertEqual(self.EXPECTED_DICT_KEYS, set(marker_dict.keys()))

    def test_dict_value_types(self) -> None:
        marker_dict = self.marker.as_dict()
        self.assertIsType(marker_dict["id"], int)
        self.assertIsType(marker_dict["size"], int)

        pixel_corners = marker_dict["pixel_corners"]
        self.assertIsType(pixel_corners, list)
        self.assertIsType(pixel_corners[0], list)
        self.assertIsType(pixel_corners[0][0], float)

        if "rvec" in marker_dict:
            self.assertIsType(marker_dict["rvec"], list)
            self.assertIsType(marker_dict["rvec"][0], float)

            self.assertIsType(marker_dict["tvec"], list)
            self.assertIsType(marker_dict["tvec"][0], float)

    def test_marker_types(self) -> None:
        self.assertIsType(self.marker.id, int)
        self.assertIsType(self.marker.size, int)
        self.assertIsType(self.marker.pixel_corners[0].x, float)
        self.assertIsType(self.marker.pixel_corners[0].y, float)
        self.assertIsType(self.marker.pixel_centre.x, float)
        self.assertIsType(self.marker.pixel_centre.y, float)

        if "rvec" in self.EXPECTED_DICT_KEYS:
            self.assertIsType(self.marker.distance, int)

            self.assertIsType(self.marker.spherical.rot_x, float)
            self.assertIsType(self.marker.spherical.rot_y, float)
            self.assertIsType(self.marker.spherical.dist, int)

            self.assertIsType(self.marker.cartesian.x, float)
            self.assertIsType(self.marker.cartesian.y, float)
            self.assertIsType(self.marker.cartesian.z, float)

    def test_repr(self) -> None:
        self.assertIn(str(self.MARKER_ID), repr(self.marker))
        self.assertIn(str(self.MARKER_SIZE), repr(self.marker))
        self.assertIn("ARUCO_6X6", repr(self.marker))

        # Eager markers also show their distance
        if isinstance(self.marker, EagerMarker):
            self.assertIn(str(self.marker.distance), repr(self.marker))
Beispiel #26
0
def test_process_frame_eager(benchmark: Callable,
                             marker_camera: MarkerCamera) -> None:
    frame = marker_camera.capture_frame()
    benchmark(lambda: list(marker_camera.process_frame_eager(frame=frame)))
Beispiel #27
0
def test_get_visible_markers(benchmark: Callable,
                             marker_camera: MarkerCamera) -> None:
    frame = marker_camera.capture_frame()
    benchmark(marker_camera.get_visible_markers, frame=frame)
Beispiel #28
0
def test_saved_image_with_annotation(temp_image_file, marker_id):
    marker_camera = MarkerCamera(marker_id,
                                 marker_dict=MarkerDict.DICT_6X6_50,
                                 marker_size=200)
    output_file = temp_image_file
    marker_camera.save_frame(output_file, annotate=True)
Beispiel #29
0
def test_marker_with_falsy_id():
    with MarkerCamera(0, marker_dict=MarkerDict.DICT_6X6_50,
                      marker_size=200) as marker_camera:
        markers = list(marker_camera.get_visible_markers())
        assert markers == [0]
Beispiel #30
0
def test_detects_marker_ids(marker_id):
    markers = MarkerCamera(marker_id,
                           marker_dict=MarkerDict.DICT_6X6_50,
                           marker_size=200).get_visible_markers()
    assert markers == [marker_id]