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():
|
def require_aruco():
|
||||||
if not hasattr(cv2, "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):
|
def get_aruco_dictionary(dict_name: str):
|
||||||
|
|
@ -319,6 +337,99 @@ def to_gray_u8_for_charuco(img01, equalize=True, invert=False):
|
||||||
return gray
|
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(
|
def detect_charuco_points(
|
||||||
img01,
|
img01,
|
||||||
board,
|
board,
|
||||||
|
|
@ -332,27 +443,36 @@ def detect_charuco_points(
|
||||||
Retorna dict: charuco_id -> (x, y), além de resumo de detecção.
|
Retorna dict: charuco_id -> (x, y), além de resumo de detecção.
|
||||||
Compatível com APIs nova/legada do OpenCV.
|
Compatível com APIs nova/legada do OpenCV.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
gray = to_gray_u8_for_charuco(img01, equalize=equalize, invert=invert)
|
gray = to_gray_u8_for_charuco(img01, equalize=equalize, invert=invert)
|
||||||
if gray is None:
|
if gray is None:
|
||||||
return {}, {"markers": 0, "corners": 0, "ok": False}
|
return {}, {"markers": 0, "corners": 0, "ok": False}
|
||||||
|
|
||||||
# API nova pode ter ArucoDetector, mas detectMarkers continua existindo em quase todos.
|
corners, ids, rejected = detect_aruco_markers_compat(
|
||||||
corners, ids, rejected = cv2.aruco.detectMarkers(gray, dictionary, parameters=detector_params)
|
gray,
|
||||||
|
dictionary,
|
||||||
|
detector_params,
|
||||||
|
)
|
||||||
|
|
||||||
n_markers = 0 if ids is None else int(len(ids))
|
n_markers = 0 if ids is None else int(len(ids))
|
||||||
if ids is None or n_markers < min_markers:
|
if ids is None or n_markers < min_markers:
|
||||||
return {}, {"markers": n_markers, "corners": 0, "ok": False}
|
return {}, {"markers": n_markers, "corners": 0, "ok": False}
|
||||||
|
|
||||||
try:
|
corners, ids, rejected = refine_detected_markers_compat(
|
||||||
cv2.aruco.refineDetectedMarkers(gray, board, corners, ids, rejected)
|
gray,
|
||||||
except Exception:
|
board,
|
||||||
pass
|
dictionary,
|
||||||
|
detector_params,
|
||||||
|
corners,
|
||||||
|
ids,
|
||||||
|
rejected,
|
||||||
|
)
|
||||||
|
|
||||||
ret, charuco_corners, charuco_ids = cv2.aruco.interpolateCornersCharuco(
|
ret, charuco_corners, charuco_ids = interpolate_charuco_compat(
|
||||||
markerCorners=corners,
|
gray,
|
||||||
markerIds=ids,
|
board,
|
||||||
image=gray,
|
corners,
|
||||||
board=board,
|
ids,
|
||||||
)
|
)
|
||||||
|
|
||||||
if charuco_corners is None or charuco_ids is None:
|
if charuco_corners is None or charuco_ids is None:
|
||||||
|
|
@ -467,11 +587,11 @@ def main():
|
||||||
|
|
||||||
# ChArUco automático
|
# 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_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_dictionary", default="DICT_4X4_50")
|
||||||
parser.add_argument("--charuco_squares_x", type=int, default=7)
|
parser.add_argument("--charuco_squares_x", type=int, default=13)
|
||||||
parser.add_argument("--charuco_squares_y", type=int, default=5)
|
parser.add_argument("--charuco_squares_y", type=int, default=7)
|
||||||
parser.add_argument("--charuco_square_length", type=float, default=1.0)
|
parser.add_argument("--charuco_square_length", type=float, default=0.031)
|
||||||
parser.add_argument("--charuco_marker_length", type=float, default=0.70)
|
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_markers", type=int, default=4)
|
||||||
parser.add_argument("--charuco_min_common_corners", type=int, default=8)
|
parser.add_argument("--charuco_min_common_corners", type=int, default=8)
|
||||||
parser.add_argument("--charuco_ransac_px", type=float, default=3.0)
|
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}
|
charuco_last["summary"] = {"rgb": rgb_sum, "re": re_sum, "nir": nir_sum}
|
||||||
|
|
||||||
if not rgb_pts:
|
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
|
charuco_sample_id += 1
|
||||||
messages = []
|
messages = []
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue