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 == []
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
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_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
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))
def test_process_frame(benchmark: Callable, marker_camera: MarkerCamera) -> None: frame = marker_camera.capture_frame() benchmark(lambda: list(marker_camera.process_frame(frame=frame)))
def marker(marker_camera: BaseMarkerCamera) -> ndarray: return next(marker_camera.process_frame())
class MarkerTestCase(TestCase): MARKER_SIZE = 200 MARKER_ID = 25 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_marker_size(self): self.assertEqual(self.marker.size, self.MARKER_SIZE) def test_marker_id(self): self.assertEqual(self.marker.id, self.MARKER_ID) def test_pixel_corners(self): 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.to_list(), [border_size, border_size]) self.assertEqual(tr.to_list(), [self.MARKER_SIZE + border_size - 1, border_size]) self.assertEqual( br.to_list(), [ self.MARKER_SIZE + border_size - 1, self.MARKER_SIZE + border_size - 1 ], ) self.assertEqual(bl.to_list(), [border_size, self.MARKER_SIZE + border_size - 1]) def test_pixel_centre(self): tl, _, br, _ = self.marker.pixel_corners self.assertEqual(self.marker.pixel_centre.to_list(), [139, 139]) def test_distance(self): self.assertEqual(self.marker.distance, 992) def test_orientation(self): rot_x, rot_y, rot_z = self.marker.orientation self.assertEqual(int(rot_x), 3) self.assertEqual(int(rot_y), 0) self.assertEqual(int(rot_z), 0) def test_cartesian_coordinates(self): x, y, z = self.marker.cartesian.values() self.assertEqual(int(x), 49) self.assertEqual(int(y), 24) self.assertEqual(int(z), 991) def test_spherical_coordinates(self): rot_x, rot_y, dist = self.marker.spherical self.assertEqual(dist, self.marker.distance) self.assertEqual(rot_x, approx(0.025, abs=1e-3)) self.assertEqual(rot_y, approx(0.05, abs=1e-3)) def test_as_dict(self): marker_dict = self.marker.as_dict() self.assertIsInstance(marker_dict, dict) self.assertEqual({"id", "size", "pixel_corners", "rvec", "tvec"}, set(marker_dict.keys())) self.assertEqual(marker_dict["size"], self.MARKER_SIZE) self.assertEqual(marker_dict["id"], self.MARKER_ID) def test_dict_as_json(self): marker_dict = self.marker.as_dict() created_marker_dict = json.loads(json.dumps(marker_dict)) self.assertEqual(marker_dict, created_marker_dict) def test_many_as_ujson(self): created_markers_dict = ujson.loads(ujson.dumps(self.markers)) self.assertEqual(len(created_markers_dict), 1) self.assertEqual({marker["id"] for marker in created_markers_dict}, {self.MARKER_ID}) def test_dict_as_ujson(self): marker_dict = self.marker.as_dict() created_marker_dict = ujson.loads(ujson.dumps(marker_dict)) self.assertEqual(marker_dict["id"], created_marker_dict["id"]) self.assertEqual(marker_dict["size"], created_marker_dict["size"]) for expected_corner, corner in zip( marker_dict["pixel_corners"], created_marker_dict["pixel_corners"]): self.assertEqual(expected_corner, approx(corner)) self.assertEqual(marker_dict["rvec"], approx(created_marker_dict["rvec"])) self.assertEqual(marker_dict["tvec"], approx(created_marker_dict["tvec"]))
def marker(marker_camera: MarkerCamera) -> BaseMarker: return next(marker_camera.process_frame())