Skip to content

Commit

Permalink
* update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
lxowalle committed Apr 8, 2024
1 parent b160aea commit 5976a93
Show file tree
Hide file tree
Showing 6 changed files with 373 additions and 28 deletions.
2 changes: 1 addition & 1 deletion docs/doc/zh/sidebar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ items:
- file: vision/image_ops.md
label: 基本图像操作
- file: vision/find_blobs.md
label: 找色块
label: 寻找色块
- file: vision/qrcode.md
label: 二维码识别
- file: vision/apriltag.md
Expand Down
131 changes: 131 additions & 0 deletions docs/doc/zh/vision/apriltag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
---
title: MaixPy 识别Apriltag标签
update:
- date: 2024-04-03
author: lxowalle
version: 1.0.0
content: 初版文档
---

阅读本文前,确保已经知晓如何开发MaixPy,详情请阅读[MaixVision -- MaixPy 编程 + 图形化积木编程](../basic/maixvision.md)

## 简介

本文介绍如何使用MaixPy来识别Apriltag标签

## 使用 MaixPy 识别Apriltag标签

MaixPy的 `maix.image.Image`中提供了`find_apriltags`方法,可以可以识别apriltag标签。

### 如何识别Apriltag标签

一个简单的示例,实现识别apriltag标签并画框

```python
from maix import image, camera, display

cam = camera.Camera()
disp = display.Display()

families = image.ApriltagFamilies.TAG36H11
x_scale = cam.width() / 160
y_scale = cam.height() / 120

while 1:
img = cam.read()

new_img = img.resize(160, 120)
apriltags = new_img.find_apriltags(families = families)
for a in apriltags:
corners = a.corners()

for i in range(4):
corners[i][0] = int(corners[i][0] * x_scale)
corners[i][1] = int(corners[i][1] * y_scale)
x = int(a.x() * x_scale)
y = int(a.y() * y_scale)
w = int(a.w() * x_scale)
h = int(a.h() * y_scale)

for i in range(4):
img.draw_line(corners[i][0], corners[i][1], corners[(i + 1) % 4][0], corners[(i + 1) % 4][1], image.COLOR_RED)
img.draw_string(x + w, y, "id: " + str(a.id()), image.COLOR_RED)
img.draw_string(x + w, y + 15, "family: " + str(a.family()), image.COLOR_RED)

disp.show(img)
```

步骤:

1. 导入image、camera、display模块

```python
from maix import image, camera, display
```

2. 初始化摄像头和显示

```python
cam = camera.Camera()
disp = display.Display()
```

3. 从摄像头获取图片并显示

```python
while 1:
img = cam.read()
disp.show(img)
```

4. 调用`find_apriltags`方法识别摄像头图片中的apriltag标签

```python
new_img = img.resize(160, 120)
apriltags = new_img.find_apriltags(families = families)
```

- `img`是通过`cam.read()`读取到的摄像头图像
- `img.resize(160, 120)`是用来将图像缩放得更小,用更小的图像来让算法计算得更快
- `new_img.find_apriltags(families = families)`用来寻找apriltag标签,并将查询结果保存到`apriltags`,以供后续处理。其中families用来选择apriltag族,默认为`image.ApriltagFamilies.TAG36H11`

5. 处理识别标签的结果并显示到屏幕上

```python
for a in apriltags:
# 获取位置信息(并映射坐标到原图)
x = int(a.x() * x_scale)
y = int(a.y() * y_scale)
w = int(a.w() * x_scale)
corners = a.corners()
for i in range(4):
corners[i][0] = int(corners[i][0] * x_scale)
corners[i][1] = int(corners[i][1] * y_scale)

# 显示
for i in range(4):
img.draw_line(corners[i][0], corners[i][1], corners[(i + 1) % 4][0], corners[(i + 1) % 4][1], image.COLOR_RED)
img.draw_string(x + w, y, "id: " + str(a.id()), image.COLOR_RED)
img.draw_string(x + w, y + 15, "family: " + str(a.family()), image.COLOR_RED)
img.draw_string(x + w, y + 30, "rotation : " + str(180 * a.rotation() // 3.1415), image.COLOR_RED)
```

- 遍历`apriltags`的成员,`apriltags`是通过`img.find_apriltags()`扫描apriltag标签的结果,如果找不到标签则`apriltags`的成员为空
- `x_scale``y_scale`用来映射坐标,由于`new_img`是缩放后的图像,计算apriltag的坐标时需要经过映射后才能正常的画在原图`img`
- `a.corners()`用来获取已扫描到的标签的四个顶点坐标,`img.draw_line()`利用这四个顶点坐标画出标签的形状
- `img.draw_string`用来显示标签的内容,其中`a.x()``a.y()`用来获取标签左上角坐标x和坐标y,`a.id()`用来获取标签的id,`a.family()`用来获取标签族类型,`a.rotation()`用来获取标签的旋转角度。

### 常用参数说明

列举常用参数说明,如果没有找到可以实现应用的参数,则需要考虑是否使用其他算法实现,或者基于目前算法的结果扩展所需的功能


| 参数 | 说明 | 示例 |
| -------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| roi | 设置算法计算的矩形区域,roi=[x, y, w, h],x,y表示矩形区域左上角坐标,w,h表示矩形区域的宽度和高度,默认为整张图片 | 计算坐标为(50,50),宽和高为100的区域<br />```img.find_apriltags(roi=[50, 50, 100, 100])``` |
| families | apriltag标签家族类型 | 扫描TAG36H11家族的标签<br />```img.find_apriltags(families = image.ApriltagFamilies.TAG36H11)``` |

本文介绍常用方法,更多 API 请看 API 文档的 [image](../../../api/maix/image.md) 部分。



166 changes: 144 additions & 22 deletions docs/doc/zh/vision/find_blobs.md
Original file line number Diff line number Diff line change
@@ -1,55 +1,177 @@
---
title: MaixPy 找色块
title: MaixPy 寻找色块
update:
- date: 2024-04-03
author: neucrack
version: 1.0.0
content: 初版文档
- date: 2024-04-03
author: lxowalle
version: 1.0.1
content: 添加寻找色块的详细用法
---

## 简介

在视觉应用中,找色块是一个非常常见的需求,比如机器人找色块,自动化生产线找色块等等。
即需要识别画面中的特定的颜色区域,获取这个区域的位置和大小等信息。

阅读本文前,确保已经知晓如何开发MaixPy,详情请阅读[MaixVision -- MaixPy 编程 + 图形化积木编程](../basic/maixvision.md)

## 使用设备自带的找色块应用

打开设备,选择`找色块`应用,然后在下方选择要识别的颜色,或者自定义颜色,即可以识别到对应的颜色了,同时串口也会输出识别到的坐标和颜色信息。
## 简介

<video src="/static/video/find_blobs.mp4" controls="controls" width="100%" height="auto"></video>
本文将介绍如何使用MaixPy来寻找色块,以及如何使用MaixCam的默认应用程序寻找色块。

### 自定义颜色的方法
在视觉应用中,寻找色块是一个非常常见的需求,比如机器人找色块,自动化生产线找色块等等,即需要识别画面中的特定的颜色区域,获取这个区域的位置和大小等信息。

TODO:

### 串口协议
## 使用 MaixPy 寻找色块

TODO:
MaixPy的 `maix.image.Image`中提供了`find_blobs`方法,可以方便的找色块。

## 使用 MaixPy 找色块
### 如何寻找色块

`maix.image.Image`中提供了`find_blobs`方法,可以方便的找色块。
一个简单的示例,实现寻找色块并画框

```python
from maix import image, camera, display

cam = camera.Camera(320, 240)
disp = display.Display()

thresholds = [[0, 100, -120, -10, 0, 30]]
# 根据色块颜色选择对应配置
thresholds = [[0, 80, 40, 80, 10, 80]] # red
# thresholds = [[0, 80, -120, -10, 0, 30]] # green
# thresholds = [[0, 80, 30, 100, -120, -60]] # blue

while 1:
img = cam.read()
blobs = img.find_blobs(thresholds)
blobs = img.find_blobs(thresholds, pixels_threshold=500)
for blob in blobs:
img.draw_rectangle(blob[0], blob[1], blob[2], blob[3], color=(255, 0, 0))
img.draw_rect(blob[0], blob[1], blob[2], blob[3], image.COLOR_GREEN)
disp.show(img)
```

这里的 `thresholds` 是一个颜色阈值列表,每个元素是一个颜色阈值,同时找到多个阈值就传入多个,每个颜色阈值的格式为 `[L_MIN, L_MAX, A_MIN, A_MAX, B_MIN, B_MAX]`,这里的 `L``A``B``LAB`颜色空间的三个通道,`L` 通道是亮度,`A` 通道是红绿通道,`B` 通道是蓝黄通道。
可以在上面使用`找色块`应用中找到被检测物体对应的颜色阈值。
步骤:

1. 导入image、camera、display模块

```python
from maix import image, camera, display
```

2. 初始化摄像头和显示

```python
cam = camera.Camera(320, 240) # 初始化摄像头,输出分辨率320x240 RGB格式
disp = display.Display()
```

3. 从摄像头获取图片并显示

```python
while 1:
img = cam.read()
disp.show(img)
```

4. 调用`find_blobs`方法寻找摄像头图片中的色块,并画到屏幕上

```python
blobs = img.find_blobs(thresholds, pixels_threshold=500)
for blob in blobs:
img.draw_rect(blob[0], blob[1], blob[2], blob[3], image.COLOR_GREEN)
```

- `img`是通过`cam.read()`读取到的摄像头图像,当初始化的方式为`cam = camera.Camera(320, 240)`时,`img`对象是一张分辨率为320x240的RGB图。
- `img.find_blobs`用来寻找色块, `thresholds` 是一个颜色阈值列表,每个元素是一个颜色阈值,同时找到多个阈值就传入多个,每个颜色阈值的格式为 `[L_MIN, L_MAX, A_MIN, A_MAX, B_MIN, B_MAX]`,这里的 `L``A``B``LAB`颜色空间的三个通道,`L` 通道是亮度,`A` 通道是红绿通道,`B` 通道是蓝黄通道。`pixels_threshold`是一个像素点数量的阈值,用来过滤一些不需要的小色块。
- `img.draw_rect`用来画色块框,`blob[0]``blob[1]``blob[1]``blob[1]`分别代表色块左上角坐标x,色块左上角坐标y,色块宽度w和色块高度h

### 常用参数说明

列举常用参数说明,如果没有找到可以实现应用的参数,则需要考虑是否使用其他算法实现,或者基于目前算法的结果扩展所需的功能

| 参数 | 说明 | 示例 |
| ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
| thresholds | 基于lab颜色空间的阈值,threshold=[[l_min, l_max, a_min, a_max, b_min, b_max]],分别表示:<br />亮度范围为[l_min, l_max]\|<br />绿色到红色的分量范围为[l_min, l_max]<br />蓝色到黄色的分量范围为[b_min, b_max]<br />可同时设置多个阈值 | 设置两个阈值来检测红色和绿色<br />```img.find_blobs(threshold=[[0, 80, 40, 80, 10, 80], [0, 80, -120, -10, 0, 30]])```<br />红色阈值为[0, 80, 40, 80, 10, 80]<br />绿色阈值为[0, 80, -120, -10, 0, 30] |
| invert | 使能阈值反转,使能后传入阈值与实际阈值相反,默认为False | 使能阈值反转<br />```img.find_blobs(invert=True)``` |
| roi | 设置算法计算的矩形区域,roi=[x, y, w, h],x,y表示矩形区域左上角坐标,w,h表示矩形区域的宽度和高度,默认为整张图片 | 计算坐标为(50,50),宽和高为100的区域<br />```img.find_blobs(roi=[50, 50, 100, 100])``` |
| area_threshold | 过滤像素面积小于area_threshold的色块,单位为像素点,默认为10。该参数可用于过滤一些无用的小色块 | 过滤面积小于1000的色块<br />```img.find_blobs(area_threshold=1000)``` |
| pixels_threshold | 过滤有效像素点小于pixels_threshold的色块,默认为10。该参数可用于过滤一些无用的小色块 | 过滤有效像素点小于1000的色块<br />```img.find_blobs(pixels_threshold=1000)``` |

本文介绍常用方法,更多 API 请看 API 文档的 [image](../../../api/maix/image.md) 部分。

## 使用寻找色块APP

为了快速验证寻找色块的功能,可以先使用MaixCam提供的寻找色块应用程序来体验寻找色块的效果。

### 使用方法
打开设备,选择`找色块`应用,然后在下方选择要识别的颜色,或者自定义颜色,即可以识别到对应的颜色了,同时串口也会输出识别到的坐标和颜色信息。

<video src="/static/video/find_blobs.mp4" controls="controls" width="100%" height="auto"></video>

### 详细说明

APP界面参考如下:

![](../../../static/image/find_blobs_app.jpg)

#### 使用默认配置

寻找色块APP默认提供了`red、green、blue、user`四种配置,其中`red、green和blue`用来`寻找红色、绿色和蓝色的色块``user`主要提供给`用户自定义寻找色块`,自定义配置的方法见下文。快速体验时通过`点击`界面下方`按钮`即可切换到对应配置,

#### 寻找自定义色块

APP提供两种方式来寻找自定义的色块:通过自适应LAB阈值寻找和手动设置LAB阈值寻找

##### 1. 自适应LAB阈值寻找色块

操作方法:

1. `点击`左下角`选项图标`,进入配置模式
2.`摄像头对准`需要`寻找的物体``点击`屏幕上的`目标物体`,此时`左侧`会显示该物体对应颜色的`矩形框`,并显示该物体颜色的LAB值。
3. 点击出现的`矩形框`,系统将会`自动设置`LAB阈值,此时画面将会画出该物体边缘。

##### 2. 手动设置LAB阈值寻找色块

手动设置可以更精确的找到目标色块。

操作方法:

1. `点击`左下角`选项图标`,进入配置模式

2.`摄像头对准`需要`寻找的物体``点击`屏幕上的`目标物体`,此时`左侧`会显示该物体对应颜色的`矩形框`,并显示该物体颜色的`LAB值`

3. 点击下方选项`L Min,L Max,A Min,A Max,B Min,B Max`,点击后右侧会出现滑动条来设置该选项值。这些值分别对应LAB颜色格式的L通道、A通道和B通道的最小值和最大值

4. 参考步骤2计算的物体颜色的`LAB值`,将`L Min,L Max,A Min,A Max,B Min,B Max`调整到合适的值,即可识别到对应的色块。

例如`LAB=(20, 50, 80)`,由于`L=20`,为了适配一定范围让`L Min=10``L Max=30`;同理,由于`A=50`,让`A Min=40``A Max=60`; 由于`B=80`,让`B Min=70``B Max=90`

#### 通过串口协议获取检测数据

寻找色块APP支持通过串口(默认波特率为115200)上报检测到的色块信息。

由于上报信息只有一条,这里直接用示例来说明上报信息的内容。

例如上报信息为:

```shell
AA CA AC BB 14 00 00 00 E1 08 EE 00 37 00 15 01 F7 FF 4E 01 19 00 27 01 5A 00 A7 20
```

- `AA CA AC BB`:协议头部,内容固定
- `14 00 00 00`:数据长度,除了协议头部和数据长度外的总长度
- `E1`:标志位,用来标识串口消息标志
- `08`:命令类型,对于寻找色块APP应用该值固定为0x08
- `EE 00 37 00 15 01 F7 FF 4E 01 19 00 27 01 5A 00`:已找到色块的四个顶点坐标,每个值用小端格式的2字节表示。`EE 00``37 00`表示第一个顶点坐标为(238, 55),`15 01``F7 FF`表示第二个顶点坐标为(277, -9),`4E 01``19 00`表示第三个顶点坐标为(334, 25),`27 01``5A 00`表示第四个顶点坐标为(295, 90)。

- `A7 20`:CRC 校验值,用以校验帧数据在传输过程中是否出错

## 关于LAB颜色空间

LAB颜色空间和RGB颜色空间一样是一种表示颜色的方法,LAB可以表示人眼能看到的所有颜色。如果需要了解LAB可以去网络上搜索相关文章,那样更详细,而对于你应该只需要了解为什么选用LAB对于MaixPy的优势。

LAB对于MaixPy的优势:

1. LAB颜色空间的色域比RGB都要大,因此完全可以替换RGB。
2. LAB颜色空间下,由于L通道是亮度通道,我们常常设置到较大的范围即可(常用[0,80]),而编写代码时主要关注是A通道和B通道,这样可以减少大量的时间在纠结颜色阈值如何选择的问题上。
3. LAB颜色空间的颜色感知更均匀,更容易用代码调试。例如,对于只需要寻找红色色块,可以固定L通道和B通道值,只需要调整A通道的值即可(这是在颜色精度要求不高的情况下);如果是RGB通道则基本需要R、G、B三个通道同时变动才能找到合适的阈值。

更多参数和用法请参考 API 文档。


Loading

0 comments on commit 5976a93

Please sign in to comment.