0

I am trying to code a simple C++ routine to first write a predefined dictionary of ArUco markers (e.g. 4x4_100) to a folder and then detect ArUco markers in a specific image selected from the folder using OpenCV 3.1 and Visual Studio 2017. I have compiled all the OpenCV-contrib libraries required to use ArUco markers. My routine builds without any error, but I am having trouble detecting the markers even after supplying all the correct arguments (e.g. image, Dictionary, etc.) to the in-built "aruco::detectMarkers" function. Could you please help me understand what`s wrong with my approach? Below is a minimal working example and the test image is attached 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();

}
Sameer Sharma
  • 23
  • 1
  • 7

1 Answers1

4

There are a few problems in your code:

  1. You are displaying the image with imshow before calling drawDetectedMarkers so you'll never see the detected marker.
  2. You are displaying the size of the markerIds vector instead of the value contained within it.
  3. (This is the main problem) Your marker has no white space around it so it's impossible to detect.

One suggestion: use forward slashes, not backslashes in your #include statements. Forward slashes work everywhere, backslashes only work on Windows.

This worked on my machine. Note that I loaded the image as a color image to make it easier to see the results of 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);

}
SSteve
  • 10,550
  • 5
  • 46
  • 72
  • It worked, Steve! I have also made a note of your suggestion regarding the usage of forward slashes. I have just started coding in C++ and am working on detecting multiple ArUco markers in a given image. Will ping you guys back in case I have other doubts. TC. – Sameer Sharma Jul 27 '17 at 07:20