Merge branch 'op_control' of http://zendioninc.com.br:3000/Zendion/agrobot_base into op_control

This commit is contained in:
Diego Freitas 2026-05-29 14:10:55 -03:00
commit 441d5f5d01
1 changed files with 138 additions and 18 deletions

View File

@ -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 = []