OpenMV4 智能摄像头
资料:
https://book.openmv.cc/python-background.html
在OpenMV4中,使用到颜色识别,就避免不了需要对应颜色的阈值,通过阈值去查找到指定的颜色。
颜色阈值的设置
这里以红色阈值设置为案例。
- 使用OpenMV IDE连接摄像头
打开OpenMV IDE,连接上OpenMV摄像头。
- 开启OpenMV4采集颜色
案例是识别红色。我使用电脑上的画图软件,画出一个矩形。
- 打开阈值编辑器
- 在弹出的窗口中,选择帧缓冲区。
- 获取颜色阈值
通过调整滑块,将我们需要识别的颜色调整为白色,其他颜色调整为黑色。完成之后下方的LAB阈值就是颜色阈值了
案例一:串口自定义格式通信
使用OpenMV4采集最大色块的中心位置,通过串口自定义格式 发送给开发板。
接线
使用ESP32S3上的串口0(TX=P01 RX=P02) 连接 OpenMV4 的串口3(RX=P5 TX=P4)。
下方连接图中的OpenMV4是Plus型号,但是与普通版通用。
OpenMV4代码
内容讲解:查找图像中最大白色色块,通过串口3(P4 P5)输出数据格式 "[%d,%d]" 给开发板的串口。
WARNING
📌 别忘了将下方第14行代码中的 (0, 85, 51, 127, -99, 122) 改为前面调整颜色阈值得到的数值。
import sensor, image, time #导入传感器类、图像类、时间类
from pyb import UART #导入串口类
uart = UART(3, 115200) #实例一个串口3,波特率为115200 (TX=P4 RX=P5)
sensor.reset() # 复位和初始化摄像头传感器
sensor.set_pixformat(sensor.RGB565) # 设置像素格式为RGB565(或GRAYSCALE)
sensor.set_framesize(sensor.QVGA) # 设置帧大小为QVGA (320x240)
sensor.skip_frames(time = 2000) # 等待设置生效
clock = time.clock() # 创建一个时钟对象来跟踪图像帧率
#白色 颜色阈值
white_threshold = (0, 85, 51, 127, -99, 122)
# 查找最大色块函数
def find_max(blobs):
max_size=0
# 把blobs每个元素代入变量blob
for blob in blobs:
# 如果当前色块的像素量 跟之前比 是最多的
if blob.pixels() > max_size:
# 记录这个最多像素量的色块
max_blob=blob
# 更新最大像素量
max_size = blob.pixels()
return max_blob
uart.write("Hello World!\r") # 通过串口3输出固定字符串 “Hello World!”
# 主循环
while(True):
clock.tick() # 更新FPS时钟
img = sensor.snapshot() # 创建一个对象,拍一张照片并返回图像数据给img对象
print(clock.fps()) # IDE调试输出帧率
# 注意:当连接到IDE时,OpenMV Cam的运行速度约为一半。
# 一旦断开连接,FPS应该会增加。
# 在img对象中根据 传入的颜色阈值(white_threshold) 查找色块
blobs = img.find_blobs( [ white_threshold ] )
# 如果色块数量不为0
if blobs:
# 找到最大色块
max_blob=find_max(blobs)
# 在img图像中 对查找到的色块 画一个矩形
# blobs.rect() 色块的矩形参数
# draw_rectangle 画一个矩形框
img.draw_rectangle(max_blob.rect())
# 在图像上绘制一个十字。 cx代表中心x点 cy表示中心y点
img.draw_cross(max_blob.cx(), max_blob.cy())
# 整理字符串 将最大色块的 中心xy点 按照%d格式,格式化字符串
output_str="[%d,%d]" % ( max_blob.cx(), max_blob.cy() )
# 在IDE中输出字符串
print( 'Maximum color block position : ' + output_str + '\r\n' )
# 通过串口3输出字符串
uart.write( 'Maximum color block position : ' + output_str + '\r\n' )
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
ESP32代码
bsp_openmv4.c
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-01-09 LCKFB-lp first version
*/
#include "bsp_openmv4.h"
#include "stdio.h"
#include "string.h"
uint8_t openmv4_recv_buff[USART_RECEIVE_LENGTH]; // 接收缓冲区
uint16_t openmv4_recv_length = 0; // 接收数据长度
uint8_t openmv4_recv_complete_flag = 0; // 接收数据完成标志位
void delay_ms(unsigned int ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}
void delay_us(unsigned int us)
{
ets_delay_us(us);
}
void delay_1ms(unsigned int ms)
{
vTaskDelay(ms / portTICK_PERIOD_MS);
}
void delay_1us(unsigned int us)
{
ets_delay_us(us);
}
/******************************************************************
* 函 数 名 称:OpenMV4_usart_gpio_config
* 函 数 说 明:OpenMV4串口配置GPIO
* 函 数 形 参:band_rate:波特率
* 函 数 返 回:无
* 作 者:LC
* 备 注:LC
******************************************************************/
void OpenMV4_usart_gpio_config(uint32_t band_rate)
{
//定义 串口配置结构体,必须赋初值,否则无法实现
uart_config_t uart_config={0};
uart_config.baud_rate = band_rate; //配置波特率
uart_config.data_bits = UART_DATA_8_BITS; //配置数据位为8位
uart_config.parity = UART_PARITY_DISABLE; //配置校验位为不需要校验
uart_config.stop_bits = UART_STOP_BITS_1; //配置停止位为 一位
uart_config.flow_ctrl = UART_HW_FLOWCTRL_DISABLE; //禁用硬件流控制
//将以上参数加载到串口1的寄存器
uart_param_config(PORT_UART, &uart_config);
//绑定引脚 TX=GPIO_TX_PIN RX=GPIO_RX_PIN RTS=不使用 CTS=不使用
uart_set_pin(PORT_UART, GPIO_TX_PIN, GPIO_RX_PIN, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
//安装 串口 驱动程序
uart_driver_install(PORT_UART, USART_RECEIVE_LENGTH, USART_RECEIVE_LENGTH, 0, NULL, 0);
//创建串口接收任务
xTaskCreate(BSP_OPENMV4_USART_TASK, "BSP_OPENMV4_USART_TASK", USART_RECEIVE_LENGTH*2, NULL, configMAX_PRIORITIES, NULL);
}
//
/******************************************************************
* 函 数 名 称:Openmv4DataAnalysis
* 函 数 说 明:解析OpenMV4 发送过来的自定义格式数据 [%d,%d] 解析
* 函 数 形 参:无
* 函 数 返 回:无
* 作 者:LC
* 备 注:无
******************************************************************/
void Openmv4DataAnalysis(void)
{
char temp[200] = {0};
char *buff = temp;
int i = 0;
//没有接收到数据 或者 数据没有接收完成 则不进行处理
if( openmv4_recv_complete_flag == 0 ) return;
//串口0输出接收到的数据(调试)
printf( "%s\r\n", openmv4_recv_buff );
//清除接收完成标志位,等待下一次接收
openmv4_recv_complete_flag = 0;
//找到格式的头 '['
if( strstr((const char*)openmv4_recv_buff, "[" ) != NULL )
{
buff = strstr((const char*)openmv4_recv_buff, "[" );
}
//找到结尾
while( buff[i] != ']' )
{
i++;
if(i > 200)
{
//UART环缓冲区刷新。丢弃UART RX缓冲区中的所有数据,准备下次接收
uart_flush(PORT_UART);
openmv4_recv_length = 0;
//清除数据
memset(temp,0,200);
printf("i > 200");
return;
}
}
//strncpy函数不会补零,需手动补上
buff[i+1] = '\0';
printf("buff = %s\r\n", buff );
//UART环缓冲区刷新。丢弃UART RX缓冲区中的所有数据,准备下次接收
uart_flush(PORT_UART);
openmv4_recv_length = 0;
//清除数据
memset(temp,0,200);
}
/************************************************
函数名称 : BSP_OPENMV4_USART_TASK
功 能 : 接收数据
参 数 : 无
返 回 值 : 无
作 者 : LC
*************************************************/
void BSP_OPENMV4_USART_TASK(void)
{
while(1)
{
if(openmv4_recv_complete_flag == 0)
{
//接收串口数据收到的数据长度
openmv4_recv_length = uart_read_bytes(PORT_UART, openmv4_recv_buff, USART_RECEIVE_LENGTH, 10 / portTICK_PERIOD_MS);
if( openmv4_recv_length > 0 )//数据长度大于0,说明接收到数据
{
openmv4_recv_buff[openmv4_recv_length] = 0;
openmv4_recv_complete_flag = 1;
}
}
delay_ms(50);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
bsp_openmv4.h
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-01-09 LCKFB-lp first version
*/
#ifndef _BSP_OPENMV4_H_
#define _BSP_OPENMV4_H_
#include <stdio.h>
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_system.h"
#include "esp_rom_sys.h"
#include "esp_timer.h"
#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "rom/ets_sys.h"
#include "driver/gptimer.h"
#include "freertos/queue.h"
#include "driver/spi_master.h"
#include "nvs_flash.h"
#define GPIO_TX_PIN 2
#define GPIO_RX_PIN 1
#define PORT_UART UART_NUM_2
/* 串口缓冲区的数据长度 */
#define USART_RECEIVE_LENGTH 1024
void delay_us(unsigned int us);
void delay_ms(unsigned int ms);
void delay_1us(unsigned int us);
void delay_1ms(unsigned int ms);
void OpenMV4_usart_gpio_config(uint32_t band_rate);
void BSP_OPENMV4_USART_TASK(void);
void Openmv4DataAnalysis(void);
#endif
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
案例验证
将ESP32-S3开发板和OpenMV4接好线。在main.c中编写以下代码。
main.c
/*
* 立创开发板软硬件资料与相关扩展板软硬件资料官网全部开源
* 开发板官网:www.lckfb.com
* 技术支持常驻论坛,任何技术问题欢迎随时交流学习
* 立创论坛:club.szlcsc.com
* 关注bilibili账号:【立创开发板】,掌握我们的最新动态!
* 不靠卖板赚钱,以培养中国工程师为己任
* Change Logs:
* Date Author Notes
* 2024-01-09 LCKFB-lp first version
*/
#include <stdio.h>
#include "bsp_openmv4.h"
void app_main(void)
{
OpenMV4_usart_gpio_config(115200); // PENMV4串口初始化
printf("Start......\r\n");
while(1)
{
Openmv4DataAnalysis();
delay_ms(100);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
上电效果:
驱动代码:
案例二:任意颜色线循迹
WARNING
📌 ESP32开发板的代码和【案例一】一致。
使用ESP32S3上的串口0(TX=P01 RX=P02) 连接 OpenMV4 的串口3(RX=P5 TX=P4)。
下方连接图中的OpenMV4是Plus型号,但是与普通版通用。
OpenMV4代码
代码说明:实现任意颜色的寻线,需要知道线的颜色和位置。线的颜色识别通过色块查找的方式;而位置的判断,通过识别出线的颜色之后,在识别到的区域中心画一个十字型符号‘+’,并记录该色块中心位置命名为x_location。
如何识别线的颜色?通过寻找色块函数 find_blobs() 进行查找
将x_location与图像的X轴中心作比较,就可以得到线的位置Line_position。其中图像的X轴中心命名为centre
当 x_location > centre 时,Line_position设置为正数,x_location 越大,则Line_position 越大。
当 x_location < centre 时,Line_position设置为负数,x_location 越小,则Line_position 越小。
当 x_location = centre 时,Line_position设置为0。
如何实现循迹?
将OpenMV4放置在中间位置。
当Line_position 为负数,说明识别到线在图像的左侧。我们需要控制小车左转。
当Line_position 为正数,说明识别到线在图像的右侧。我们需要控制小车右转。
当Line_position 为0 , 说明识别到线在图像的中间。我们往前直行。
需要注意的是,线的颜色不可以和背景色相同,否则该案例失效。
WARNING
📌 别忘了将下方第14行代码中的 (19, 0, -128, 62, -128, 77) 改为前面调整颜色阈值得到的数值。
import sensor, image, time, math#调用声明
from pyb import UART
import json
#修改这里的颜色阈值可以做到任意颜色识别循迹
#颜色阈值修改可以参考: ”颜色阈值选择工具“ https://book.openmv.cc/image/blob.html
GRAYSCALE_THRESHOLD =(19, 0, -128, 62, -128, 77)
# 识别颜色的矩形区域
Identification_region = [0, 50, 160, 20]
# 色块的X轴位置
x_location = 0
# 图像的X轴中心
centre = 0
# 线的位置
Line_position = 0
# 摄像头配置
sensor.reset() # 初始化摄像头传感器
sensor.set_pixformat(sensor.RGB565) # 设置相机的像素模式为16 bits/像素(即显示彩色)
sensor.set_framesize(sensor.QQVGA2) # 128x160 分辨率的相机传感器
sensor.skip_frames(30) # 跳过30帧,让相机图像在改变相机设置后稳定下来
uart = UART(3,115200) #实例一个串口3,波特率为115200 (TX=P4 RX=P5)
uart.init(115200,bits=8,parity=None,stop=1) #配置串口的波特率、数据位、校验位、停止位
while(True):
img = sensor.snapshot() # 拍一张照片并返回图像
#设置图像的X轴中心
centre = (img.width() / 2)
# 寻找 颜色阈值【GRAYSCALE_THRESHOLD】设置的颜色
blobs = img.find_blobs([GRAYSCALE_THRESHOLD], roi=Identification_region, merge=True)
# roi 是感兴趣区域的矩形元组(x,y,w,h)。如果指定[10,10,20,20],则在以(10,10)为起点的位置,以长宽都为20的大小查找色块
# 如果roi未指定,ROI即整个图像的图像矩形。 操作范围仅限于 roi 区域内的像素。
# merge 若为True,则合并所有没有被过滤掉的色块,这些色块的边界矩形互相交错重叠。
#识别到色块
if blobs:
most_pixels = 0 #最大色块的像素
largest_blob = 0 #最大色块
for i in range(len(blobs)):
#目标区域找到的颜色块(线段块)可能不止一个,找到最大的一个,作为本区域内的目标直线
if blobs[i].pixels() > most_pixels:
most_pixels = blobs[i].pixels() #记录最大色块的像素
largest_blob = i #记录最大色块
# 在查找到的最大色块处画矩形
img.draw_rectangle(blobs[largest_blob].rect())
#在起始点(0,0)到结束点(30,30)画一个矩形
#img.draw_rectangle((0,0,30, 30))
# 在最大色块的中心画一个十字
#.cx()表示中心点的x轴, .cy()表示中心点的y轴
img.draw_cross(blobs[largest_blob].cx(),blobs[largest_blob].cy())
#记录中心点X轴位置
x_location = blobs[largest_blob].cx()
#未识别到色块
else:
x_location = centre
#在图像的正中间画一个红色的十字,方便确定屏幕中间的位置
img.draw_cross(int(centre), int(img.height()/2), color = (255, 0, 0), size = 10 )
#在识别的区域内画蓝色矩形
img.draw_rectangle(Identification_region,color=(0, 0, 255))
#计算色块距离屏幕中间的距离, (img.width() / 2)后,色块中心点在屏幕左边则是负值 色块中心点在屏幕右边则是正值
Line_position="[%d]"%( x_location - centre )
# 串口3发送数据
uart.write(Line_position+'\r\n')
# IDE调试输出,以下内容可以删除
#小于-10输出左转
#大于 10输出右转
#在-10到10范围内则输出前进
num = x_location - centre
if (num <= 10 and num >= -10):
print("前进")
elif num > 10:
print("右转")
elif num < 10:
print("左转")
#输出
print(Line_position)
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
案例验证
案例三:矩形识别与中心判断
OpenMV4代码
import sensor, image, time
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA2)#像素128x160
sensor.skip_frames(time = 2000)
clock = time.clock()
# 查找最大矩形块函数
def find_max(rects):
rect_max=0
# 把blobs每个元素代入变量rect
for rect in rects:
# 如果当前矩形的宽 跟之前比 是最大的
if rect.w() > rect_max:
global max_rect
# 记录这个最多大的矩形
max_rect = rect
# 更新最大矩形宽度
rect_max = rect.w()
#返回这个最大矩形元素
return max_rect
while(True):
#记录帧率
clock.tick()
#拍照
img = sensor.snapshot()
#查找到最大矩形块,查找范围x=0,y=20,w=128,h=120
rects = find_max(img.find_rects(roi=(0,20,128,120)))
#将查找到的最大矩形画一个绿色的矩形框
img.draw_rectangle(rects.x(),rects.y(),rects.w(),rects.h(),color=(0,255,0))
#计算矩形中心
#中心X定位:矩形像素宽度 / 2 + x轴起点位置
#中心Y定位:矩形像素高度 / 2 + y轴起点位置
x_central = (rects.w() / 2) + rects.x()
y_central = (rects.h() / 2) + rects.y()
#显示识别到的最大矩形中心的X,Y位置
img.draw_string(2,1,"x=%d y=%d"%(x_central,y_central))
#在查找到的矩形中心画一个蓝色的十字
img.draw_cross(int(x_central), int(y_central), color = (0, 0, 255), size = 5 )
#在查找区域画一个红色方框
#区域越小,帧数越高
img.draw_rectangle(0,20,128,120,color=(255,0,0))
#IDE输出帧率
print(clock.fps())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
案例验证
案例四:任意角度矩形识别与边角定位
OpenMV4代码
import sensor, image, time
# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 设置图像色彩格式为RGB565格式
sensor.set_framesize(sensor.QQVGA) # 设置图像大小为160*120
sensor.set_auto_whitebal(True) # 设置自动白平衡
sensor.set_brightness(3000) # 设置亮度为3000
sensor.skip_frames(time = 20) # 跳过帧
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#去除鱼眼畸变
img.lens_corr(1.8)
# -----矩形框部分-----
# 在图像中寻找矩形
for r in img.find_rects(threshold = 10000):
# 判断矩形边长是否符合要求
if r.w() > 20 and r.h() > 20:
# 在屏幕上框出矩形
img.draw_rectangle(r.rect(), color = (255, 0, 0), scale = 4)
# 获取矩形角点位置
corner = r.corners()
# 在屏幕上圈出矩形角点
img.draw_circle(corner[0][0], corner[0][1], 5, color = (255, 0, 0), thickness = 2, fill = False)
img.draw_circle(corner[1][0], corner[1][1], 5, color = (0, 255, 0), thickness = 2, fill = False)
img.draw_circle(corner[2][0], corner[2][1], 5, color = (0, 0, 255), thickness = 2, fill = False)
img.draw_circle(corner[3][0], corner[3][1], 5, color = (255, 255, 0), thickness = 2, fill = False)
# 打印四个角点坐标, 角点1的数组是corner[0], 坐标就是(corner[0][0],corner[0][1])
# 角点检测输出的角点排序每次不一定一致,矩形左上的角点有可能是corner0,1,2,3其中一个
left_down_dot ="LD=[%d,%d]"%(corner[0][0],corner[0][1]) #红色点
right_down_dot ="RD=[%d,%d]"%(corner[1][0],corner[1][1]) #绿色点
right_up_dot ="RU=[%d,%d]"%(corner[2][0],corner[2][1]) #蓝色点
left_up_dot ="LU=[%d,%d]"%(corner[3][0],corner[3][1]) #黄色点
print(left_up_dot + "\n" + left_down_dot + "\n" + right_up_dot + "\n" + right_down_dot)
# 打印帧率
print(clock.fps())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
案例验证
案例五 激光识别与定位
将识别到的红色激光以黑色方框圈出,并在IDE中输出激光XY轴位置。
OpenMV4代码
import sensor, image, time
from pyb import UART #导入串口类
uart = UART(3, 115200) #实例一个串口3,波特率为115200 (TX=P4 RX=P5)
sensor.reset() # 复位和初始化摄像头传感器
sensor.set_pixformat(sensor.RGB565) # 设置像素格式为RGB565(或GRAYSCALE)
sensor.set_framesize(sensor.QVGA) # 设置帧大小为QVGA (320x240)
sensor.skip_frames(time = 2000) # 等待设置生效
clock = time.clock() # 创建一个时钟对象来跟踪图像帧率
# 初始化摄像头
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 设置图像色彩格式为RGB565格式
sensor.set_framesize(sensor.QQVGA) # 设置图像大小为160*120
sensor.set_auto_whitebal(True) # 设置自动白平衡
sensor.set_brightness(3000) # 设置亮度为3000
sensor.skip_frames(time = 20) # 跳过帧
clock = time.clock()
while(True):
clock.tick()
img = sensor.snapshot()
#去除鱼眼畸变
img.lens_corr(1.8)
# -----跟踪激光部分-----
# 设置红色激光颜色阈值
G_td = [(91, 100, -128, 127, -75, 127)]
# 根据阈值找到色块
for b in img.find_blobs(G_td,pixels_threshold=2, area_threshold=15, merge=True,invert = 0):
# 在识别到的激光处画一个黑色矩形
img.draw_rectangle(b.rect(), color = (0, 0, 0), scale = 1, thickness = 2)
# 打印激光色块的中心位置
# 使用b.x()获取色块矩形左上角X坐标
# 使用b.y()获取色块矩形左上角Y坐标
# 使用b.w()获取色块矩形宽度
# 使用b.h()获取色块矩形高度
# 矩形中心坐标为(x + w/2,y + h/2)
print("[%d,%d]"%( (b.x() + b.w()/2), (b.y() + b.h()/2 ) ))
# 整理字符串串
output_str="[%d,%d]" % ( (b.x() + b.w()/2), (b.y() + b.h()/2 ) )
# 通过串口3输出字符串
uart.write( 'Point:' + output_str + '\r\n' )
break
# 打印帧率
print(clock.fps())
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
案例验证
如识别不出红色激光点,请按照颜色阈值的设置章节,配置你的阈值。