javaopencvcomputer-visionaruco

ArUco marker cannot be detected by OpenCV ArUco library in JAVA


I was working on a project where I have to detect ArUco markers in the images captured by the webcam. I was following the documentation until I found out that Java implementation of OpenCV ArUco module differs from what was described in the documentation, and deviated to finding my own way of detecting ArUco markers. Here is a minimal, reproducible example:

public class Main {
    public static void main(String[] args) {
        OpenCV.loadLocally();

        // ---------------------------------------------------------------
        // Adding the marker to detect in the dictionary.
        byte[][] marker =
                {{0, 1, 1, 0, 0, 1}, {0, 1, 1, 0, 1, 0}, {1, 1, 0, 0, 0, 0},
                {1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 0, 0}, {0, 0, 1, 1, 0, 0}};

        Mat mat = new Mat(6, 6, CvType.CV_8UC1);
        for (int i = 0; i < 6; i++)
            for (int j = 0; j < 6; j++)
                mat.put(i, j, marker[i][j]);
        Mat compressed = Dictionary.getByteListFromBits(mat);

        Dictionary dict = new Dictionary(compressed, 6);
        ArucoDetector detector = new ArucoDetector(dict);

        // ---------------------------------------------------------------
        // Initializing webcam (/dev/video0) and looping
        VideoCapture cap = new VideoCapture("/dev/video0");

        while (cap.isOpened()) {
            Mat image = new Mat();

            cap.read(image);
            if (image.empty())
                continue;

            ArrayList<Mat> corners = new ArrayList<>();
            Mat ids = new Mat();

            try {
                detector.detectMarkers(image, corners, ids);
                if (!corners.isEmpty())                         // If the marker is detected,
                    System.out.println(corners.size());         // this should print something.
            } catch (CvException e) {
                System.out.println(e.getMessage());
            }
        }
    }
}

(OpenCV and ArUco detection library have been install by Gradle)

The above code was written to detect the marker at the center of the image.

Thanks for the help in advance, and I will provide more information appropriately if needed.


Edit:

As described in many documentations, blog posts, and stackoverflow questions, I tried getPredefinedDictionary method, but got the following error:

            ArucoDetector detector = new ArucoDetector(Aruco.getPredefinedDictionary(Aruco.DICT_6X6_250));
                                     ^
    constructor ArucoDetector.ArucoDetector(long) is not applicable
      (argument mismatch; org.opencv.aruco.Dictionary cannot be converted to long)
    constructor ArucoDetector.ArucoDetector(org.opencv.objdetect.Dictionary) is not applicable
      (argument mismatch; org.opencv.aruco.Dictionary cannot be converted to org.opencv.objdetect.Dictionary)

Here's the code in the original question with Dictionary changed.

public class Main {
    public static void main(String[] args) {
        OpenCV.loadLocally();



        // ---------------------------------------------------------------
        // Adding the marker to detect in the dictionary.
        byte[][] marker =
                {{0, 1, 1, 0, 0, 1}, {0, 1, 1, 0, 1, 0}, {1, 1, 0, 0, 0, 0},
                {1, 0, 0, 1, 1, 0}, {0, 0, 1, 1, 0, 0}, {0, 0, 1, 1, 0, 0}};

        Mat mat = new Mat(6, 6, CvType.CV_8UC1);
        for (int i = 0; i < 6; i++)
            for (int j = 0; j < 6; j++)
                mat.put(i, j, marker[i][j]);
        Mat compressed = Dictionary.getByteListFromBits(mat);

        // Dictionary dict = new Dictionary(compressed, 6);
        ArucoDetector detector = new ArucoDetector(Aruco.getPredefinedDictionary(Aruco.DICT_6X6_250));

        // ---------------------------------------------------------------
        // Initializing webcam (/dev/video0) and looping
        VideoCapture cap = new VideoCapture("/dev/video0");

        while (cap.isOpened()) {
            Mat image = new Mat();

            cap.read(image);
            if (image.empty())
                continue;

            ArrayList<Mat> corners = new ArrayList<>();
            Mat ids = new Mat();

            try {
                detector.detectMarkers(image, corners, ids);
                if (!corners.isEmpty())                         // If the marker is detected,
                    System.out.println(corners.size());         // this should print something.
            } catch (CvException e) {
                System.out.println(e.getMessage());
            }
        }
    }
}

I also attempted to cast the return value of getPredefinedDictionary to org.opencv.objdetect.Dictionary, which is required by org.opencv.objdetect.ArucoDetector, but casting also have failed.


Solution

  • You can use Aruco.getPredefinedDictionary(Aruco.DICT_6X6_250). It is a more standard approach than creating a custom dictionary unless you have a specific need. The dictionary DICT_6X6_250 includes a wide range of markers. If you need a specific marker, you can customize the dictionary as per your needs. You can use 'DetectorParameters.create()' for more customizable detection. Here are some more OpenCV-related links that you may find helpful:

    Aruco , Charuco detection with java and opencv

    https://www.pcbway.com/project/shareproject/How_to_use_AI_to_program_a_2DOF_ROBOT_Arduino_pyhton_opencv_chatgp_ps3eyecam_d3896679.html