无法使用 OpenCV 3.1.0 检测 ArUco 标记

Unable to detect ArUco markers with OpenCV 3.1.0

我正在尝试编写一个简单的 C++ 例程,首先将预定义的 ArUco 标记字典(例如 4x4_100)写入文件夹,然后使用 OpenCV 3.1 在从该文件夹中选择的特定图像中检测 ArUco 标记和 Visual Studio 2017。我已经编译了使用 ArUco 标记所需的所有 OpenCV-contrib 库。我的例程构建没有任何错误,但即使在向内置 "aruco::detectMarkers" 函数提供所有正确的参数(例如图像、字典等)后,我也无法检测到标记。你能帮我理解我的方法有什么问题吗?下面是一个最小的工作示例,并附上测试图像 here "4x4Marker_40.jpg":

#include "opencv2\core.hpp"
#include "opencv2\imgproc.hpp"
#include "opencv2\imgcodecs.hpp"
#include "opencv2\aruco.hpp"
#include "opencv2\highgui.hpp"
#include <sstream>
#include <fstream>
#include <iostream>

using namespace cv;
using namespace std;

// Function to write ArUco markers
void createArucoMarkers()
{

// Define variable to store the output markers
    Mat outputMarker;
// Choose a predefined Dictionary of markers
    Ptr< aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
// Write each of the markers to a '.jpg' image file
    for (int i = 0; i < 50; i++)
    {
        aruco::drawMarker(markerDictionary, i, 500, outputMarker, 1);
        ostringstream convert;
        string imageName = "4x4Marker_";
        convert << imageName << i << ".jpg";
        imwrite(convert.str(), outputMarker);

    }
}


// Main body of the routine
int main(int argv, char** argc)
{
    createArucoMarkers();

// Read a specific image
    Mat frame = imread("4x4Marker_40.jpg", CV_LOAD_IMAGE_UNCHANGED);
// Define variables to store the output of marker detection
    vector<int> markerIds;
    vector<vector<Point2f>> markerCorners, rejectedCandidates;
// Define a Dictionary type variable for marker detection  
    Ptr<aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);

// Detect markers
    aruco::detectMarkers(frame, markerDictionary, markerCorners, markerIds);

// Display the image
    namedWindow("Webcam", CV_WINDOW_AUTOSIZE);
    imshow("Webcam", frame);
// Draw detected markers on the displayed image
    aruco::drawDetectedMarkers(frame, markerCorners, markerIds);
    cout << "\nmarker ID is:\t"<<markerIds.size();
    waitKey();

}

您的代码中存在一些问题:

  1. 您在调用 drawDetectedMarkers 之前使用 imshow 显示图像,因此您永远不会看到检测到的标记。
  2. 您显示的是 markerIds 向量的大小,而不是其中包含的值。
  3. (这是主要问题)您的标记周围没有白色 space,因此无法检测到。

一个建议:在 #include 语句中使用正斜杠,而不是反斜杠。正斜杠无处不在,反斜杠仅在 Windows.

上有效

这在我的机器上有效。请注意,我将图像加载为彩色图像,以便更容易查看 drawDetectedMarkers.

的结果
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/aruco.hpp>
#include <opencv2/highgui.hpp>
#include <sstream>
#include <fstream>
#include <iostream>

using namespace cv;
using namespace std;

// Function to write ArUco markers
void createArucoMarkers()
{

    // Create image to hold the marker plus surrounding white space
    Mat outputImage(700, 700, CV_8UC1);
    // Fill the image with white
    outputImage = Scalar(255);
    // Define an ROI to write the marker into
    Rect markerRect(100, 100, 500, 500);
    Mat outputMarker(outputImage, markerRect);

    // Choose a predefined Dictionary of markers
    Ptr< aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);
    // Write each of the markers to a '.jpg' image file
    for (int i = 0; i < 50; i++)
    {
        //Draw the marker into the ROI
        aruco::drawMarker(markerDictionary, i, 500, outputMarker, 1);
        ostringstream convert;
        string imageName = "4x4Marker_";
        convert << imageName << i << ".jpg";
        // Note we are writing outputImage, not outputMarker
        imwrite(convert.str(), outputImage);

    }
}


// Main body of the routine
int main(int argv, char** argc)
{
    createArucoMarkers();

    // Read a specific image
    Mat frame = imread("4x4Marker_40.jpg", CV_LOAD_IMAGE_COLOR);
    // Define variables to store the output of marker detection
    vector<int> markerIds;
    vector<vector<Point2f>> markerCorners, rejectedCandidates;
    // Define a Dictionary type variable for marker detection
    Ptr<aruco::Dictionary> markerDictionary = aruco::getPredefinedDictionary(aruco::PREDEFINED_DICTIONARY_NAME::DICT_4X4_50);

    // Detect markers
    aruco::detectMarkers(frame, markerDictionary, markerCorners, markerIds);

    // Display the image
    namedWindow("Webcam", CV_WINDOW_AUTOSIZE);
    // Draw detected markers on the displayed image
    aruco::drawDetectedMarkers(frame, markerCorners, markerIds);
    // Show the image with the detected marker
    imshow("Webcam", frame);

    // If a marker was identified, show its ID
    if (markerIds.size() > 0) {
        cout << "\nmarker ID is:\t" << markerIds[0] << endl;
    }
    waitKey(0);

}