先决条件:
你必须安装 Python 和 OpenCV Contrib
你必须安装 numpy 库
你必须对 Python 语言及其基本库有基本的了解。
如果你想实时识别 Aruco Markers,你可能需要一个网络摄像头。
注意:这里的所有文件都在这个 Github 上:https://github.com/Suave101/StackData/tree/main/Aruco_Marker/How%20to%20draw%20on%20an%20Aruco%20marker%20in%20OpenCV%C2%A0python%3F
Aruco Markers 是OpenCV 库可以使用简单的函数和变量生成和识别的基准标记。每个标记都有自己的识别号。
要开始生成这些标记,我们需要设置项目环境。在开始创建 Python 文件之前,你需要创建一个空文件夹来放置标记生成器。创建此文件夹后,你可以在此文件夹中创建一个 python 文件。如果你很懒,只想复制粘贴一次,这里是 Github 上的文件:https://github.com/Suave101/StackData/tree/main/Aruco_Marker/How%20to%20draw%20on%20an%20Aruco%20marker%20in%20OpenCV%C2%A0python%3F
你需要先导入所需的库:
- import cv2
-
- import numpy as np
然后你需要为你的标记设置字典变量和空白变量:
注意:除了 6x6 之外,你还可以使用许多不同大小的字典。这些将在下一节中列出。
- dictionary = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)
- markerImage = np.zeros((300, 300), dtype=np.uint8)
之后,你需要生成标记。下面是一个生成 250 个标记的 for 循环。
- for x in range(0, 250):
- markerImage = cv2.aruco.drawMarker(dictionary, x, 300, markerImage, 1)
- cv2.imwrite(f"marker{x}.png", markerImage)
运行此代码(https://github.com/Suave101/StackData/blob/main/Aruco_Marker/How%20to%20draw%20on%20an%20Aruco%20marker%20in%20OpenCV%C2%A0python%3F/aruco_marker_generator.py)后,你应该会得到一个包含 Aruco Markers 的文件夹。
如果你收到这样的错误:
AttributeError: module 'cv2' has no attribute 'aruco'
这可能是因为你没有安装 OpenCV 的 contrib 版本。要干净利落地执行此操作,你必须卸载旧的 OpenCV 发行版,然后下载 contrib 版本。
- pip uninstall opencv-python
- pip install opencv-contrib-python
首先,在识别 Aruco 标记时,我们将在图像中识别它们。
这是 Github 上的代码:https://github.com/Suave101/StackData/tree/main/Aruco_Marker/How%20to%20draw%20on%20an%20Aruco%20marker%20in%20OpenCV%C2%A0python%3F
我们需要 Aruco 标记的图像,因此,你应该使用网络摄像头或手机拍照,以便让 OpenCV 找到 Aruco 标记。以下代码显示了如何读取图像:
- import cv2
-
- image = cv2.imread("path\\to\\image.png")
接下来,你需要定义字典大小和参数:
- dictionary = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)
- parameters = cv2.aruco.DetectorParameters_create()
最后,你需要查找标记并打印数据:
- markerCorners, markerIds, rejectedCandidates = cv2.aruco.detectMarkers(image, dictionary, parameters=parameters)
-
- print(markerIds)
要实时识别 Aruco 标记,我们需要有一个网络摄像头来获取帧。如果你没有网络摄像头,你仍然可以通过从 Internet 获取视频或使用录制设备录制视频来参与此练习。
为此,你必须将 Video Capture 函数中的 number 参数替换为你尝试读取的视频的路径。例如,我将在下面使用的视频文件名为“Mighty_Wings.mov”,它位于我的硬盘 Z 上:
vid = cv2.VideoCapture("Z:\\Mighty_Wings.mov")
回到现场识别标记。首先,我们将初始化所需的变量并导入必要的库。在这种情况下,我们只导入 OpenCV 库。我们之前已经看过字典和参数变量,但是,这个视频捕获对象呢?视频捕获对象从视频源或网络摄像头获取视频输入。0 代表使用的视频设备。
- import cv2
- vid = cv2.VideoCapture(0)
- dictionary = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)
- parameters = cv2.aruco.DetectorParameters_create()
现在我们需要定义识别循环。首先,循环从网络摄像头读取作为实时图像的帧数据。然后它会寻找一个 Aruco 标记。这个 while 循环将循环直到按下等待键“q”。
- while True:
- ret, frame = vid.read()
- markerCorners, markerIds, rejectedCandidates = cv2.aruco.detectMarkers(frame, dictionary, parameters=parameters)
- cv2.imshow('frame', frame)
- if cv2.waitKey(1) & 0xFF == ord('q'):
- break
最后,我们将停止从网络摄像头或视频源获取视频输入,并关闭任何延迟的窗口以实现冗余。
- vid.release()
- cv2.destroyAllWindows()
这是要复制和粘贴的 Github 文件:https://github.com/Suave101/StackData/blob/main/Aruco_Marker/How%20to%20draw%20on%20an%20Aruco%20marker%20in%20OpenCV%C2%A0python%3F/advanced_aruco_recognition.py
首先,我们导入库并定义变量。我们将随机库用于随机唯一颜色的 ID。我们使用数学库来计算距离公式。for 循环创建一个随机颜色列表。它比冗余所需的时间长。
- import random
-
- import cv2
- import math
-
- vid = cv2.VideoCapture(0)
- dictionary = cv2.aruco.Dictionary_get(cv2.aruco.DICT_6X6_250)
- parameters = cv2.aruco.DetectorParameters_create()
- color_list = []
- for x in range(0, 260):
- color_list.append((random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)))
然后我们得到大坏循环函数。我们读取帧,然后寻找标记。之后,我们将解析结果,直到我们得到 4 组坐标。它们是矩形的每个角。它们被放入一个列表中,因此我们从左下角开始,围绕矩形逆时针方向移动。
顶点标记
然后我们使用一些代数来获得宽度和高度。OpenCV 矩形函数使用顶点零作为其 X 和 Y 位置。此外,我们将矩形标记为 Aruco Marker ID。
请注意,文本标签在矩形下方 10 像素处,以免被矩形覆盖。我们从上一步中创建的颜色列表中获取一种颜色,以获得独特的颜色。
- while True:
- ret, frame = vid.read()
- markerCorners, markerIds, rejectedCandidates = cv2.aruco.detectMarkers(frame, dictionary, parameters=parameters)
- del rejectedCandidates
- if markerIds is not None:
- i = 0
- for marker in markerIds:
- k = str(markerCorners[i]).replace("\n", "").split("[")
- k2 = []
- for j in k:
- j = j.split("]")
- j2 = []
- for n in j:
- n = n.split(".")
- j2 = j2 + n
- k2 = k2 + j2
- del j2, j
- del k
- k3 = []
- for item in k2:
- try:
- k3.append(int(item))
- except:
- pass
- del k2
- k2 = [k3[i:i + 2] for i in range(0, len(k3), 2)]
- del k3
- x = k2[0][0]
- y = k2[0][1]
- w = int(math.dist(k2[0], k2[1]))
- h = int(math.dist(k2[3], k2[0]))
- frame = cv2.rectangle(frame, (x, y), (x + w, y + h), color_list[int(marker)], 1)
- frame = cv2.putText(frame, f'Marker: {int(marker)}', (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.9,
- color_list[int(marker)], 2)
- i = i + 1
- del i, markerCorners, markerIds
- cv2.imshow('frame', frame)
- if cv2.waitKey(1) & 0xFF == ord('q'):
- break
最后,我们执行之前见过的冗余代码行。
- vid.release()
- cv2.destroyAllWindows()
有许多不同大小的标记用于不同的用途。你可能希望对质量较低的相机或距离较远的相机使用较少量的数据。相反,如果你的环境中需要更多数据点,你可能需要更大的数据集。
4x4 标记有 50 个可能的 ID。5x5 标记有 100 个可能的 ID。6x6 标记有 250 个可能的 ID。7x7 标记有 1000 个可能的 ID。6x6 是最流行的标记系统之一。这就是我们使用它的原因。
本教程没有沿色谱的颜色分布均匀。为此,你必须乘以黄金比例,使用一些调制函数,并将 HSV 值转换为 RGB 值。
☆ END ☆
如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 woshicver」,每日朋友圈更新一篇高质量博文。
↓扫描二维码添加小编↓