【opencv】示例-aruco_dict_utils.cpp 计算 ArUco 字典度量

此博客介绍了一个程序,它可用于计算 ArUco 字典度量,若要计算考虑翻转标记的指标,可使用 -'r' 标志。此外,该程序还能创建和编写自定义 ArUco 词典,输出文件为 custom_dict.yml。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

4016747f97a8a4fca15b65323d64f7e6.png

该程序可用于计算 ArUco 字典度量。

要计算考虑翻转标记的指标,请使用 -'r' 标志。

该程序可用于创建和编写自定义 ArUco 词典。

12c62f192220aefee57f8be0b298a5cf.png

1ebaa80dcafb8732a4bbb5f6135590af.png

#include <opencv2/objdetect/aruco_detector.hpp> // 包含aruco marker检测相关功能的头文件
#include <iostream> // 包含输入输出流相关功能的头文件


using namespace cv; // 使用命名空间cv,这样我们就可以直接使用OpenCV的函数和类而不需要加cv::前缀
using namespace std; // 使用命名空间std,标准的C++库函数比如std::cout可以直接写成cout


// 下面是静态函数的定义,因为我们不需要实例化对象就可以直接用类名调用它们
//为了确保ArUco标记的独一无二,这个函数计算了一个标记的自身最小汉明距离(即标记的不同旋转形态之间的最小差异度量),这有助于保证即使在不同的旋转下,标记也能被准确地检测和识别。
static int _getSelfDistance(const Mat &marker) {
    // 计算单个marker自身的汉明距离(marker之间的差异程度)


    Mat bytes = aruco::Dictionary::getByteListFromBits(marker); // 将marker的位图转换为字节列表


    double minHamming = (double)marker.total() + 1; // 初始化最小汉明距离为marker的总数+1
    for(int r = 1; r < 4; r++) { // 对每个旋转的标记进行遍历(共有四种旋转,不包括未旋转)
        // 创建两个临时的字节行,用于存储转换后的字节信息
        cv::Mat tmp1(1, bytes.cols, CV_8UC1, Scalar::all(0));
        cv::Mat tmp2(1, bytes.cols, CV_8UC1, Scalar::all(0));
        uchar* rot0 = tmp1.ptr(); // 获取行tmp1的指针
        uchar* rot1 = tmp2.ptr(); // 获取行tmp2的指针


        for (int i = 0; i < bytes.cols; ++i) { // 将marker的字节旋转r*90度并拷贝到临时字节行中
            rot0[i] = bytes.ptr()[i];
            rot1[i] = bytes.ptr()[bytes.cols*r + i];
        }


        // 计算两个临时行的汉明距离
        double currentHamming = cv::norm(tmp1, tmp2, cv::NORM_HAMMING);
        // 更新最小汉明距离
        if (currentHamming < minHamming) minHamming = currentHamming;
    }
    
    // 对marker进行水平翻转和垂直翻转后的处理逻辑与上面类似,不再重复。
    // 在marker的所有可能的变换后,返回最小的汉明距离
    // 检查水平翻转后的情况
    Mat b; // 定义一个矩阵用于存储翻转的结果
    flip(marker, b, 0); // 对marker进行水平翻转
    Mat flipBytes = aruco::Dictionary::getByteListFromBits(b); // 获取翻转后marker的字节列表
    // 对翻转后的marker进行相似度检查,逻辑与上面类似
    for(int r = 0; r < 4; r++) {
        // ... 代码逻辑与上面类似 ...
        cv::Mat tmp1(1, flipBytes.cols, CV_8UC1, Scalar::all(0));
        cv::Mat tmp2(1, bytes.cols, CV_8UC1, Scalar::all(0));
        uchar* rot0 = tmp1.ptr();
        uchar* rot1 = tmp2.ptr();


        for (int i = 0; i < bytes.cols; ++i) {
            rot0[i] = flipBytes.ptr()[i];
            rot1[i] = bytes.ptr()[bytes.cols*r + i];
        }


        double currentHamming = cv::norm(tmp1, tmp2, cv::NORM_HAMMING);
        if(currentHamming < minHamming) minHamming = currentHamming;
    }
    // 检查垂直翻转后的情况
    flip(marker, b, 1); // 对marker进行垂直翻转
    flipBytes = aruco::Dictionary::getByteListFromBits(b); // 获取翻转后marker的字节列表
    // 对垂直翻转后的marker进行相似度检查,逻辑与上面类似
    for(int r = 0; r < 4; r++) {
        // ... 代码逻辑与上面类似 ...
        cv::Mat tmp1(1, flipBytes.cols, CV_8UC1, Scalar::all(0));
        cv::Mat tmp2(1, bytes.cols, CV_8UC1, Scalar::all(0));
        uchar* rot0 = tmp1.ptr();
        uchar* rot1 = tmp2.ptr();


        for (int i = 0; i < bytes.cols; ++i) {
            rot0[i] = flipBytes.ptr()[i];
            rot1[i] = bytes.ptr()[bytes.cols*r + i];
        }


        double currentHamming = cv::norm(tmp1, tmp2, cv::NORM_HAMMING);
        if(currentHamming < minHamming) minHamming = currentHamming;
    }
    // 返回最小汉明距离的四舍五入结果
    return cvRound(minHamming);
}
//计算给定字典中,某个ArUco标记与特定ID的其他标记之间在全部或部分旋转的情况下的最小汉明距离。这个函数可以用于评估字典中标记的独一无二性,以及是否可以准确识别翻转后的标记。
static inline int getFlipDistanceToId(const aruco::Dictionary& dict, InputArray bits, int id, bool allRotations = true) {
    /
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值