In this tutorial you will learn how to detect ArUco markers in images and real-time video streams using OpenCV and Python.
This blog post is part two in our three-part series on ArUco markers and fiducials:
- Generating ArUco markers with OpenCV and Python (last week’s post)
- Detecting ArUco markers in images and video with OpenCV (today’s tutorial)
- Automatically determining ArUco marker type with OpenCV (next week’s post)
Last week we learned:
- What an ArUco dictionary is
- How to select an ArUco dictionary appropriate to our task
- How to generate ArUco markers using OpenCV
- How to create ArUco markers using online tools
Today we’re going to learn how to actually detect ArUco markers using OpenCV.
To learn how to detect ArUco markers in images and real-time video with OpenCV, just keep reading.
Looking for the source code to this post?
Jump Right To The Downloads SectionDetecting ArUco markers with OpenCV and Python
In the first part of this tutorial, you will learn about OpenCV’s cv2.aruco
module and how to detect ArUco markers in images and real-time video streams by:
- Specifying your ArUco dictionary
- Creating the parameters to the ArUco detector (which is typically just a single line of code using the default values)
- Applying the
cv2.aruco.detectMarkers
to actually detect the ArUco markers in your image or video stream
From there we’ll review our project directory structure and implement two Python scripts:
- One Python script to detect ArUco markers in images
- And another Python script to detect ArUco markers in real-time video streams
We’ll wrap up this tutorial on ArUco marker detection using OpenCV with a discussion of our results.
OpenCV ArUCo marker detection
As I discussed in last week’s tutorial, the OpenCV library comes with built-in ArUco support, both for generating ArUco markers and for detecting them.
Detecting ArUco markers with OpenCV is a three-step process made possible via the
submodule:cv2.aruco
- Step #1: Use the
cv2.aruco.Dictionary_get
function to grab the dictionary of ArUco markers we’re using. - Step #2: Define the ArUco detection parameters using
cv2.aruco.DetectorParameters_create
. - Step #3: Perform ArUco marker detection via the
cv2.aruco.detectMarkers
function.
Most important to us, we need to learn how to use the detectMarkers
function.
Understanding the “cv2.aruco.detectMarkers” function
We can define an ArUco marker detection procedure in, essentially, only 3-4 lines of code:
arucoDict = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_50) arucoParams = cv2.aruco.DetectorParameters_create() (corners, ids, rejected) = cv2.aruco.detectMarkers(image, arucoDict, parameters=arucoParams)
The
function accepts three arguments:cv2.aruco.detectMarkers
image
: The input image that we want to detect ArUco markers in
: The ArUco dictionary we are usingarucoDict
: The ArUco parameters used for detection (unless you have a good reason to modify the parameters, the default parameters returned byparameters
cv2.aruco.DetectorParameters_create
are typically sufficient)
After applying ArUco tag detection, the cv2.aruco.detectMarkers
method returns three values:
: A list containing the (x, y)-coordinates of our detected ArUco markerscorners
: The ArUco IDs of the detected markersids
: A list of potential markers that were found but ultimately rejected due to the inner code of the marker being unable to be parsed (visualizing therejected
rejected
markers is often useful for debugging purposes)
Later in this post you will see how to use the cv2.aruco.detectMarkers
function to detect ArUco markers in images and real-time video streams.
Configuring your development environment
In order to generate and detect ArUco markers, you need to have the OpenCV library installed.
Luckily, OpenCV is pip-installable:
$ pip install opencv-contrib-python
If you need help configuring your development environment for OpenCV 4.3+, I highly recommend that you read my pip install opencv guide — it will have you up and running in a matter of minutes.
Having problems configuring your development environment?
All that said, are you:
- Short on time?
- Learning on your employer’s administratively locked system?
- Wanting to skip the hassle of fighting with the command line, package managers, and virtual environments?
- Ready to run the code right now on your Windows, macOS, or Linux system?
Then join PyImageSearch Plus today!
Gain access to Jupyter Notebooks for this tutorial and other PyImageSearch guides that are pre-configured to run on Google Colab’s ecosystem right in your web browser! No installation required.
And best of all, these Jupyter Notebooks will run on Windows, macOS, and Linux!
Project structure
Before we can learn how to detect ArUco tags in images, let’s first review our project directory structure so you have a good idea on how our project is organized and what Python scripts we’ll be using.
Start by using the “Downloads” section of this tutorial to download the source code and example images.
From there, we can inspect the project directory:
$ tree . --dirsfirst . ├── images │ ├── example_01.png │ └── example_02.png ├── detect_aruco_image.py └── detect_aruco_video.py 2 directories, 9 files
Today we’ll be reviewing two Python scripts:
: Detects ArUco tags in images. The example images we’ll be applying this script to reside in thedetect_aruco_image.py
directory.images/
: Applies ArUco detection to real-time video streams. I’ll be using my webcam as an example, but you could pipe in frames from a video file residing on disk as well.detect_aruco_video.py
With our project directory structure reviewed, we can move on to implementing ArUco tag detection with OpenCV!
Detecting ArUco markers with OpenCV in images
Ready to learn how to detect ArUco tags in images using OpenCV?
Open up the
file in your project directory, and let’s get to work:detect_aruco_image.py
# import the necessary packages import argparse import imutils import cv2 import sys
We start off by importing our required Python packages.
We’ll use argparse
to parse our command line arguments, imutils
for resizing images, cv2
for our OpenCV bindings, and sys
in the event that we need to prematurely exit our script.
Next comes our command line arguments:
# construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-i", "--image", required=True, help="path to input image containing ArUCo tag") ap.add_argument("-t", "--type", type=str, default="DICT_ARUCO_ORIGINAL", help="type of ArUCo tag to detect") args = vars(ap.parse_args())
We have two command line arguments that we need to parse:
--image
: The path to the input image containing any ArUco tags we want to detect
: The type of ArUco tags that we’ll be detecting--type
Setting the
argument correctly is absolutely critical to successfully detect ArUco tags in input images.--type
Simply put:
The --type
argument that we supply here must be the same ArUco type used to generate the tags in the input images. If one type was used to generate ArUco tags and then you use a different type when trying to detect them, the detection will fail, and you’ll end up with zero detected ArUco tags.
Therefore, you must make absolutely certain that the type used to generate the ArUco tags is the same type you are using for the detection phase.
Note: Don’t know what ArUco dictionary was used to generate the tags in your input images? Don’t worry, I’ve got you covered. Next week I’ll be showing you one of the Python scripts in my personal arsenal that I break out when I can’t identify what type a given ArUco tag is. This script automatically identifies the ArUco tag type. Stay tuned for next week’s tutorial, where I’ll review it in detail.
Next up comes our
, which enumerates each of the ArUco tag types that OpenCV supports:ARUCO_DICT
# define names of each possible ArUco tag OpenCV supports ARUCO_DICT = { "DICT_4X4_50": cv2.aruco.DICT_4X4_50, "DICT_4X4_100": cv2.aruco.DICT_4X4_100, "DICT_4X4_250": cv2.aruco.DICT_4X4_250, "DICT_4X4_1000": cv2.aruco.DICT_4X4_1000, "DICT_5X5_50": cv2.aruco.DICT_5X5_50, "DICT_5X5_100": cv2.aruco.DICT_5X5_100, "DICT_5X5_250": cv2.aruco.DICT_5X5_250, "DICT_5X5_1000": cv2.aruco.DICT_5X5_1000, "DICT_6X6_50": cv2.aruco.DICT_6X6_50, "DICT_6X6_100": cv2.aruco.DICT_6X6_100, "DICT_6X6_250": cv2.aruco.DICT_6X6_250, "DICT_6X6_1000": cv2.aruco.DICT_6X6_1000, "DICT_7X7_50": cv2.aruco.DICT_7X7_50, "DICT_7X7_100": cv2.aruco.DICT_7X7_100, "DICT_7X7_250": cv2.aruco.DICT_7X7_250, "DICT_7X7_1000": cv2.aruco.DICT_7X7_1000, "DICT_ARUCO_ORIGINAL": cv2.aruco.DICT_ARUCO_ORIGINAL, "DICT_APRILTAG_16h5": cv2.aruco.DICT_APRILTAG_16h5, "DICT_APRILTAG_25h9": cv2.aruco.DICT_APRILTAG_25h9, "DICT_APRILTAG_36h10": cv2.aruco.DICT_APRILTAG_36h10, "DICT_APRILTAG_36h11": cv2.aruco.DICT_APRILTAG_36h11 }
The key to this dictionary is a human-readable string (i.e., the name of the ArUco tag type). The key then maps to the value, which is OpenCV’s unique identifier for the ArUco tag type.
Using this dictionary we can take our input --type
command line argument, pass it through ARUCO_DICT
, and then obtain the unique identifier for the ArUco tag type.
The following Python shell block shows you a simple example of how this lookup operation is performed:
>>> print(args) {'type': 'DICT_5X5_100'} >>> arucoType = ARUCO_DICT[args["type"]] >>> print(arucoType) 5 >>> 5 == cv2.aruco.DICT_5X5_100 True >>>
I covered the types of ArUco dictionaries, including their name conventions in my previous tutorial, Generating ArUco markers with OpenCV and Python.
If you would like more information on ArUco dictionaries, please refer there; otherwise, simply understand that this dictionary lists out all possible ArUco tags that OpenCV can detect.
Next, let’s move on to loading our input image from disk:
# load the input image from disk and resize it print("[INFO] loading image...") image = cv2.imread(args["image"]) image = imutils.resize(image, width=600) # verify that the supplied ArUCo tag exists and is supported by # OpenCV if ARUCO_DICT.get(args["type"], None) is None: print("[INFO] ArUCo tag of '{}' is not supported".format( args["type"])) sys.exit(0) # load the ArUCo dictionary, grab the ArUCo parameters, and detect # the markers print("[INFO] detecting '{}' tags...".format(args["type"])) arucoDict = cv2.aruco.Dictionary_get(ARUCO_DICT[args["type"]]) arucoParams = cv2.aruco.DetectorParameters_create() (corners, ids, rejected) = cv2.aruco.detectMarkers(image, arucoDict, parameters=arucoParams)
Lines 43 and 44 load our input image
and then resize it to have a width of 600 pixels (such that the image can easily fit on our screen).
If you have a high resolution input image that has small ArUco tags, you may need to adjust this resizing operation; otherwise, the ArUco tags may be too small to detect after the resizing operation.
Line 48 checks to see if the ArUco --type
name exists in the ARUCO_DICT
. If it does not, then we exit the script, since we don’t have an ArUco dictionary available for the supplied --type
.
Otherwise, we:
- Load the ArUco dictionary using the
--type
and theARUCO_DICT
lookup (Line 56) - Instantiate our ArUco detector parameters (Line 57)
- Apply ArUco detection using the
cv2.aruco.detectMarkers
function (Lines 58 and 59)
The cv2.aruco.detectMarkers
results in a 3-tuple of:
: The (x, y)-coordinates of our detected ArUco markerscorners
: The identifiers of the ArUco markers (i.e., the ID encoded in the marker itself)ids
: A list of potential markers that were detected but ultimately rejected due to the code inside the marker not being able to be parsedrejected
Let’s now start visualizing the ArUco markers we have detected:
# verify *at least* one ArUco marker was detected if len(corners) > 0: # flatten the ArUco IDs list ids = ids.flatten() # loop over the detected ArUCo corners for (markerCorner, markerID) in zip(corners, ids): # extract the marker corners (which are always returned in # top-left, top-right, bottom-right, and bottom-left order) corners = markerCorner.reshape((4, 2)) (topLeft, topRight, bottomRight, bottomLeft) = corners # convert each of the (x, y)-coordinate pairs to integers topRight = (int(topRight[0]), int(topRight[1])) bottomRight = (int(bottomRight[0]), int(bottomRight[1])) bottomLeft = (int(bottomLeft[0]), int(bottomLeft[1])) topLeft = (int(topLeft[0]), int(topLeft[1]))
Line 62 makes a check to ensure at least one marker was detected.
If so, we proceed to flatten the ArUco ids
list (Line 64) and then loop over each of the corners
and ids
together.
Each markerCorner
is represented by a list of four (x, y)-coordinates (Line 70).
These (x, y)-coordinates represent the top-left, top-right, bottom-right, and bottom-left corners of the ArUco tag (Line 71). Furthermore, the (x, y)-coordinates are always returned in that order.
The topRight
, bottomRight
, bottomLeft
, and topLeft
variables are NumPy arrays; however, we need to cast them to integer values (int
) such that we can use OpenCV’s drawing functions to visualize the markers on our image
(Lines 74-77).
With the marker (x, y)-coordinates cast of integers, we can draw them on image
:
# draw the bounding box of the ArUCo detection cv2.line(image, topLeft, topRight, (0, 255, 0), 2) cv2.line(image, topRight, bottomRight, (0, 255, 0), 2) cv2.line(image, bottomRight, bottomLeft, (0, 255, 0), 2) cv2.line(image, bottomLeft, topLeft, (0, 255, 0), 2) # compute and draw the center (x, y)-coordinates of the ArUco # marker cX = int((topLeft[0] + bottomRight[0]) / 2.0) cY = int((topLeft[1] + bottomRight[1]) / 2.0) cv2.circle(image, (cX, cY), 4, (0, 0, 255), -1) # draw the ArUco marker ID on the image cv2.putText(image, str(markerID), (topLeft[0], topLeft[1] - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) print("[INFO] ArUco marker ID: {}".format(markerID)) # show the output image cv2.imshow("Image", image) cv2.waitKey(0)
Lines 80-83 draw the bounding box of the ArUco tag on our
using image
cv2.line
calls.
We then compute the center (x, y)-coordinates of the ArUco marker and draw the center on the image
via a call to cv2.circle
(Lines 87-89).
Our final visualization step is to draw the markerID
on the image
and print it to our terminal (Lines 92-95).
The final output visualization is displayed to our screen on Lines 98 and 99.
OpenCV ArUco marker detection results
Let’s put our OpenCV ArUco detector to work!
Use the “Downloads” section of this tutorial to download the source code and example images.
From there, you can execute the following command:
$ python detect_aruco_image.py --image images/example_01.png --type DICT_5X5_100 [INFO] loading image... [INFO] detecting 'DICT_5X5_100' tags... [INFO] ArUco marker ID: 42 [INFO] ArUco marker ID: 24 [INFO] ArUco marker ID: 70 [INFO] ArUco marker ID: 66 [INFO] ArUco marker ID: 87
This image contains the ArUco markers that we generated in last week’s blog post. I took each of the five individual ArUco markers and constructed a montage of them in a single image.
As Figure 3 shows, we’ve been able to correctly detect each of the ArUco markers and extract their IDs.
Let’s try a different image, this one containing ArUco markers not generated by us:
$ python detect_aruco_image.py --image images/example_02.png --type DICT_ARUCO_ORIGINAL [INFO] loading image... [INFO] detecting 'DICT_ARUCO_ORIGINAL' tags... [INFO] ArUco marker ID: 241 [INFO] ArUco marker ID: 1007 [INFO] ArUco marker ID: 1001 [INFO] ArUco marker ID: 923
Figure 4 displays the results of our OpenCV ArUco detector. As you can see, I have detected each of the four ArUco markers on my Pantone color matching card (which we’ll be using in a number of upcoming tutorials, so get used to seeing it).
Looking at the command line arguments to the above script, you may be wondering:
“Hey Adrian, how did you know to use
DICT_ARUCO_ORIGINAL
and not some other ArUco dictionary.”
The short answer is that I didn’t … at least, not initially.
I actually have a “secret weapon” up my sleeve. I’ve put together a Python script that can automatically infer ArUco marker type, even if I don’t know what type of marker is in an image.
I’ll be sharing that script with you next week, so be on the lookout for it.
Detecting ArUco markers in real-time video streams with OpenCV
In our previous section we learned how to detect ArUco markers in images …
… but is it possible to detect ArUco markers in real-time video streams?
The answer is yes, it absolutely is — and I’ll be showing you how to do so in this section.
Open up the detect_aruco_video.py
file in your project directory structure, and let’s get to work:
# import the necessary packages from imutils.video import VideoStream import argparse import imutils import time import cv2 import sys
Lines 2-7 import our required Python packages. These imports are identical to our previous script, with two exceptions:
: Used to access our webcamVideoStream
: Inserts a small delay, allowing our camera sensor to warm uptime
Let’s now parse our command line arguments:
# construct the argument parser and parse the arguments ap = argparse.ArgumentParser() ap.add_argument("-t", "--type", type=str, default="DICT_ARUCO_ORIGINAL", help="type of ArUCo tag to detect") args = vars(ap.parse_args())
We only need a single command line argument here, --type
, which is the type of ArUco tags we are going to detect in our video stream.
Next we define the ARUCO_DICT
, used to map the --type
to OpenCV’s unique ArUco tag type:
# define names of each possible ArUco tag OpenCV supports ARUCO_DICT = { "DICT_4X4_50": cv2.aruco.DICT_4X4_50, "DICT_4X4_100": cv2.aruco.DICT_4X4_100, "DICT_4X4_250": cv2.aruco.DICT_4X4_250, "DICT_4X4_1000": cv2.aruco.DICT_4X4_1000, "DICT_5X5_50": cv2.aruco.DICT_5X5_50, "DICT_5X5_100": cv2.aruco.DICT_5X5_100, "DICT_5X5_250": cv2.aruco.DICT_5X5_250, "DICT_5X5_1000": cv2.aruco.DICT_5X5_1000, "DICT_6X6_50": cv2.aruco.DICT_6X6_50, "DICT_6X6_100": cv2.aruco.DICT_6X6_100, "DICT_6X6_250": cv2.aruco.DICT_6X6_250, "DICT_6X6_1000": cv2.aruco.DICT_6X6_1000, "DICT_7X7_50": cv2.aruco.DICT_7X7_50, "DICT_7X7_100": cv2.aruco.DICT_7X7_100, "DICT_7X7_250": cv2.aruco.DICT_7X7_250, "DICT_7X7_1000": cv2.aruco.DICT_7X7_1000, "DICT_ARUCO_ORIGINAL": cv2.aruco.DICT_ARUCO_ORIGINAL, "DICT_APRILTAG_16h5": cv2.aruco.DICT_APRILTAG_16h5, "DICT_APRILTAG_25h9": cv2.aruco.DICT_APRILTAG_25h9, "DICT_APRILTAG_36h10": cv2.aruco.DICT_APRILTAG_36h10, "DICT_APRILTAG_36h11": cv2.aruco.DICT_APRILTAG_36h11 }
Refer to the “Detecting ArUco markers with OpenCV in images” section above for a more detailed review of this code block.
We can now load our ArUco dictionary:
# verify that the supplied ArUCo tag exists and is supported by # OpenCV if ARUCO_DICT.get(args["type"], None) is None: print("[INFO] ArUCo tag of '{}' is not supported".format( args["type"])) sys.exit(0) # load the ArUCo dictionary and grab the ArUCo parameters print("[INFO] detecting '{}' tags...".format(args["type"])) arucoDict = cv2.aruco.Dictionary_get(ARUCO_DICT[args["type"]]) arucoParams = cv2.aruco.DetectorParameters_create() # initialize the video stream and allow the camera sensor to warm up print("[INFO] starting video stream...") vs = VideoStream(src=0).start() time.sleep(2.0)
Lines 43-46 check to see if the ArUco tag --type
exists in our ARUCO_DICT
. If not, we exit the script.
Otherwise, we load the arucoDict
and grab the arucoParams
for the detector (Lines 50 and 51).
From there, we start our VideoStream
and allow our camera sensor to warm up (Lines 55 and 56).
We’re now ready to loop over frames from our video stream:
# loop over the frames from the video stream while True: # grab the frame from the threaded video stream and resize it # to have a maximum width of 1000 pixels frame = vs.read() frame = imutils.resize(frame, width=1000) # detect ArUco markers in the input frame (corners, ids, rejected) = cv2.aruco.detectMarkers(frame, arucoDict, parameters=arucoParams)
Line 62 grabs a
from our video stream, which we then resize to have a width of 1000 pixels.frame
We then apply the cv2.aruco.detectMarkers
function to detect ArUco tags in the current frame
.
Let’s now parse the results of the ArUco tag detection:
# verify *at least* one ArUco marker was detected if len(corners) > 0: # flatten the ArUco IDs list ids = ids.flatten() # loop over the detected ArUCo corners for (markerCorner, markerID) in zip(corners, ids): # extract the marker corners (which are always returned # in top-left, top-right, bottom-right, and bottom-left # order) corners = markerCorner.reshape((4, 2)) (topLeft, topRight, bottomRight, bottomLeft) = corners # convert each of the (x, y)-coordinate pairs to integers topRight = (int(topRight[0]), int(topRight[1])) bottomRight = (int(bottomRight[0]), int(bottomRight[1])) bottomLeft = (int(bottomLeft[0]), int(bottomLeft[1])) topLeft = (int(topLeft[0]), int(topLeft[1]))
The above code block is essentially identical to the one from our
script.detect_aruco_image.py
Here we are:
- Verifying that at least one ArUco tag was detected (Line 70)
- Flattening the ArUco
ids
list (Line 72) - Looping over all
corners
andids
together (Line 75) - Extracting the marker corners in top-left, top-right, bottom-right, and bottom-left order (Lines 79 and 80)
- Converting the corner (x, y)-coordinates from NumPy array data types to Python integers such that we can draw the coordinates using OpenCV’s drawing functions (Lines 83-86)
The final step here is to draw our ArUco tag bounding boxes just as we did in
:detect_aruco_image.py
# draw the bounding box of the ArUCo detection cv2.line(frame, topLeft, topRight, (0, 255, 0), 2) cv2.line(frame, topRight, bottomRight, (0, 255, 0), 2) cv2.line(frame, bottomRight, bottomLeft, (0, 255, 0), 2) cv2.line(frame, bottomLeft, topLeft, (0, 255, 0), 2) # compute and draw the center (x, y)-coordinates of the # ArUco marker cX = int((topLeft[0] + bottomRight[0]) / 2.0) cY = int((topLeft[1] + bottomRight[1]) / 2.0) cv2.circle(frame, (cX, cY), 4, (0, 0, 255), -1) # draw the ArUco marker ID on the frame cv2.putText(frame, str(markerID), (topLeft[0], topLeft[1] - 15), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # show the output frame cv2.imshow("Frame", frame) key = cv2.waitKey(1) & 0xFF # if the `q` key was pressed, break from the loop if key == ord("q"): break # do a bit of cleanup cv2.destroyAllWindows() vs.stop()
Our visualization steps include:
- Drawing the outlines of the ArUco tag on the
frame
(Lines 89-92) - Drawing the center of the ArUco tag (Lines 96-98)
- Displaying the ID of the detected ArUco tag (Lines 101-104)
Finally, we display the output frame
to our screen.
If the q
key is pressed while the window opened by OpenCV is active, we break
from the script and cleanup our video pointers.
OpenCV ArUco video detection results
Ready to apply ArUco detection to real-time video streams?
Start by using the “Downloads” section of this tutorial to download the source code and example images.
From there, pop open a shell, and execute the following command:
$ python detect_aruco_video.py
As you can see, I’m easily able to detect the ArUco markers in real-time video.
What's next? We recommend PyImageSearch University.
86 total classes • 115+ hours of on-demand code walkthrough videos • Last updated: October 2024
★★★★★ 4.84 (128 Ratings) • 16,000+ Students Enrolled
I strongly believe that if you had the right teacher you could master computer vision and deep learning.
Do you think learning computer vision and deep learning has to be time-consuming, overwhelming, and complicated? Or has to involve complex mathematics and equations? Or requires a degree in computer science?
That’s not the case.
All you need to master computer vision and deep learning is for someone to explain things to you in simple, intuitive terms. And that’s exactly what I do. My mission is to change education and how complex Artificial Intelligence topics are taught.
If you're serious about learning computer vision, your next stop should be PyImageSearch University, the most comprehensive computer vision, deep learning, and OpenCV course online today. Here you’ll learn how to successfully and confidently apply computer vision to your work, research, and projects. Join me in computer vision mastery.
Inside PyImageSearch University you'll find:
- ✓ 86 courses on essential computer vision, deep learning, and OpenCV topics
- ✓ 86 Certificates of Completion
- ✓ 115+ hours of on-demand video
- ✓ Brand new courses released regularly, ensuring you can keep up with state-of-the-art techniques
- ✓ Pre-configured Jupyter Notebooks in Google Colab
- ✓ Run all code examples in your web browser — works on Windows, macOS, and Linux (no dev environment configuration required!)
- ✓ Access to centralized code repos for all 540+ tutorials on PyImageSearch
- ✓ Easy one-click downloads for code, datasets, pre-trained models, etc.
- ✓ Access on mobile, laptop, desktop, etc.
Summary
In this tutorial you learned how to detect ArUco markers in images and real-time video streams using OpenCV and Python.
Detecting ArUco markers with OpenCV is a three-step process:
- Set what ArUco dictionary you are using.
- Define the parameters to the ArUco detector (typically the default options suffice).
- Apply the ArUco detector with OpenCV’s
function.cv2.aruco.detectMarkers
OpenCV’s ArUco marker is extremely fast and, as our results showed, is capable of detecting ArUco markers in real-time.
Feel free to use this code as a starting point when using ArUco markers in your own computer vision pipelines.
However, let’s say you are developing a computer vision project to automatically detect ArUco markers in images, but you don’t know what marker type is being used, and therefore, you can’t explicitly set the ArUco marker dictionary — what do you do then?
How are you going to detect ArUco markers if you don’t know what marker type is being used?
I’ll be answering that exact question in next week’s blog post.
To download the source code to this post (and be notified when future tutorials are published here on PyImageSearch), simply enter your email address in the form below!
Download the Source Code and FREE 17-page Resource Guide
Enter your email address below to get a .zip of the code and a FREE 17-page Resource Guide on Computer Vision, OpenCV, and Deep Learning. Inside you'll find my hand-picked tutorials, books, courses, and libraries to help you master CV and DL!
Comment section
Hey, Adrian Rosebrock here, author and creator of PyImageSearch. While I love hearing from readers, a couple years ago I made the tough decision to no longer offer 1:1 help over blog post comments.
At the time I was receiving 200+ emails per day and another 100+ blog post comments. I simply did not have the time to moderate and respond to them all, and the sheer volume of requests was taking a toll on me.
Instead, my goal is to do the most good for the computer vision, deep learning, and OpenCV community at large by focusing my time on authoring high-quality blog posts, tutorials, and books/courses.
If you need help learning computer vision and deep learning, I suggest you refer to my full catalog of books and courses — they have helped tens of thousands of developers, students, and researchers just like yourself learn Computer Vision, Deep Learning, and OpenCV.
Click here to browse my full catalog.