调整 aruco 检测参数对标记识别的影响

Eta*_*nio 2 opencv aruco

我有两张非常相似的照片,这张照片被正确识别为 5x5_250 字典的标记 209

Aruco 识别的标记 209

虽然另一个非常相似但无法识别,但它是同一 5x5_250 字典的标记 207:

标记 207 未被 Aruco 识别

并且在另一张照片中也识别出了标记 207:

标记 207 已识别

我尝试更改探测器参数中的某些内容

params->adaptiveThreshWinSizeMin = 4;
params->adaptiveThreshWinSizeMax = 26;
params->adaptiveThreshWinSizeStep = 2;
params->minMarkerPerimeterRate = 0.01;
params->maxMarkerPerimeterRate = 4;
params->polygonalApproxAccuracyRate = 0.1;
params->perspectiveRemovePixelPerCell = 10;
Run Code Online (Sandbox Code Playgroud)

但似乎没有任何变化,所以我回到默认值,所以我的问题是:

  1. 标记周围是否需要有白色边框?
  2. 为什么第二张照片中的标记 207 未被识别?谢谢

Joh*_*ohn 6

ArUco 标记周围的白色边框是必要的,因为 ArUco 标记检测的第一步是角点检测。有关参考,请参阅ArUco 库文档的第 4 页

不幸的是,切断标记周围所谓的“安静区域”是一个常见问题。将来,打印带有额外角的标记可能会有所帮助,如下所示:

ArUco 带角标记

要生成角,请运行此代码片段并将图像拖放到其指示的位置。然后右键单击并“将图像另存为...”。

var canvas = document.getElementById("myCanvas");
var context = canvas.getContext("2d");
var theImage = null;

function redraw(){
    if (!theImage){
        context.font = "30px Arial";
        context.fillStyle = "black";
        context.fillText("Drag & Drop image here.", 10, 40);
        return;
    }
    
    var width = theImage.width;
    var height = theImage.height;
    
    var nTiles = 8;
    var padding = 3;
    var cornerLength = 4;
    var dx = width / nTiles;
    var dy = height / nTiles;
    
    canvas.width = 2 * padding * dx + width;
    canvas.height = 2 * padding * dy + height;
    
    // clear background
    context.fillStyle = "#ffffff";
    context.fillRect(0, 0, canvas.width, canvas.height);
    
    // draw corners
    context.fillStyle = "#000000";
    context.fillRect(0, 0, dx, dy * cornerLength);
    context.fillRect(0, 0, cornerLength * dx, dy);
    context.fillRect(canvas.width - dx, canvas.height - dy * cornerLength, dx, dy * cornerLength);
    context.fillRect(canvas.width - cornerLength * dx, canvas.height - dy, cornerLength * dx, dy);
    context.fillRect(canvas.width - dx, 0, dx, dy * cornerLength);
    context.fillRect(canvas.width - cornerLength * dx, 0, dx * cornerLength, dy);
    context.fillRect(0, canvas.height - dy * cornerLength, dx, dy * cornerLength);
    context.fillRect(0, canvas.height - dy, cornerLength * dx, dy);
    
    // draw image
    context.drawImage(theImage, padding * dx, padding * dy);
}

redraw();

function handleFile(file){
    var reader = new FileReader();
    reader.onload = function(){
        var image = new Image();
        image.src = this.result;
        image.onload = function(){
            theImage = image;
            redraw();
        }
    }
    reader.readAsDataURL(file);
}

canvas.addEventListener("dragover", function(e){
    e.preventDefault()
    e.stopPropagation()
})

canvas.addEventListener("drop", function(e){
    var files = e.dataTransfer.files;
    for (var i = 0; i < files.length; i++){
        handleFile(files[i]);
    }
    e.preventDefault()
    e.stopPropagation()
})
Run Code Online (Sandbox Code Playgroud)
<canvas id="myCanvas" width="512" height="512"></canvas>
Run Code Online (Sandbox Code Playgroud)