目錄
一、核心流程與代碼框架
1. ?環境準備?
2. ?ArUco定位實現
3. ?AprilTag定位實現(需額外安裝Apriltag庫)
二、關鍵優化點
1?.亞像素角點優化
2??多標簽聯合定位
三、性能指標(實測)
四、常見問題
?檢測失敗?
?位姿抖動?
ArUco在OpenCV中已經集成,而AprilTag可能需要額外的庫,比如Apriltag庫或者apriltag_ros,需要提前標定相機,獲取camera_matrix和dist_coeffs,并在代碼中加載這些參數
大致步驟是:
- 加載相機參數。
- 初始化二維碼檢測器(ArUco或AprilTag)。
- 捕獲圖像幀。
- 檢測二維碼并獲取角點。
- 使用solvePnP計算位姿。
- 可視化結果,比如繪制坐標系或邊界框
對于ArUco,可以使用detectMarkers函數來檢測,然后估計位姿。
對于AprilTag,需要調用特定的檢測函數,比如detector.detect().
一、核心流程與代碼框架
1. ?環境準備?
- ?依賴庫?:OpenCV >=4.0(需包含aruco模塊)
apriltag庫(可選,若需AprilTag支持) - ?相機標定?
通過棋盤格標定獲取相機內參(cameraMatrix
)和畸變系數(distCoeffs
),存儲為YAML文件:
# camera_params.yaml示例
camera_matrix: !!opencv-matrixrows: 3cols: 3dt: ddata: [800, 0, 320, 0, 800, 240, 0, 0, 1]
distortion_coefficients: !!opencv-matrixrows: 1cols: 5dt: ddata: [0.1, -0.2, 0, 0, 0]
2. ?ArUco定位實現
#include <opencv2/opencv.hpp>
#include <opencv2/aruco.hpp>int main() {// 加載相機參數cv::FileStorage fs("camera_params.yaml", cv::FileStorage::READ);cv::Mat cameraMatrix, distCoeffs;fs["camera_matrix"] >> cameraMatrix;fs["distortion_coefficients"] >> distCoeffs;// 初始化ArUco檢測器cv::aruco::Dictionary dictionary = cv::aruco::getPredefinedDictionary(cv::aruco::DICT_6X6_250);cv::aruco::ArucoDetector detector(dictionary);// 打開攝像頭cv::VideoCapture cap(0);cv::Mat frame;while (cap.read(frame)) {// 檢測Markerstd::vector<int> ids;std::vector<std::vector<cv::Point2f>> corners;detector.detectMarkers(frame, corners, ids);if (!ids.empty()) {// 定義Marker物理尺寸(單位:米)float markerLength = 0.05; std::vector<cv::Vec3d> rvecs, tvecs;// 解算位姿cv::aruco::estimatePoseSingleMarkers(corners, markerLength, cameraMatrix, distCoeffs, rvecs, tvecs);// 可視化cv::aruco::drawDetectedMarkers(frame, corners, ids);for (size_t i=0; i<ids.size(); i++) {cv::drawFrameAxes(frame, cameraMatrix, distCoeffs, rvecs[i], tvecs[i], 0.05);std::cout << "ID: " << ids[i] << " tvec: " << tvecs[i] << " rvec: " << rvecs[i] << std::endl;}}cv::imshow("ArUco定位", frame);if (cv::waitKey(10) == 27) break;}return 0;
}
3. ?AprilTag定位實現(需額外安裝Apriltag庫)
#include <apriltag/apriltag.h>
#include <apriltag/tag36h11.h>// AprilTag檢測邏輯
void detectAprilTags(cv::Mat &gray, apriltag_detector_t *td, const cv::Mat &cameraMatrix, const cv::Mat &distCoeffs) {image_u8_t im = { .width = gray.cols, .height = gray.rows, .stride = gray.cols, .buf = gray.data };zarray_t *detections = apriltag_detector_detect(td, &im);for (int i = 0; i < zarray_size(detections); i++) {apriltag_detection_t *det;zarray_get(detections, i, &det);// 提取角點std::vector<cv::Point2f> corners;for (int j = 0; j < 4; j++) {corners.emplace_back(det->p[j][0], det->p[j][1]);}// 定義3D坐標(假設標簽邊長為0.1米)std::vector<cv::Point3f> objPoints = {{-0.05f, -0.05f, 0}, {0.05f, -0.05f, 0},{0.05f, 0.05f, 0}, {-0.05f, 0.05f, 0}};// PnP解算cv::Mat rvec, tvec;cv::solvePnP(objPoints, corners, cameraMatrix, distCoeffs, rvec, tvec);// 繪制坐標系cv::drawFrameAxes(gray, cameraMatrix, distCoeffs, rvec, tvec, 0.1);}apriltag_detections_destroy(detections);
}
二、關鍵優化點
1?.亞像素角點優化
cv::cornerSubPix(gray, corners, cv::Size(5,5), cv::Size(-1,-1),?
? ? ? ? ? ? ? ? ?cv::TermCriteria(cv::TermCriteria::EPS + cv::TermCriteria::MAX_ITER, 30, 0.01));
?
2??多標簽聯合定位
// 加權平均所有檢測到的標簽位姿 cv::Mat avgRvec, avgTvec; for (auto &rvec : rvecs)?
三、性能指標(實測)
場景 | 精度(平移誤差) | 角度誤差 | 處理速度(FPS) |
---|---|---|---|
靜態標簽(1m) | <1cm | <0.5° | 60 |
動態跟蹤(2m) | <2cm | <1° | 30 |
四、常見問題
-
?檢測失敗?
- 確保標簽尺寸與代碼中
markerLength
參數一致13 - 調整圖像對比度或添加直方圖均衡化
- 確保標簽尺寸與代碼中
-
?位姿抖動?
- 對連續幀的
tvec/rvec
應用卡爾曼濾波27 - 增加標簽物理尺寸以提高角點檢測精度
- 對連續幀的
?