详细解释opencv aruco::detectMarkers代码

detectMarkers 函数是 Aruco 标记检测的核心函数之一,其主要作用是从输入图像中检测出 Aruco 标记,并输出它们的角点、ID 以及其他相关信息。以下是对 detectMarkers 函数代码的主要功能和流程的详细解释:


1. 输入参数

void detectMarkers(InputArray _image, OutputArrayOfArrays _corners, OutputArray _ids,
                   OutputArrayOfArrays _rejectedImgPoints, OutputArray _dictIndices, DictionaryMode dictMode)
  • _image: 输入图像(单通道或三通道)。
  • _corners: 输出检测到的标记角点数组。
  • _ids: 输出检测到的标记 ID 数组。
  • _rejectedImgPoints: 被拒绝的候选角点。
  • _dictIndices: 检测到的标记对应的字典索引(多字典模式下使用)。
  • dictMode: 字典模式,支持 Single 和 Multi

2. 图像预处理

Mat grey;
_convertToGrey(_image, grey);

将输入图像转换为灰度图 grey,以便后续处理。


3. 参数检查与设置

CV_Assert(!_image.empty());
CV_Assert(detectorParams.markerBorderBits > 0);
CV_Assert(!(detectorParams.useAruco3Detection == true && detectorParams.minSideLengthCanonicalImg == 0 && detectorParams.minMarkerLengthRatioOriginalImg == 0.0));

对输入图像和检测参数进行有效性检查:

  • 确保输入图像不为空。
  • 确保 markerBorderBits 大于 0。
  • 如果启用了 Aruco3 检测模式 (useAruco3Detection),需要确保 minSideLengthCanonicalImg 或 minMarkerLengthRatioOriginalImg 有有效值。

4. 图像金字塔构建

vector grey_pyramid;
int closest_pyr_image_idx = 0, num_levels = 0;

if (detectorParams.useAruco3Detection) {
    const float scale_pyr = 2.f;
    const float img_area = static_cast(grey.rows * grey.cols);
    const float min_area_marker = static_cast(detectorParams.minSideLengthCanonicalImg *
            detectorParams.minSideLengthCanonicalImg);
    num_levels = static_cast(log2(img_area / min_area_marker)/scale_pyr);
    const float scale_img_area = img_area * fxfy * fxfy;
    closest_pyr_image_idx = cvRound(log2(img_area / scale_img_area)/scale_pyr);
}
buildPyramid(grey, grey_pyramid, num_levels);

// resize to segmentation image
if (fxfy != 1.f)
    resize(grey, grey, Size(cvRound(fxfy * grey.cols), cvRound(fxfy * grey.rows)));
  • 构建图像金字塔 grey_pyramid,用于多尺度检测。
  • 在启用 Aruco3 功能时,根据公式计算图像金字塔的层数和最近层索引。
  • 将图像调整为适合分割的大小。

5. 候选标记检测

vector > candidates;
vector > contours;

if(detectorParams.cornerRefinementMethod == (int)CORNER_REFINE_APRILTAG){
    _apriltag(grey, detectorParams, candidates, contours);
} else {
    detectCandidates(grey, candidates, contours);
}
  • 使用 _apriltag 或 detectCandidates 方法检测候选标记。
  • detectCandidates 调用 _detectInitialCandidates 和 _reorderCandidatesCorners 来检测和排序候选标记角点。

6. 过滤过于接近的候选标记

vector ids;
vector> rejectedImgPoints;
vector selectedCandidates;

if (DictionaryMode::Single == dictMode) {
    Dictionary& dictionary = dictionaries.at(0);
    auto selectedCandidates = filterTooCloseCandidates(grey.size(), candidates, contours, dictionary.markerSize);
    ...
}
  • 调用 filterTooCloseCandidates 过滤过于接近的候选标记,并返回经过筛选的候选标记树 selectedCandidates

7. 标记识别

identifyCandidates(grey, grey_pyramid, selectedCandidates, candidates, contours, ids, dictionary, rejectedImgPoints);
  • 调用 identifyCandidates 对候选标记进行识别,判断是否符合指定字典中的标记格式。
  • 如果识别成功,则将其加入最终检测结果;否则,标记为被拒绝的候选标记。

8. 角点优化

if (detectorParams.cornerRefinementMethod == (int)CORNER_REFINE_SUBPIX) {
    performCornerSubpixRefinement(grey, grey_pyramid, closest_pyr_image_idx, candidates, dictionary);
}
  • 如果启用了亚像素角点优化 (CORNER_REFINE_SUBPIX),则调用 performCornerSubpixRefinement 对检测到的标记角点进行优化。

9. 其他角点优化方法

if (detectorParams.cornerRefinementMethod == (int)CORNER_REFINE_CONTOUR) {
    parallel_for_(Range(0, (int)candidates.size()), [&](const Range& range) {
        for (int i = range.start; i < range.end; i++) {
            _refineCandidateLines(contours[i], candidates[i]);
        }
    });
}
  • 如果启用了轮廓角点优化 (CORNER_REFINE_CONTOUR),则调用 _refineCandidateLines 对角点进行进一步优化。

10. 结果输出

_copyVector2Output(candidates, _corners);
Mat(ids).copyTo(_ids);
if(_rejectedImgPoints.needed()) {
    _copyVector2Output(rejectedImgPoints, _rejectedImgPoints);
}
if (_dictIndices.needed()) {
    Mat(dictIndices).copyTo(_dictIndices);
}
  • 将检测到的角点、ID 以及被拒绝的角点等信息输出到相应的输出参数中。

总结

detectMarkers 函数的主要流程如下:

  1. 图像预处理:将输入图像转换为灰度图。
  2. 参数检查:验证输入参数的有效性。
  3. 图像金字塔构建:支持多尺度检测。
  4. 候选标记检测:通过传统方法或 AprilTag 方法检测候选标记。
  5. 过滤候选标记:移除过于接近的候选标记。
  6. 标记识别:识别候选标记是否符合指定字典。
  7. 角点优化:根据配置选择不同的角点优化方法。
  8. 结果输出:将检测结果输出到指定变量中。

该函数实现了从原始图像到 Aruco 标记检测的完整流程,涵盖了检测、识别和优化等多个关键步骤。

你可能感兴趣的:(opencv,人工智能,计算机视觉,Aruco,标记,detectMarkers)