k210机器视觉
机器视觉
LCD
LCD 液晶显示屏是非常常见的一个外接显示设备,跟前面的 OLED 显示屏相比,LCD 会更常用一些,我们看到的手持设备、小型电器,很多都用到 LCD,部分配合触摸屏应用,能实现非常多的功能。
除此之外,LCD 还是 pyAI-K210 机器视觉应用中显示的重要工具。
本实验用的 LCD 是 2.8 寸,驱动是常见的 ST7789V,使用 8 位接口跟 pyAIK210 通信,按以往嵌入式 C 语言开发,我们需要对 ST7789 进行编程实现驱动,然后再建立各种字符显示及显示图片等函数。使用 MicroPython 其实也需要做以上工作,但由于可读性和移植性强的特点,我们只需要搞清各个对象函数使如何使用即可。总的来说和之前一样,有构造函数和功能函数。构造函数解决的是初始化问题,告诉 pyAI-K210 外设是怎么接线,是什么样的;而功能函数解决的则是使用问题,我们基于自己的需求直接调用相关功能函数,实现自己的功能即可!我们管这些函数的集合叫驱动,MaixPy 已经将这 LCD.py 驱动写好了,我们学会如何使用即可。其构造函数和使用方法如下:
构造函数
1 | lcd.init(type=1,freq=15000000,color=lcd.BLACK) |
初始化 LCD。
【type】LCD 类型;
【freq】通信频率;
【color】LCD 初始化的颜色。
使用方法
1 | lcd.deinit() |
注销 LCD 驱动,释放 IO 引脚。
1 | lcd.clear(color) |
填充指定颜色。默认是黑色
1 | lcd.draw_string(x,y,str,color,bg_color) |
写字符
【x,y】起始坐标;
【str】字符内容
【color】字体颜色
【bg_color】字体背景颜色
1 | lcd.display(image,roi=Auto) |
显示图片。
【image】RGB565 或 GRAYSCALE 图片。
【ROI】显示的感兴趣区域,未指定则为图像大小。
1 | lcd.rotation(dir) |
LCD 屏幕方向设定。
【dir】取值范围[0-3],从 0 到 3 依顺时钟旋转。
1 | lcd.mirror(invert) |
镜面显示。
【invert】=True 则为镜面显示;=False 则否。
更多 LCD 模块说明请看 MaxiPy 官方文档:
https://wiki.sipeed.com/soft/maixpy/zh/api_reference/machine_vision/lcd.html
有了上面的对象构造函数和使用说明,编程可以说是信手拈来了,我们来跑
一下其主要功能显示字符和图像,代码编写流程如下:
1 | import lcd,image,utime |
摄像头应用
从前面的基础实验我们熟悉了 K210 基于 MicroPython 的编程方法,但那可以说是只发挥了 K210 冰山一角的性能应用,摄像头是整个机器视觉应用的基础。今天我们就通过示例代码来看看 pyAI-K210 是如何使用摄像头的。
MaixPy 机器视觉库代码大部分都是参考 OpenMV 移植过来,其已经将所有的摄像头功能封装到 sersor 模块中,用户可以通过调用轻松使用。这也是使用MicroPython 编程的魅力所在。
构造函数
sensor
摄像头对象,通过 import 直接调用
使用方法
1 | sensor.reset() |
初始化摄像头
1 | sensor.set_pixformat(*pixformat*) |
设置像素格式。pixformat 有 3 个参数。
sensor.GRAYSCAL:灰度图像,每像素 8 位(1 字节),处理速度快;
sensor.RGB565: 每像素为 16 位(2 字节),5 位用于红色,6 位用于绿色,5 位用于蓝色,处理速度比灰度图像要慢。
1 | sensor.set_framesize(*framesize*) |
设置每帧大小(即图像尺寸)。常用的 framesize 参数有下面这些:
sensor.QQVGA: 160*120;
sensor.QVGA: 320*240;
sensor.VGA: 640*480;
sensor.skip_frames([n, time])
摄像头配置后跳过 n 帧或者等待时间 time 让其变稳定。n:跳过帧数;time:等待
时间,单位 ms。
(如果 n 和 time 均没指定,则默认跳过 300 毫秒的帧。)
1 | sensor.snapshot() |
使用相机拍摄一张照片,并返回 image 对象。
*其它更多用法请阅读 MaixPy 官方文档:
https://wiki.sipeed.com/soft/maixpy/zh/api_reference/machine_visio
n/sensor.html
我们再来看看本例程用于计算 FPS(每秒帧数)的 clock 模块。
构造函数
1 | clock=time.clock() |
创建一个时钟。
使用方法
1 | clock.tick() |
开始追踪运行时间。
1 | clock.fps () |
停止追踪运行时间,并返回当前 FPS(每秒帧数)。
在调用该函数前始终首先调用 tick 。
*其它更多用法请阅读 Maixpy 官方文档:
文档链接:http://docs.openmv.io/library/omv.time.html
我们来看看 helloword 代码的编写流程图:
这个实验运行的就是编辑框里面的 helloworld 代码:
1 | import sensor, image, time, lcd |
画图
通过摄像头采集到照片后,我们会进行一些处理,而这时候往往需要一些图形来指示,比如在图片某个位置标记箭头、人脸识别后用矩形框提示等。本节就是学习在图形上画图的使用功能。
构造函数
1 | img=sensor.snapshot() 或 img=image.Image(path[, copy_to_fb=False]) |
创建图像,通过拍摄或者读取文件路径获取。
copy_to_fb=True**:可以加载大图片;
copy_to_fb=False:不可以加载大图片。
示例:img = image.Image(“01Studio.bmp”, copy_to_fb=True),表示加载根
目录下的 01Studio.bmp 图片。
使用方法
1 | image.draw_line(*x0*, *y0*, *x1*, *y1*[, *color*[, *thickness=1*]]) |
画线段。(x0,y0):起始坐标;(x1,y1):终点坐标;color:颜色,如
(255,0,0)表示红色;thickness:粗细。
1 | image.draw_rectangle(*x*, *y*, *w*, *h*[, *color*[, thickness*=1*[, *fill=False*]]]) |
画矩形。(x,y):起始坐标;w:宽度;h:长度;color:颜色;thickness:边框粗细;fill:是否填充。
1 | image.draw_circle(*x*, *y*, *radius*[, *color*[, thickness*=1*[, *fill=False*]]]) |
画圆。(x,y):圆心; radius:半径; color:颜色;thickness:线条粗细;
fill:是否填充。
1 | image.draw_arrow(*x0*, *y0*, *x1*, *y1*[, *color*[, size,[thickness*=1]*]]) |
画箭头。(x0,y0):起始坐标;(x1,y1):终点坐标;color:颜色;size:箭头位置大小。thickness:线粗细。
1 | image.draw_cross(*x*, *y*[, *color*[, *size=5*[, *thickness=1*]]]) |
画十字交叉。(x,y):交叉坐标;color:颜色;size:尺寸;thickness:线粗细。
1 | image.draw_string(*x*, *y*, *text*[, *color*[, *scale=*1[,*mono_space=True*…]]]]) |
写字符。(x,y): 起始坐标;text:字符内容;color:颜色;scale:字体大小;
mono_space:强制间距。
*其它更多用法请阅读 MaixPy 官方文档:
https://wiki.sipeed.com/soft/maixpy/zh/api_reference/machine_vision/image/image.html
熟悉了 image 对象的画图功能后,我们尝试在摄像头采集到的画面依次画出线段、矩形、圆形、箭头、十字交叉和字符。具体编程思路如下:
1 | import sensor, image, time, lcd |
颜色识别
我们活在一个色彩斑斓的世界里。本节我们来学习机器视觉中的颜色识别。我们会预先设定颜色阈值,如红、绿、蓝。这样 K210 摄像头采集图像后就能自动识别了。
通过编程实现 pyAI-K210 识别程序预先设定的颜色色块,分别是红、绿、蓝三种颜色。
MaixPy 集成了 RGB565 颜色块识别 find_blobs 函数,主要是基于 LAB 颜色模型(每个颜色都是用一组 LAB 阈值表示,有兴趣的用户可以自行查阅相关模型资料)。其位于 image 模块下,因此我们直接将拍摄到的图片进行处理即可,那么我们像以往一样像看一下本实验相关对象和函数说明,具体如下:
构造函数
1 | image.find_blobs(thresholds[,invert=False[,roi[,x_stride=2[,y_stride=1[,area_threshold=10[,pixels_threshold=10[,merge=False[,margin=0[, threshold_cb=None[, merge_cb=None]]]]]]]]]]) |
查找图像中指定的色块。返回 image.blog 对象列表;
【thresholds】 必须是元组列表。 [(lo, hi), (lo, hi), …, (lo, hi)] 定义你想追踪的颜
色范围。 对于灰度图像,每个元组需要包含两个值 - 最小灰度值和最大灰
度值。 仅考虑落在这些阈值之间的像素区域。 对于 RGB565 图像,每个元
组需要有六个值(l_lo,l_hi,a_lo,a_hi,b_lo,b_hi) - 分别是 LAB L,A 和 B
通道的最小值和最大值。
【area_threshold】若色块的边界框区域小于此参数值,则会被过滤掉;
【pixels_threshold】若色块的像素数量小于此参数值,则会被过滤掉;
【merge】若为 True,则合并所有没有被过滤的色块;
【margin】调整合并色块的边缘。
使用方法
以上函数返回 image.blob。
1 | blob.rect() |
返回一个矩形元组(x,y,w,h),如色块边界。可以通过索引[0-3]来获得这些值。
1 | blob.cx() |
返回色块(int)的中心 x 位置。可以通过索引[5]来获得这个值。
1 | blob.cy() |
返回色块(int)的中心 y 位置。可以通过索引[6]来获得这个值。
*更多使用说明请阅读官方文档:
https://wiki.sipeed.com/soft/maixpy/zh/api_reference/machine_vision/image/image.html
了解了找色块函数应用方法后,我们可以理清一下编程思路,代码编写流程如下:
参考代码如下:
1 | import sensor,lcd,time |
在 IDE 中运行代码,代码默认检测的是蓝色,用户可以自行修改 find_blobs()参数的阈值数组编号来切换识别颜色
二维码识别
相信大家都知道二维码了,特别是在扫描支付越来越流行的今天,二维码的应用非常广泛。今天我们就来学习如何使用 pyAI-K210 开发套件实现二维码信息识别
而对于 pyAI-K210 而言,直接使用 MicroPython 中的 find_qrcodes()即可获取摄像头采集图像中二维码的相关信息。具体说明如下:
构造函数
1 | image.find_qrcodes([roi]) |
查找 roi 区域内的所有二维码并返回一个 image.qrcode 的对象列表。
使用方法
以上函数返回 image.qrcode 对象列表。
qrcode.rect()
返回一个矩形元组(
x,y,w,h);
qrcode.payload()
返回二维码字符串信息。可以通过索引[4]来获得这个值。
qrcode.verison()
返回二维码版本号。
*更多使用说明请阅读官方文档:
从上表可以看到,使用 MicroPython 编程我们只需要简单地调find_qrcodes()函数,对得到的结果再进行处理即可,非常方便。代码编写流程如下图所示:
参考代码如下:
1 | import sensor,lcd,time |
人脸识别
pyAI-K210 开发套件,配 SD 卡放模型文件。
我们来简单介绍一下 K210 的 KPU。KPU 是 K210 内部一个神经网络处理器,它可以在低功耗的情况下实现卷积神经网络计算,实时获取被检测目标的大小、坐标和种类,对人脸或者物体进行检测和分类。
KPU 具备以下几个特点:
➢ 支持主流训练框架按照特定限制规则训练出来的定点化模型
➢ 对网络层数无直接限制,支持每层卷积神经网络参数单独配置,包括输
入输出通道数目、输入输 出行宽列高
➢ 支持两种卷积内核 1x1 和 3x3
➢ 支持任意形式的激活函数
➢ 实时工作时最大支持神经网络参数大小为 5.5MiB 到 5.9MiB
➢ 非实时工作时最大支持网络参数大小为(Flash 容量-软件体积)
简单来说就是 KPU 能加载和运行各种现成的 AI 算法模型,实现各种机器视
觉等功能。
MaixPy 中人脸识别本质是目标检测,主要通过在 K210 的 KPU 上跑 YOLO(You Only Look Once)目标检测算法来实现。我们来看一下 KPU 在 MaixPy 下的用法
构造函数
1 | import KPU as kpu |
常用的 KPU 模块导入方法。
使用方法
1 | kpu.load(offset or file_path) |
加载模型。
【offset】模型存放在 flash 的偏移量,如 0x300000;
【file_path】模型在文件系统为文件名,如“xxx.kmodel”
1 | kpu.init_yolo2(kpu_net,threshold,nms_value,anchor_num,anchor) |
初始化 yolo2 网络;
【kpu_net】kpu 网络对象;
【threshold】概率阈值;
【nms_value】box_iou 门限;
【anchor_num】描点数;
【anchor】描点参数与模型参数一致。
1 | kpu.run_yolo2(kpu_net,image) |
运行 yolo2 网络;
【kpu_net】从 kpu_load()中返回的网络对象;
【image】从 sensor 中采集到的图像
1 | kpu.deinit(kpu_net) |
反初始化。
【kpu_net】kpu 网络对象;
从上表可以看到通过 KPU 模块直接加载 YOLO2 网络,再结合人脸检测模型
来实现人脸识别。具体编程思路如下:
代码如下
1 | import sensor,lcd,time |
有了代码后我们还需要将模型放在文件系统中。这里介绍 2 个方法:
方法一:将模型放在 SD 卡中。
在本节示例程序路径中可以看到有 1 个件夹 face_model_at_0x300000将里面的 facedetect.kmodel 文件移动到 SD 卡,运行上述代码即可。
方法二:将模型烧录到 K210 的 Flash 中。
打开本节示例程序路径的件夹face_model_at_0x300000里面的flash-list.json文件,内容如下(告诉烧录软件烧写地址和文件名):
1 | { |
接下来直接将 kmodel 和 json 这两个文件用 zip 方式压缩(不要用文件夹),然后将 zip 后缀名改成 kfpkg,得到一个可以用 K210 固件烧录工具烧录的文件。
再使用 K210 固件烧录工具烧录直接烧录该文件即可,烧录软件会根据上述的 json 文件自动调整烧录地址,无需再次填写。
当我们去识别图片时候,可以将摄像头设置成后置,sensor 初始化时增加以
下代码:(LCD 装在 pyAI-K210 核心板背面,横屏测试。)
1 | sensor.set_vflip(1) #设置摄像头后置 |
物体识别
在上一节人脸检测章节我们已经介绍过 KPU 的用法,这里不再重复。本实验还是使用到 YOLO2 网络,结合 20class 模型(20 种物体分类模型)来识别图像中的物体。下面重温一下 KPU 的用法
构造函数
1 | import KPU as kpu |
常用的 KPU 模块导入方法。
使用方法
1 | kpu.load(offset or file_path) |
加载模型。
【offset】模型存放在 flash 的偏移量,如 0x300000;
【file_path】模型在文件系统为文件名,如“xxx.kmodel”
1 | kpu.init_yolo2(kpu_net,threshold,nms_value,anchor_num,anchor) |
初始化 yolo2 网络;
【kpu_net】kpu 网络对象;
【threshold】概率阈值;
【nms_value】box_iou 门限;
【anchor_num】描点数;
【anchor】描点参数与模型参数一致。
1 | kpu.run_yolo2(kpu_net,image) |
运行 yolo2 网络;
【kpu_net】从 kpu_load()中返回的网络对象;
【image】从 sensor 中采集到的图像
1 | kpu.deinit(kpu_net) |
反初始化。
【kpu_net】kpu 网络对象;
1 | import sensor,image,lcd,time |
在线训练模型
当我们想自己学习识别自
己的东西(比如键盘和鼠标的区分),就可以通过在线训练平台训练自己的模型。
在线训练上有完整的教程,这里不再重复
MaixHub 在线训练链接:https://maixhub.com/
当然上面也有很多现成别人训练好的模型可以直接使用,在模型库中选择
nncase 即可以看到适合 K210 使用的模型
图片拍摄
我们在前面摄像头应用章节已经学习过拍摄是使用 image=sensor.snapshot()函数模块,那么我们只需要学会将图片保存即可。保存也是可以直接使用 image下的 save 模块,具体如下:
构造函数
1 | img=sensor.snapshot() |
通过拍摄创建图像 img
使用方法
1 | image.save(*path*[, *roi*[, *quality=50*]]) |
保存图片。
path:保存路径;
roi:指定保存区域(x, y, w, h),默认全图保存;
quality:仅针对 JPEG 格式的质量控制,有效值为 0-100。
掌握了拍照和保存功能,我们就可以编程实现了,例程编程代码流程图如下:
代码如下
1 | import sensor, lcd, image |
视频录制
pyAI-K210 使用的 MaixPy 集成了 vedio 视频模块,也就是通过 MicroPython编程可以轻松实现录制视频功能,我们来看看 vedio 对象:
构造函数
1 | import vedio |
播放或录制视频文件。
【path】文件路径,比如:/sd/badapple.avi;
【record】=True 表示视频录制,=False 表示视频播放;
【interval】录制帧间隔,单位是微妙;FPS=1000000/interval,默认值
是 100000,即 FPS 默认是 10(每秒 10 帧);
【quality】jpeg 压缩质量(%),默认 50;
【width】录制屏幕宽度,默认 320;
【height】录制屏幕高度,默认 240;
【audio】是否录制音频,默认 False;
【sample_rate】录制音频采样率,默认 44100(44.1k);
【channels】录制音频声道数,默认 1,即单声道。
使用方法
1 | v.play() |
播放视频;
1 | v.volume([value]) |
设置音量值。
【value】0-100;
1 | v.revord () |
录制音视频;
1 | v.revord_finish () |
停止录制;
*更多使用说明请阅读官方文档:
https://maixpy.sipeed.com/zh/libs/machine_vision/video.html
学习了 vedio 的相关用法后,我们整理思路,代码编写流程如下:
参考代码
1 | import video, sensor, image, lcd, time |
人脸识别
1 |
|