用单目相机和apriltag二维码aruco实现单目定位

目录

一、核心流程与代码框架

[1. ‌环境准备‌](#1. ‌环境准备‌)

[2. ‌ArUco定位实现](#2. ‌ArUco定位实现)

[3. ‌AprilTag定位实现(需额外安装Apriltag库)](#3. ‌AprilTag定位实现(需额外安装Apriltag库))

二、关键优化点

1‌.亚像素角点优化

[2‌ 多标签联合定位](#2‌ 多标签联合定位)

三、性能指标(实测)

四、常见问题

‌检测失败‌

‌位姿抖动‌


ArUco在OpenCV中已经集成,而AprilTag可能需要额外的库,比如Apriltag库或者apriltag_ros,需要提前标定相机,获取camera_matrix和dist_coeffs,并在代码中加载这些参数

大致步骤是:

  1. 加载相机参数。
  2. 初始化二维码检测器(ArUco或AprilTag)。
  3. 捕获图像帧。
  4. 检测二维码并获取角点。
  5. 使用solvePnP计算位姿。
  6. 可视化结果,比如绘制坐标系或边界框

对于ArUco,可以使用detectMarkers函数来检测,然后估计位姿。

对于AprilTag,需要调用特定的检测函数,比如detector.detect().

一、核心流程与代码框架

1. ‌环境准备

  • 依赖库 ‌:OpenCV >=4.0(需包含aruco模块)
    apriltag库(可选,若需AprilTag支持)

  • 相机标定
    通过棋盘格标定获取相机内参(cameraMatrix)和畸变系数(distCoeffs),存储为YAML文件:

    camera_params.yaml示例

    camera_matrix: !!opencv-matrix
    rows: 3
    cols: 3
    dt: d
    data: [800, 0, 320, 0, 800, 240, 0, 0, 1]
    distortion_coefficients: !!opencv-matrix
    rows: 1
    cols: 5
    dt: d
    data: [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)) {
        // 检测Marker
        std::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
  • 增加标签物理尺寸以提高角点检测精度
相关推荐
智驱力人工智能6 天前
夏季道路安全的AI革命:节省人力、提升效率
人工智能·安全·边缘计算·视觉算法·视觉分析·智能巡航·人工智能云计算
智驱力人工智能1 个月前
人员进出新视界:视觉分析算法的力量
人工智能·智慧工厂·智慧工地·视觉算法·智慧监控·视觉分析·离岗检测
智驱力人工智能1 个月前
智能飞鸟监测 守护高压线安全
人工智能·计算机视觉·视觉检测·智能巡检·视觉算法·飞鸟检测·视觉分析
boss-dog6 个月前
2.5D视觉——Aruco码定位检测
视觉定位·视觉算法·aruco
lucky li1 年前
多相机系统通用视觉 SLAM 框架的设计与评估
slam·视觉算法