Skip to content

Commit 5bda6a9

Browse files
did
1 parent 73f4910 commit 5bda6a9

File tree

10 files changed

+151
-101
lines changed

10 files changed

+151
-101
lines changed

.github/workflows/tests.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,15 @@ jobs:
2020
- name: Install dependencies
2121
run: |
2222
python -m pip install --upgrade pip
23-
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
23+
if [ -f vision/requirements.txt ]; then pip install -r vision/requirements.txt; fi
24+
python -m pip install pyright
2425
2526
- name: Run unit tests
2627
working-directory: ./vision
2728
run: |
2829
python run_tests.py
30+
31+
- name: Run type checks
32+
working-directory: ./vision
33+
run: |
34+
python -m pyright .

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@ numpy>=1.23
77
robotpy
88
trimesh[easy]
99
rtree
10-
opencv-python
10+
opencv-python
11+
pyright

vision/lib/calibration_board_pdf.py

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import argparse
44
import zlib
55
from pathlib import Path
6+
from typing import Any, cast
67

78
import cv2
89
import numpy as np
@@ -35,31 +36,34 @@ def _orient(page_w_pt: float, page_h_pt: float, orientation: str) -> tuple[float
3536
def _dictionary_by_name(name: str):
3637
if not hasattr(cv2, "aruco"):
3738
raise RuntimeError("cv2.aruco is required for charuco")
39+
aruco = cast(Any, cv2.aruco)
3840
n = str(name).strip().upper()
39-
code = getattr(cv2.aruco, n, None)
41+
code = getattr(aruco, n, None)
4042
if code is None:
4143
raise ValueError(f"unsupported aruco dictionary: {name}")
42-
return cv2.aruco.getPredefinedDictionary(int(code))
44+
return aruco.getPredefinedDictionary(int(code))
4345

4446

4547
def _make_charuco_board(squares_x: int, squares_y: int, marker_ratio: float, dictionary):
48+
aruco = cast(Any, cv2.aruco)
4649
mr = float(marker_ratio)
4750
if mr <= 0.0 or mr >= 1.0:
4851
raise ValueError("marker-ratio must be in (0, 1)")
49-
if hasattr(cv2.aruco, "CharucoBoard"):
50-
return cv2.aruco.CharucoBoard((int(squares_x), int(squares_y)), 1.0, mr, dictionary)
51-
return cv2.aruco.CharucoBoard_create(int(squares_x), int(squares_y), 1.0, mr, dictionary)
52+
if hasattr(aruco, "CharucoBoard"):
53+
return aruco.CharucoBoard((int(squares_x), int(squares_y)), 1.0, mr, dictionary)
54+
return aruco.CharucoBoard_create(int(squares_x), int(squares_y), 1.0, mr, dictionary)
5255

5356

5457
def _draw_charuco_image(squares_x: int, squares_y: int, cell_px: int, marker_ratio: float, dict_name: str, invert: bool) -> np.ndarray:
5558
dictionary = _dictionary_by_name(dict_name)
5659
board = _make_charuco_board(squares_x, squares_y, marker_ratio, dictionary)
60+
board_any = cast(Any, board)
5761
width = int(squares_x) * int(cell_px)
5862
height = int(squares_y) * int(cell_px)
59-
if hasattr(board, "generateImage"):
60-
img = board.generateImage((width, height), marginSize=0, borderBits=1)
63+
if hasattr(board_any, "generateImage"):
64+
img = board_any.generateImage((width, height), marginSize=0, borderBits=1)
6165
else:
62-
img = board.draw((width, height), marginSize=0, borderBits=1)
66+
img = board_any.draw((width, height), marginSize=0, borderBits=1)
6367
out = np.asarray(img, dtype=np.uint8)
6468
if out.ndim == 3:
6569
out = cv2.cvtColor(out, cv2.COLOR_BGR2GRAY)

vision/lib/calibration_capture.py

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import math
55
import time
66
from pathlib import Path
7+
from typing import Any, cast
78

89
import cv2
910
import numpy as np
@@ -29,51 +30,55 @@ def _starting_index(out_dir: Path, prefix: str, ext: str) -> int:
2930
def _dict_by_name(name: str):
3031
if not hasattr(cv2, "aruco"):
3132
raise RuntimeError("cv2.aruco is required for charuco")
32-
code = getattr(cv2.aruco, str(name).strip().upper(), None)
33+
aruco = cast(Any, cv2.aruco)
34+
code = getattr(aruco, str(name).strip().upper(), None)
3335
if code is None:
3436
raise ValueError(f"unsupported aruco dictionary: {name}")
35-
return cv2.aruco.getPredefinedDictionary(int(code))
37+
return aruco.getPredefinedDictionary(int(code))
3638

3739

3840
def _make_charuco_board(cols: int, rows: int, marker_ratio: float, dict_name: str):
41+
aruco = cast(Any, cv2.aruco)
3942
dictionary = _dict_by_name(dict_name)
4043
sx = int(cols) + 1
4144
sy = int(rows) + 1
4245
mr = float(marker_ratio)
4346
if mr <= 0.0 or mr >= 1.0:
4447
raise ValueError("marker-ratio must be in (0, 1)")
45-
if hasattr(cv2.aruco, "CharucoBoard"):
46-
board = cv2.aruco.CharucoBoard((sx, sy), 1.0, mr, dictionary)
48+
if hasattr(aruco, "CharucoBoard"):
49+
board = aruco.CharucoBoard((sx, sy), 1.0, mr, dictionary)
4750
else:
48-
board = cv2.aruco.CharucoBoard_create(sx, sy, 1.0, mr, dictionary)
51+
board = aruco.CharucoBoard_create(sx, sy, 1.0, mr, dictionary)
4952
return board, dictionary
5053

5154

5255
def _make_aruco_detector(dictionary):
56+
aruco = cast(Any, cv2.aruco)
5357
params = None
54-
if hasattr(cv2.aruco, "DetectorParameters"):
55-
params = cv2.aruco.DetectorParameters()
56-
elif hasattr(cv2.aruco, "DetectorParameters_create"):
57-
params = cv2.aruco.DetectorParameters_create()
58-
if hasattr(cv2.aruco, "ArucoDetector") and params is not None:
59-
return cv2.aruco.ArucoDetector(dictionary, params), params
58+
if hasattr(aruco, "DetectorParameters"):
59+
params = aruco.DetectorParameters()
60+
elif hasattr(aruco, "DetectorParameters_create"):
61+
params = aruco.DetectorParameters_create()
62+
if hasattr(aruco, "ArucoDetector") and params is not None:
63+
return aruco.ArucoDetector(dictionary, params), params
6064
return None, params
6165

6266

6367
def _detect_markers(gray: np.ndarray, dictionary, detector, detector_params):
68+
aruco = cast(Any, cv2.aruco)
6469
if detector is not None:
6570
return detector.detectMarkers(gray)
6671
if detector_params is None:
67-
return cv2.aruco.detectMarkers(gray, dictionary)
68-
return cv2.aruco.detectMarkers(gray, dictionary, parameters=detector_params)
72+
return aruco.detectMarkers(gray, dictionary)
73+
return aruco.detectMarkers(gray, dictionary, parameters=detector_params)
6974

7075

7176
def _detect_checkerboard(gray: np.ndarray, pattern_size: tuple[int, int]) -> tuple[bool, np.ndarray | None]:
7277
found, corners = cv2.findChessboardCornersSB(gray, pattern_size, None)
7378
if found and corners is not None:
7479
return True, corners
7580
flags = cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_NORMALIZE_IMAGE + cv2.CALIB_CB_FAST_CHECK
76-
found2, corners2 = cv2.findChessboardCorners(gray, pattern_size, flags)
81+
found2, corners2 = cv2.findChessboardCorners(gray, pattern_size, None, flags)
7782
if not found2 or corners2 is None:
7883
return False, None
7984
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 40, 0.001)
@@ -89,17 +94,18 @@ def _detect_charuco(
8994
detector_params,
9095
min_corners: int,
9196
) -> tuple[bool, np.ndarray | None, np.ndarray | None, tuple]:
97+
aruco = cast(Any, cv2.aruco)
9298
corners, ids, rejected = _detect_markers(gray, dictionary, detector, detector_params)
9399
if ids is None or len(ids) <= 0:
94100
return False, None, None, (corners, ids, rejected)
95-
if hasattr(cv2.aruco, "refineDetectedMarkers"):
101+
if hasattr(aruco, "refineDetectedMarkers"):
96102
try:
97-
refined = cv2.aruco.refineDetectedMarkers(gray, board, corners, ids, rejected)
103+
refined = aruco.refineDetectedMarkers(gray, board, corners, ids, rejected)
98104
if isinstance(refined, tuple) and len(refined) >= 3:
99105
corners, ids, rejected = refined[0], refined[1], refined[2]
100106
except Exception:
101107
pass
102-
retval, charuco_corners, charuco_ids = cv2.aruco.interpolateCornersCharuco(corners, ids, gray, board)
108+
retval, charuco_corners, charuco_ids = aruco.interpolateCornersCharuco(corners, ids, gray, board)
103109
if retval is None or float(retval) < float(min_corners) or charuco_corners is None or charuco_ids is None:
104110
return False, None, None, (corners, ids, rejected)
105111
return True, charuco_corners, charuco_ids, (corners, ids, rejected)
@@ -229,9 +235,9 @@ def main() -> None:
229235
)
230236
marker_corners, marker_ids, _ = marker_pack
231237
if marker_ids is not None and len(marker_ids) > 0:
232-
cv2.aruco.drawDetectedMarkers(vis, marker_corners, marker_ids)
238+
cast(Any, cv2.aruco).drawDetectedMarkers(vis, marker_corners, marker_ids)
233239
if found and cc is not None and ci is not None:
234-
cv2.aruco.drawDetectedCornersCharuco(vis, cc, ci, (0, 255, 0))
240+
cast(Any, cv2.aruco).drawDetectedCornersCharuco(vis, cc, ci, (0, 255, 0))
235241
points = cc
236242
else:
237243
found, corners = _detect_checkerboard(gray, pattern)

0 commit comments

Comments
 (0)