Title: Generating ArUco markers with OpenCV and Python - PyImageSearch

URL Source: https://pyimagesearch.com/2020/12/14/generating-aruco-markers-with-opencv-and-python/

Published Time: 2020-12-14T15:00:00+00:00

Markdown Content:
In this tutorial you will learn how to generate ArUco markers using OpenCV and Python.

![Image 1](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20456'%3E%3C/svg%3E)

Today’s blog post is part one in our three-part series on ArUCo markers and fiducials:

1.  _Generating ArUco markers with OpenCV and Python_ (today’s post)
2.  _Detecting ArUco markers in images and video with OpenCV_ (next week’s tutorial)
3.  _Automatically determining ArUco marker type with OpenCV_ (blog post two weeks from now)

Similar to [AprilTags](https://pyimagesearch.com/2020/11/02/apriltag-with-python/), ArUco markers are 2D binary patterns that computer vision algorithms can easily detect.

Typically, we use AprilTags and ArUco markers for:

*   Camera calibration
*   Object size estimation
*   Measuring the distance between camera and object
*   3D position
*   Object orientation
*   Robotics and autonomous navigation
*   _etc._

**The primary benefits of using ArUco markers over AprilTags include:**

1.  ArUco markers are built into the OpenCV library via the `cv2.aruco` submodule (i.e., we don’t need additional Python packages).
2.  The OpenCV library itself can generate ArUco markers via the `cv2.aruco.drawMarker` function.
3.  There are online ArUco generators that we can use if we don’t feel like coding (unlike AprilTags where no such generators are easily found).
4.  There are ROS (Robot Operating System) implementations of ArUco markers.
5.  And from an implementation perspective, ArUco marker detections tend to be more accurate, even when using the default parameters.

In this introductory series to ArUco markers, you will learn how to generate them, detect them in images and real-time video streams, and even how to _automatically_ detect the type of ArUco marker in an image (even if you _don’t_ know what type of marker is being used).

We’ll then take this knowledge and use ArUco markers in our own computer vision and image processing pipelines in future PyImageSearch tutorials.

**_Updated 25 Nov 2021 with a note on using your ArUco markers on a white background._**

**To learn how to generate ArUco markers with OpenCV and Python, _just keep reading._**

![Image 2](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20128%20128'%3E%3C/svg%3E)

#### Looking for the source code to this post?

[Jump Right To The Downloads Section](#download-the-code)

In the first part of this tutorial, we’ll discuss ArUco markers, including what they are and why we may want to use them in our computer vision and image processing pipelines.

We’ll then discuss how to generate ArUco markers using OpenCV and Python. I’ll also provide a few example websites that will generate ArUco markers for you if you don’t feel like writing code to generate them (although the code implementation itself is _dead simple_).

From there we’ll review our project directory structure and then implement a Python script named `opencv_generate_aruco.py`, which will generate a specific ArUco image and then save it to disk.

We’ll wrap up this tutorial with a discussion of our results.

### **What are ArUco markers?**

![Image 3](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20640%20480'%3E%3C/svg%3E)

**Figure 1:** ArUco tags are fiducial markers, similar to AprilTags ([image source](https://docs.opencv.org/master/d5/dae/tutorial_aruco_detection.html)).

I’ve already covered the fundamentals of fiducial markers, AprilTags, and ArUco markers [in this previous tutorial](https://pyimagesearch.com/2020/11/02/apriltag-with-python/), so I’m not going to rehash the basics here.

If you are new to fiducial markers and need to understand why they are important, how they work, or when we would want to use them in a computer vision/image processing pipeline, I suggest you give my [AprilTag tutorial](https://pyimagesearch.com/2020/11/02/apriltag-with-python/) a read.

From there you should come back here and finish reading this tutorial on ArUco markers with OpenCV.

### **How can we generate ArUco markers with OpenCV and Python?**

![Image 4](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20411'%3E%3C/svg%3E)

**Figure 2:** We can use the `cv2.aruco.drawMarker` function to generate and draw ArUco markers using OpenCV and Python.

**The OpenCV library has a built-in ArUco marker generator through its** `cv2.aruco.drawMarker` **function.**

The parameters to this function include:

*   `` `dictionary` ``: The ArUco dictionary specifying the type of markers we’re using
*   `` `id` ``: The ID of the marker we’ll be drawing (has to be a valid ID In the ArUco `dictionary`)
*   `` `sidePixels` ``: Size in pixels of the (square) image that we’ll be drawing the ArUco marker on
*   `` `borderBits` ``: Width and height (in pixels) of the border

The `` `drawMarker` `` function then returns the output image with the ArUco marker drawn on it.

As you’ll see later in this tutorial, using the function is fairly straightforward in practice. The steps required include:

1.  Select which ArUco dictionary you want to use
2.  Specify which ArUco ID you’re going to draw
3.  Allocate memory for your output ArUco image (in pixels)
4.  Use the `` `drawMarker` `` function to draw the ArUco tag
5.  Draw the ArUco marker itself

That said, if you don’t want to write any code, you could leverage an online ArUco generator.

### **Are there online ArUco marker generators?**

![Image 5](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20392'%3E%3C/svg%3E)

**Figure 3:** If you don’t wish to use OpenCV to generate ArUco markers, you can use online ArUco generators, [such as this one](https://chev.me/arucogen/), developed by Oleg Kalachev.

If you don’t feel like writing some code, or are simply in a hurry, there _are_ online ArUco marker generators that you can use.

My favorite is [this one, put together by Oleg Kalachev.](https://chev.me/arucogen/)

All you have to do is:

1.  Select the ArUco dictionary you want to use
2.  Enter the marker ID
3.  Specify the marker size (in millimeters)

From there you can save the ArUco marker as an SVG file or PDF, print it, and then use it in your own OpenCV and computer vision applications.

### **What are ArUco dictionaries?**

![Image 6](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20700%20380'%3E%3C/svg%3E)

**Figure 4:** ArUco tags come in different types and flavors called “dictionaries” ([image source](https://stackoverflow.com/questions/47899071/cv2-aruco-detectmarkers-doesnt-detect-markers-in-python)).

So far in this tutorial, I’ve mentioned the concept of an “ArUco dictionary”, but what exactly _is_ an ArUco dictionary? And what role does it play in ArUco generation and detection?

**The short answer is that an ArUco dictionary specifies the type of ArUco marker we are generating and detecting. Without the dictionary we would be unable to generate and detect these markers.**

Imagine you are kidnapped, blindfolded, put on a plane, and dropped in a random country in the world. You are then given a notebook containing the secret to your release, but it’s written in a language you have never seen before in your life.

One captor takes pity on you and gives you a dictionary to help you translate what you see in your book.

Using the dictionary you are able to translate the document, reveal the secret, and escape with your life intact.

**But without that dictionary you would have _never_ been able to escape.** Just as you needed that dictionary to translate the secret to your escape, we must know what type of ArUco markers we are working with in order to generate and detect them.

### **Types of ArUco dictionaries in OpenCV**

![Image 7](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20400'%3E%3C/svg%3E)

**Figure 5:** Sample ArUco tags generated by OpenCV ([image source](https://docs.opencv.org/master/d5/dae/tutorial_aruco_detection.html)).

**There are 21 different ArUco dictionaries built into the OpenCV library.** I have listed them here in the following Python dictionary:

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 majority of these dictionaries follow a specific naming convention, `cv2.aruco.DICT_NxN_M`, with an _NxN_ size followed by an integer value, _M_ — **_but what do these values mean?_**

The _NxN_ value is the 2D _bit size_ of the ArUco marker. For example, for a _6×6_ marker we have a total of 36 bits.

The integer _M_ following the grid size specifies the total number of unique ArUco IDs that can be generated with that dictionary.

To make the naming convention more concrete, consider the following examples:

The `cv2.aruco.DICT_4X4_50` value implies that we want to generate a binary _4×4_ square AruCo marker. We’ll be able to generate 50 unique ArUco marker IDs using this dictionary.

The value `cv2.aruco.DICT_7X7_250` implies that we’ll be creating a binary _7×7_ ArUco marker and that there will be 250 unique ArUco marker IDs in the dictionary.

**So, how do you decide on which ArUco marker dictionary you want to use?**

1.  **To start, consider how many unique values in the dictionary you need.** Only need a small handful of markers? Choose a dictionary that has a smaller unique number of values then. Need to detect a lot of markers? Select a dictionary with more unique ID values. Essentially, pick a dictionary that has the _bare minimum_ number of IDs you need — **don’t take more than what you actually need.**
2.  **Look at your input image/video resolution size.** Keep in mind that the larger your grid size gets, the larger the ArUco marker will need to be when captured by your camera. If you have a _large_ grid but a _low resolution_ input, then the marker may be undetectable (or may be misread).
3.  **Consider the inter-marker distance.** OpenCV’s ArUco detection implementation utilizes error correction to improve the accuracy and robustness of marker detection. The error correction hinges on the concept of _inter-marker distance._ **Smaller dictionary sizes with larger _NxN_ marker sizes increase the inter-marker distance, thereby making them less prone to false readings.**

**Ideal settings for an ArUco dictionary include:**

1.  A low number of unique ArUco IDs that need to be generated and read
2.  High-quality image input containing the ArUco markers that will be detected
3.  A larger _NxN_ grid size, balanced with a low number of unique ArUco IDs such that the inter-marker distance can be used to correct misread markers

[Be sure to refer to the OpenCV documentation for more details on ArUco dictionaries.](https://docs.opencv.org/master/d5/dae/tutorial_aruco_detection.html)

_**Note:** I’ll wrap up this section by saying that the final few entries in the_ `` `ARUCO_DICT` `` _variable indicate that we can generate and detect [AprilTags](https://pyimagesearch.com/2020/11/02/apriltag-with-python/) as well!_

### **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 with OpenCV, I _highly recommend_ that you read my [_pip install OpenCV_ guide](https://pyimagesearch.com/2018/09/19/pip-install-opencv/)** — it will have you up and running in a matter of minutes.

### **Having problems configuring your development environment?**

[![Image 8: Screenshot of PyImageSearch Plus and Google Colab Notebook with Jupyter logo overlaid](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20500%20334'%3E%3C/svg%3E)](https://pyimagesearch.com/pyimagesearch-plus/)

**Figure 6:** Having trouble configuring your dev environment? Want access to pre-configured Jupyter Notebooks running on Google Colab? Be sure to join [PyImageSearch Plus](https://pyimagesearch.com/pyimagesearch-plus/) — you’ll be up and running with this tutorial in a matter of minutes.

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](https://pyimagesearch.com/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 start generating ArUco markers with OpenCV, let’s first review our project directory structure.

Use the **_“Downloads”_** section of this tutorial to download the source code and example images to this tutorial. From there, let’s inspect what we have:

$ tree . --dirsfirst
.
├── tags
│   ├── DICT\_5X5\_100\_id24.png
│   ├── DICT\_5X5\_100\_id42.png
│   ├── DICT\_5X5\_100\_id66.png
│   ├── DICT\_5X5\_100\_id70.png
│   └── DICT\_5X5\_100\_id87.png
└── opencv\_generate\_aruco.py

1 directory, 6 files

As the name suggests, the `opencv_generate_aruco.py` script is used to generate ArUco markers. The resulting ArUco markers are then saved to task in the `tags/` directory.

Next week we’ll learn how to actually _detect_ and _recognize_ these (and other) ArUco markers.

### **Implementing our ArUco marker generation script with OpenCV and Python**

Let’s learn how to generate ArUco markers with OpenCV.

Open up the `opencv_generate_aruco.py` file in your project directory structure, and insert the following code:

\# import the necessary packages
import numpy as np
import argparse
import cv2
import sys

Here we import our required Python packages. We’ll use NumPy to allocate an empty NumPy array to store our generated ArUco tag, while `cv2` (our OpenCV bindings), will generate the ArUco tag itself.

Let’s move on to our command line arguments:

\# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add\_argument("-o", "--output", required=True,
	help="path to output image containing ArUCo tag")
ap.add\_argument("-i", "--id", type=int, required=True,
	help="ID of ArUCo tag to generate")
ap.add\_argument("-t", "--type", type=str,
	default="DICT\_ARUCO\_ORIGINAL",
	help="type of ArUCo tag to generate")
args = vars(ap.parse\_args())

We have three command line arguments to our script, two required and one optional:

1.  `` `--output` ``: The path to the output image where we’ll save the generated ArUco tag
2.  `` `--id` ``: The unique identifier of the ArUco tag — this ID _must_ be a valid ID in the ArUco dictionary used to generate the tag
3.  `--type`: The name of the ArUco dictionary we’ll use to generate the tag; by default, we’ll use the original ArUco dictionary

With our command line arguments parsed, we can move on to define our `` `ARUCO_DICT` ``, which contains all possible ArUco dictionaries that OpenCV supports:

\# 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
}

I reviewed the ArUco dictionaries in the _“Types of ArUco dictionaries in OpenCV”_ section above, so be sure to refer there if you would like additional explanation on this code block.

With our `ARUCO_DICT` mappings defined, let’s now load the ArUco dictionary using OpenCV:

\# 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
arucoDict = cv2.aruco.Dictionary\_get(ARUCO\_DICT\[args\["type"\]\])

**Line 45** makes a check to see if the ArUco dictionary `--type` exists in our `ARUCO_DICT`.

If not, we report that the supplied `--type` does not exist in the `ARUCO_DICT` and then gracefully exit the script.

Otherwise, we load the ArUco dictionary by looking up the ArUco dictionary `--type` in our `ARUCO_DICT` and then passing this value into the `cv2.aruco.Dictionary_get` function.

The `cv2.aruco.Dictionary_get` function returns all information OpenCV needs to draw our ArUco tags.

Speaking of drawing the tag, let’s go ahead and do that now:

\# allocate memory for the output ArUCo tag and then draw the ArUCo
# tag on the output image
print("\[INFO\] generating ArUCo tag type '{}' with ID '{}'".format(
	args\["type"\], args\["id"\]))
tag = np.zeros((300, 300, 1), dtype="uint8")
cv2.aruco.drawMarker(arucoDict, args\["id"\], 300, tag, 1)

# write the generated ArUCo tag to disk and then display it to our
# screen
cv2.imwrite(args\["output"\], tag)
cv2.imshow("ArUCo Tag", tag)
cv2.waitKey(0)

**Line 57** allocates memory for a _300x300x1_ grayscale image. We use grayscale here, since an ArUco tag is a _binary_ image.

Additionally, you can use whatever image dimensions you wish. I hardcoded 300 pixels here, but again, feel free to increase/decrease resolution as you see fit for your own project.

**Line 58** then draws the ArUco tag using OpenCV’s `` `cv2.aruco.drawMarker` `` function. This method requires five arguments:

1.  `arucoDict`: The ArUco dictionary loaded by `cv2.aruco.Dictionary_get`. This function tells OpenCV which ArUco dictionary we are using, how to draw the tags, etc.
2.  `` `id` ``: The ID of the ArUco tag we are drawing. This ID **_must_** be a valid tag ID in `arucoDict`.
3.  `` `300` ``: The size of the ArUco tag that will be drawn. This value should match the width/height of the NumPy array we initialized on **Line 57**.
4.  `` `tag` ``: The NumPy array that we are drawing the ArUco tag on.
5.  `` `1` ``: The number of “border bits” to pad the tag with. If we generate a _5×5_ tag, then setting `borderBits=1`will output a _6×6_ image with a 1 bit border surrounding the _5×5_ region, making the tag easier to detect and read. Typically you should set `borderBits=1`.

Finally, **Lines 62-64** write the generated ArUco tag to disk via the `` `--output` `` command line argument and then display the ArUco tag to our screen.

### **OpenCV ArUco generation results**

We are now ready to generate ArUco markers with OpenCV!

Start by using the **_“Downloads”_** section of this tutorial to download the source code and example images.

From there, open up a terminal, and execute the following command:

$ python opencv\_generate\_aruco.py --id 24 --type DICT\_5X5\_100 \\
	--output tags/DICT\_5X5\_100\_id24.png
\[INFO\] generating ArUCo tag type 'DICT\_5X5\_100' with ID '24'

![Image 9](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E)

**Figure 7:** Generating an ArUco tag with OpenCV. This tag uses the _5×5_ dictionary with 100 possible unique IDs. This particular tag has an ID of “24”.

Here we have generated a _5×5_ ArUco marker using a dictionary that allows for 100 unique ArUco IDs. This marker has an ID value of `24`.

Let’s create another image using the same dictionary, but with a value of `42`:

$ python opencv\_generate\_aruco.py --id 42 --type DICT\_5X5\_100 \\
	--output tags/DICT\_5X5\_100\_id42.png
\[INFO\] generating ArUCo tag type 'DICT\_5X5\_100' with ID '42'

![Image 10](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E)

**Figure 8:** ArUco tag generated with OpenCV. This tag has an ID of “42” and belongs to the _5×5_ dictionary which supports 100 unique IDs.

Again, we use the same `cv2.aruco.DICT_5X5_100` dictionary, but this time creating an ArUco marker with an ID of `42`.

Let’s generate another marker:

$ python opencv\_generate\_aruco.py --id 66 --type DICT\_5X5\_100 \\
	--output tags/DICT\_5X5\_100\_id66.png
\[INFO\] generating ArUCo tag type 'DICT\_5X5\_100' with ID '66'

![Image 11](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E)

**Figure 9:** Using OpenCV to generate ArUco tags. This tag has a unique ID of “66”.

The marker in **Figure 9** has a value of `66`.

Now let’s generate an ArUco marker with an ID of an `87`:

$ python opencv\_generate\_aruco.py --id 87 --type DICT\_5X5\_100 \\
	--output tags/DICT\_5X5\_100\_id87.png
\[INFO\] generating ArUCo tag type 'DICT\_5X5\_100' with ID '87'

![Image 12](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E)

**Figure 10:** ArUco tag generation with OpenCV — here we’ve produced an ArUco tag with an ID of “87”. This tag belongs to the same dictionary as the others.

In **Figure 10** you can see our _5×5_ ArUco marker with an ID of `87`.

The final example here generates an ArUco marker with a value of `70`:

$ python opencv\_generate\_aruco.py --id 70 --type DICT\_5X5\_100 \\
	--output tags/DICT\_5X5\_100\_id70.png
\[INFO\] generating ArUCo tag type 'DICT\_5X5\_100' with ID '70'

![Image 13](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E)

**Figure 11:** ArUco tag generation with OpenCV, resulting in an ArUco tag with an ID of “70”.

At this point we’ve generated five ArUco markers, a montage of which I’ve created below:

![Image 14](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20600%20400'%3E%3C/svg%3E)

**Figure 12:** A montage of ArUco tags we’ve generated in this tutorial.

But so what? The markers don’t do much use just sitting on our disk.

**How can we take these markers and then _detect_ them in images and real-time video streams?**

I’ll be addressing that very question in next week’s tutorial.

Stay tuned.

**One final note in case you want to create ArUco markers on your own, you need to put the ArUco markers in this tutorial on a white background to ensure the code works properly in the next blog post.**

**If you don’t have a white background for your ArUco markers, I can’t guarantee will work properly.**

### What's next? We recommend [PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend).

**Course information:**  
84 total classes • 114+ hours of on-demand code walkthrough videos • Last updated: February 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:**

*   ✓ **84 courses** on essential computer vision, deep learning, and OpenCV topics
*   ✓ **84 Certificates** of Completion
*   ✓ **114+ 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_ 536+ tutorials** on PyImageSearch
*   ✓ **Easy one-click downloads** for code, datasets, pre-trained models, etc.
*   ✓ **Access** on mobile, laptop, desktop, etc.

[Click here to join PyImageSearch University](https://pyimagesearch.com/pyimagesearch-university/?utm_source=blogPost&utm_medium=bottomBanner&utm_campaign=What%27s%20next%3F%20I%20recommend)

**Summary**
-----------

In this tutorial you learned how to generate ArUco markers with OpenCV and Python.

Working with ArUco tags with OpenCV is dead simple due to the handy `` `cv2.aruco` `` submodule built into the OpenCV library (i.e., you don’t need any additional Python packages or dependencies to detect ArUco tags).

Now that we’ve actually _generated_ some ArUco tags, next week I will show you how to take the generated tags and actually _detect_ them in images and real-time video streams.

By the end of this series of tutorials, you will have the knowledge necessary to confidently and successfully work with ArUco tags in your own OpenCV projects.

**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!_**

![Image 15](data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20410%20567'%3E%3C/svg%3E)

#### 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!