OpenCV provides a module called "ArUco" that can easily handle AR markers.
This article shows basic usage of ArUco.
Contents
- Preparation for using ArUco
- How to generate markers using ArUco
- How to detect markers using ArUco
- How to extract coordinates of a marker using ArUco
- How to overlay marker IDs and video
sponsored link
Preparation for using ArUco : Install OpenCV-contrib.
ArUco module can be used by installing OpenCV-contrib, an extension module of OpenCV.
OpenCV-contrib can be installed with following command.
$ pip install opencv-contrib-python
Versions of OpenCV and OpenCV-contrib must be the same.
Specify version and install OpenCV-contrib.
This is an example specifying version 3.4.5.20.
$ pip install opencv-contrib-python==3.4.5.20
If you want to install OpenCV-contrib on Raspberry Pi, please refer to this page.
How to install OpenCV on Raspberry Pi
sponsored link
How to generate markers using ArUco
First, I show how to generate markers.
In the following sample code, marker images are generated and saved.
### Generate markers
import cv2
from cv2 import aruco
import os
### --- parameter --- ###
# Save location
dir_mark = r'C:\test'
# Parameter
num_mark = 20 #Number of markers
size_mark = 500 #Size of markers
### --- marker images are generated and saved --- ###
# Call marker type
dict_aruco = aruco.Dictionary_get(aruco.DICT_4X4_50)
for count in range(num_mark) :
id_mark = count
img_mark = aruco.drawMarker(dict_aruco, id_mark, size_mark)
if count < 10 :
img_name_mark = 'mark_id_0' + str(count) + '.jpg'
else :
img_name_mark = 'mark_id_' + str(count) + '.jpg'
path_mark = os.path.join(dir_mark, img_name_mark)
cv2.imwrite(path_mark, img_mark)
Output
Here are the generated markers.
The 20 marker images were saved in test folder.
sponsored link
How to detect markers using ArUco
I show how to detect markers.
In the following sample code, detected marker IDs is returned.
### Detect markers
import cv2
from cv2 import aruco
import numpy as np
import time
class MarkSearch :
dict_aruco = aruco.Dictionary_get(aruco.DICT_4X4_50)
parameters = aruco.DetectorParameters_create()
def __init__(self, cameraID):
self.cap = cv2.VideoCapture(cameraID)
def get_markID(self):
"""
Obtain marker id list from still image
"""
ret, frame = self.cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, dict_aruco, parameters=parameters)
list_ids = np.ravel(ids)
return list_ids
if __name__ == "__main__" :
import cv2
from cv2 import aruco
import numpy as np
import time
dict_aruco = aruco.Dictionary_get(aruco.DICT_4X4_50)
parameters = aruco.DetectorParameters_create()
### --- parameter --- ###
cameraID = 0
cam0_mark_search = MarkSearch(cameraID)
try:
while True:
print(' ----- get_markID ----- ')
print(cam0_mark_search.get_markID())
time.sleep(0.5)
except KeyboardInterrupt:
cam0_mark_search.cap.release()
Output
List of markers displayed on the camera is returned.
For example, When ID1~5 markers are detected, this is output.
[5 1 2 3 4]
Supplementary explanation
ID is extracted from still image converted to gray image.
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, dict_aruco, parameters=parameters)
Marker IDs are stored in "ids".
"ids" is difficult to use, as shown below.
[[1]
[3]
[4]
[5]
[2]]
Therefore, it is converted to one-dimensional list.
list_ids = np.ravel(ids)
sponsored link
How to extract coordinates of a marker using ArUco
I show how to extract coordinates of a marker.
In the following sample code, coordinates are returned in list when specified marker is detected.
### Extract coordinates of a marker
import cv2
from cv2 import aruco
import numpy as np
import time
class MarkSearch :
dict_aruco = aruco.Dictionary_get(aruco.DICT_4X4_50)
parameters = aruco.DetectorParameters_create()
def __init__(self, cameraID):
self.cap = cv2.VideoCapture(cameraID)
def get_mark_coordinate(self, num_id):
"""
Obtain marker id list from still image
"""
ret, frame = self.cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, dict_aruco, parameters=parameters)
### If marker of num_id is detected ###
if num_id in np.ravel(ids) :
index = np.where(ids == num_id)[0][0] #Extract index of num_id
cornerUL = corners[index][0][0]
cornerUR = corners[index][0][1]
cornerBR = corners[index][0][2]
cornerBL = corners[index][0][3]
center = [ (cornerUL[0]+cornerBR[0])/2 , (cornerUL[1]+cornerBR[1])/2 ]
print('Upper left : {}'.format(cornerUL))
print('Upper right : {}'.format(cornerUR))
print('Lower right : {}'.format(cornerBR))
print('Lower Left : {}'.format(cornerBL))
print('Center : {}'.format(center))
print(corners[index])
return center
return None
if __name__ == "__main__" :
import cv2
from cv2 import aruco
import numpy as np
import time
dict_aruco = aruco.Dictionary_get(aruco.DICT_4X4_50)
parameters = aruco.DetectorParameters_create()
### --- parameter --- ###
cameraID = 0
cam0_mark_search = MarkSearch(cameraID)
markID = 1
try:
while True:
print(' ----- get_mark_coordinate ----- ')
print(cam0_mark_search.get_mark_coordinate(markID))
time.sleep(0.5)
except KeyboardInterrupt:
cam0_mark_search.cap.release()
Output
Coordinates are returned in list when specified marker is detected.
For example, if mark with ID=1 is specified and it is detected, this is output.
[216.5, 448.0]
In this sample code, center coordinates of mark are returned.
Supplementary explanation
ID is extracted from still image converted to gray image.
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, dict_aruco, parameters=parameters)
Check if list of markers includes marker with specified ID.
if num_id in np.ravel(ids) :
"np.where" is used to find index corresponding to specified mark in "ids".
index = np.where(ids == num_id)[0][0]
Upper left coordinates of mark is extracted by the following command.
cornerUL = corners[index][0][0]
sponsored link
How to overlay marker IDs and video
I show how to overlay marker ID and video.
In the following sample code, display video with marker IDs.
### Overlay marker ID and video
import cv2
from cv2 import aruco
import time
dict_aruco = aruco.Dictionary_get(aruco.DICT_4X4_50)
parameters = aruco.DetectorParameters_create()
cap = cv2.VideoCapture(0)
try:
while True:
ret, frame = cap.read()
gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)
corners, ids, rejectedImgPoints = aruco.detectMarkers(gray, dict_aruco, parameters=parameters)
frame_markers = aruco.drawDetectedMarkers(frame.copy(), corners, ids)
cv2.imshow('frame', frame_markers)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cv2.destroyWindow('frame')
cap.release()
except KeyboardInterrupt:
cv2.destroyWindow('frame')
cap.release()
Output
sponsored link