无法使用OpenCV 3.1.0检测ArUco标记

时间:2017-07-26 12:17:34

标签: c++ opencv visual-c++ opencv3.1 aruco

我正在尝试编写一个简单的C ++例程,首先将一个预定义的ArUco标记字典(例如4x4_100)写入文件夹,然后使用OpenCV 3.1和Visual Studio 2017检测从该文件夹中选择的特定图像中的ArUco标记。编译了使用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 个答案:

答案 0 :(得分:2)

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

  1. 在调用imshow之前,您正在使用drawDetectedMarkers显示图片,因此您永远不会看到检测到的标记。
  2. 您正在显示markerIds向量的大小,而不是其中包含的值。
  3. (这是主要问题)你的标记周围没有空白区域,因此无法检测到。
  4. 一个建议:在#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);
    
    }