ajustado homografia através de charuco
This commit is contained in:
parent
b4397d0954
commit
66046cffd1
|
|
@ -242,7 +242,25 @@ def save_offsets_json(path, data):
|
|||
|
||||
def require_aruco():
|
||||
if not hasattr(cv2, "aruco"):
|
||||
raise RuntimeError("cv2.aruco não disponível. Instale opencv-contrib-python no ambiente.")
|
||||
raise RuntimeError(
|
||||
"cv2.aruco não disponível. Instale opencv-contrib-python no ambiente."
|
||||
)
|
||||
|
||||
has_detector = hasattr(cv2.aruco, "ArucoDetector") or hasattr(cv2.aruco, "detectMarkers")
|
||||
has_charuco = hasattr(cv2.aruco, "CharucoBoard") or hasattr(cv2.aruco, "CharucoBoard_create")
|
||||
|
||||
if not has_detector:
|
||||
raise RuntimeError(
|
||||
"cv2.aruco existe, mas não tem ArucoDetector nem detectMarkers. "
|
||||
"Provável instalação incompleta/incompatível do OpenCV. "
|
||||
"Use opencv-contrib-python."
|
||||
)
|
||||
|
||||
if not has_charuco:
|
||||
raise RuntimeError(
|
||||
"cv2.aruco existe, mas não tem suporte ChArUco. "
|
||||
"Use opencv-contrib-python."
|
||||
)
|
||||
|
||||
|
||||
def get_aruco_dictionary(dict_name: str):
|
||||
|
|
@ -319,6 +337,99 @@ def to_gray_u8_for_charuco(img01, equalize=True, invert=False):
|
|||
return gray
|
||||
|
||||
|
||||
def detect_aruco_markers_compat(gray, dictionary, detector_params):
|
||||
if hasattr(cv2.aruco, "ArucoDetector"):
|
||||
detector = cv2.aruco.ArucoDetector(dictionary, detector_params)
|
||||
return detector.detectMarkers(gray)
|
||||
|
||||
if hasattr(cv2.aruco, "detectMarkers"):
|
||||
return cv2.aruco.detectMarkers(
|
||||
gray,
|
||||
dictionary,
|
||||
parameters=detector_params,
|
||||
)
|
||||
|
||||
raise RuntimeError(
|
||||
"Nenhuma API compatível para detectar ArUco foi encontrada. "
|
||||
"Instale opencv-contrib-python no ambiente atual."
|
||||
)
|
||||
|
||||
|
||||
def refine_detected_markers_compat(gray, board, dictionary, detector_params, corners, ids, rejected):
|
||||
if ids is None or len(ids) == 0:
|
||||
return corners, ids, rejected
|
||||
|
||||
try:
|
||||
if hasattr(cv2.aruco, "ArucoDetector"):
|
||||
detector = cv2.aruco.ArucoDetector(dictionary, detector_params)
|
||||
|
||||
result = detector.refineDetectedMarkers(
|
||||
image=gray,
|
||||
board=board,
|
||||
detectedCorners=corners,
|
||||
detectedIds=ids,
|
||||
rejectedCorners=rejected,
|
||||
)
|
||||
|
||||
if isinstance(result, tuple) and len(result) >= 3:
|
||||
return result[0], result[1], result[2]
|
||||
|
||||
return corners, ids, rejected
|
||||
|
||||
if hasattr(cv2.aruco, "refineDetectedMarkers"):
|
||||
result = cv2.aruco.refineDetectedMarkers(
|
||||
gray,
|
||||
board,
|
||||
corners,
|
||||
ids,
|
||||
rejected,
|
||||
)
|
||||
|
||||
if isinstance(result, tuple) and len(result) >= 3:
|
||||
return result[0], result[1], result[2]
|
||||
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return corners, ids, rejected
|
||||
|
||||
|
||||
def interpolate_charuco_compat(gray, board, corners, ids):
|
||||
if ids is None or len(ids) == 0:
|
||||
return 0, None, None
|
||||
|
||||
if hasattr(cv2.aruco, "interpolateCornersCharuco"):
|
||||
return cv2.aruco.interpolateCornersCharuco(
|
||||
markerCorners=corners,
|
||||
markerIds=ids,
|
||||
image=gray,
|
||||
board=board,
|
||||
)
|
||||
|
||||
if hasattr(cv2.aruco, "CharucoDetector"):
|
||||
detector = cv2.aruco.CharucoDetector(board)
|
||||
|
||||
try:
|
||||
result = detector.detectBoard(
|
||||
image=gray,
|
||||
markerCorners=corners,
|
||||
markerIds=ids,
|
||||
)
|
||||
except TypeError:
|
||||
result = detector.detectBoard(gray, corners, ids)
|
||||
|
||||
if isinstance(result, tuple) and len(result) >= 2:
|
||||
charuco_corners = result[0]
|
||||
charuco_ids = result[1]
|
||||
ret = 0 if charuco_ids is None else len(charuco_ids)
|
||||
return ret, charuco_corners, charuco_ids
|
||||
|
||||
raise RuntimeError(
|
||||
"Nenhuma API compatível para interpolar ChArUco foi encontrada. "
|
||||
"Verifique se o ambiente usa opencv-contrib-python."
|
||||
)
|
||||
|
||||
|
||||
def detect_charuco_points(
|
||||
img01,
|
||||
board,
|
||||
|
|
@ -332,27 +443,36 @@ def detect_charuco_points(
|
|||
Retorna dict: charuco_id -> (x, y), além de resumo de detecção.
|
||||
Compatível com APIs nova/legada do OpenCV.
|
||||
"""
|
||||
|
||||
gray = to_gray_u8_for_charuco(img01, equalize=equalize, invert=invert)
|
||||
if gray is None:
|
||||
return {}, {"markers": 0, "corners": 0, "ok": False}
|
||||
|
||||
# API nova pode ter ArucoDetector, mas detectMarkers continua existindo em quase todos.
|
||||
corners, ids, rejected = cv2.aruco.detectMarkers(gray, dictionary, parameters=detector_params)
|
||||
corners, ids, rejected = detect_aruco_markers_compat(
|
||||
gray,
|
||||
dictionary,
|
||||
detector_params,
|
||||
)
|
||||
|
||||
n_markers = 0 if ids is None else int(len(ids))
|
||||
if ids is None or n_markers < min_markers:
|
||||
return {}, {"markers": n_markers, "corners": 0, "ok": False}
|
||||
|
||||
try:
|
||||
cv2.aruco.refineDetectedMarkers(gray, board, corners, ids, rejected)
|
||||
except Exception:
|
||||
pass
|
||||
corners, ids, rejected = refine_detected_markers_compat(
|
||||
gray,
|
||||
board,
|
||||
dictionary,
|
||||
detector_params,
|
||||
corners,
|
||||
ids,
|
||||
rejected,
|
||||
)
|
||||
|
||||
ret, charuco_corners, charuco_ids = cv2.aruco.interpolateCornersCharuco(
|
||||
markerCorners=corners,
|
||||
markerIds=ids,
|
||||
image=gray,
|
||||
board=board,
|
||||
ret, charuco_corners, charuco_ids = interpolate_charuco_compat(
|
||||
gray,
|
||||
board,
|
||||
corners,
|
||||
ids,
|
||||
)
|
||||
|
||||
if charuco_corners is None or charuco_ids is None:
|
||||
|
|
@ -467,11 +587,11 @@ def main():
|
|||
|
||||
# ChArUco automático
|
||||
parser.add_argument("--charuco_auto", action="store_true", help="Inicia direto no modo de homografia automática por ChArUco.")
|
||||
parser.add_argument("--charuco_dictionary", default="DICT_5X5_100")
|
||||
parser.add_argument("--charuco_squares_x", type=int, default=7)
|
||||
parser.add_argument("--charuco_squares_y", type=int, default=5)
|
||||
parser.add_argument("--charuco_square_length", type=float, default=1.0)
|
||||
parser.add_argument("--charuco_marker_length", type=float, default=0.70)
|
||||
parser.add_argument("--charuco_dictionary", default="DICT_4X4_50")
|
||||
parser.add_argument("--charuco_squares_x", type=int, default=13)
|
||||
parser.add_argument("--charuco_squares_y", type=int, default=7)
|
||||
parser.add_argument("--charuco_square_length", type=float, default=0.031)
|
||||
parser.add_argument("--charuco_marker_length", type=float, default=0.023)
|
||||
parser.add_argument("--charuco_min_markers", type=int, default=4)
|
||||
parser.add_argument("--charuco_min_common_corners", type=int, default=8)
|
||||
parser.add_argument("--charuco_ransac_px", type=float, default=3.0)
|
||||
|
|
@ -684,7 +804,7 @@ def main():
|
|||
charuco_last["summary"] = {"rgb": rgb_sum, "re": re_sum, "nir": nir_sum}
|
||||
|
||||
if not rgb_pts:
|
||||
return False, "ChArUco: RGB não detectou cantos válidos"
|
||||
return False, "ChArUco: RGB nao detectou cantos validos"
|
||||
|
||||
charuco_sample_id += 1
|
||||
messages = []
|
||||
|
|
|
|||
Loading…
Reference in New Issue