【K210】人脸识别 KPU-kpu.run_yolo2()函数说明

零、摄像头采集图像

img = sensor.snapshot()

这里 img 就可以直接作为输入, 这里需要 注意snapshot() 函数采集到图片后,会将图片数据放到两个地方
(1) RGB565 内存块, 图像以 RGB565 的形式存放在一块内存中,方便图像处理的函数使用,注意在内存中的排序是 [像素1 RGB, 像素2 RGB...]
(2) RGB888 内存块, 图像以 R8G8B8 的形式存放在另一块内存中,注意在内存中的排序是 [所有像素 R, 所有像素 G, 所有像素 B], 我们也称之为 AI 内存
直接从摄像头采集的图像会自动填充 RGB888 区域,但是我们使用图像处理函数比如 image.resize() 时,只会修改 RGB565,没有修改 RGB888,因为同时修改两处内存需要耗费大量时间,而 KPU 的输入又是 RGB888 内存块, 所以在需要进行 KPU 运算时, 需要同步(刷新)一下 RGB888 内存块, 使用 img.pix_to_ai() 来进行同步,否则先前的修改将不会在 KPU 上生效。
参考:https://wiki.sipeed.com/soft/maixpy/zh/course/ai/basic/maixpy_hardware_ai_basic.html

一、图像缓冲区介绍#

MaixPy 为图像设计了两个缓冲区,

  • 一个是RGB565缓冲区,顾名思义, 是以RGB565的格式存放这图片的信息的一块内存。注意在内存中的排序是[像素1 RGB, 像素2 RGB...]
  • 另一个是RGB888缓冲区,顾名思义, 是以RGB88的格式存放这图片的信息的一块内存。注意在内存中的排序是[所有像素 R, 所有像素 G, 所有像素 B], 我们也称之为AI内存

这里使用两个内存块主要的原因是底层代码所有图片操作以及LCD显示均是基于RGB565, 但是KPU又需要RGB888的输入。

                   +---------------+
                   |               |
          +--------+ camera(sensor)+-------+
          |        |               |       |
          |        +---------------+       |
          |                                |
+---------v------+                +--------v---------+
|                | img.pix_to_ai()|                  |
|      RGB565    +--------------->+      RGB888      |
|                |                |                  |
+--------+-------+                +------+-----------+
         ^                               |
         |                               |
         |                               v
+--------+----------+             +------+-----------+
|                   |             |                  |
|     image ops     |             |   KPU            |
|                   |             |                  |
+-------------------+             +------------------+

只有摄像头采集图片时,硬件会自动放一份数据到RGB888内存区域, 其它的都不会自动填充RGB888内存块, 软件操作只会对RGB565内存进行操作,不会自动更新RGB888,(因为更新需要消耗时间) 这很值得注意,
这意味着,每次我们用更改了RGB565内存块,比如执行了img = img.resize((224, 224)),如果希望KPU使用更改过后的图片, 需要执行img.pix_to_ai()来将RGB565的图像手动更新到RGB888的区域,然后才可以调用kpu相关的函数进行模型推理!

同样反方向更新也提供 API: img.ai_to_pix(), 这会将RGB888区域的数据更新到RGB565区域

二、KPU函数说明

yolo2网络模型传入初始化参数, 只有使用yolo2时使用

KPU.init_yolo2(kpu_net, threshold, nms_value, anchor_num, anchor)
import KPU as kpu
task = kpu.load(0x300000)
anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025)
kpu.init_yolo2(task, 0.5, 0.3, 5, anchor)

参数#

  • kpu_net: kpu 网络对象, 即加载的模型对象, KPU.load()的返回值
  • threshold: 概率阈值, 只有是这个物体的概率大于这个值才会输出结果, 取值范围:[0, 1]
  • nms_value: box_iou 门限, 为了防止同一个物体被框出多个框,当在同一个物体上框出了两个框,这两个框的交叉区域占两个框总占用面积的比例 如果小于这个值时, 就取其中概率最大的一个框
  • anchor_num: anchor 的锚点数, 这里固定为 len(anchors)//2
  • anchor: 锚点参数与模型参数一致,同一个模型这个参数是固定的,和模型绑定的(训练模型时即确定了), 不能改成其它值。

返回值#

successbool类型, 是否成功

#sensor.set_framesize(sensor.QQVGA)    # 设置图像分辨率 (160*120)
sensor.set_framesize(sensor.QVGA)    # 设置图像分辨率 (320*240)
img = sensor.snapshot()            # 摄像头采集到的一帧图片
objects = kpu.run_yolo2(task, img) #运行yolo2, 返回一个kpu_yolo2_find 列表
#返回值说明: 是以下的形式 类型为Python中的list xy表示 矩形框左上角的元素位置,wh表示矩形的宽度和高度
#{"x":158, "y":65, "w":83, "h":111, "value":0.829885, "classid":0, "index":0, "objnum":1}
#{"x":158, "y":66, "w":83, "h":111, "value":0.829885, "classid":0, "index":0, "objnum":1}

#注意:如果是以下情况: 运行会报错:
#解释:因为摄像头采集到的图像格式是RGR565格式,在内存中的排序是[像素1 RGB, 像素2 RGB...]  
#而KPU需要 RGB888格式,在内存中的排序是[所有像素 R, 所有像素 G, 所有像素 B], 我们也称之为AI内存

#第一种情况: img 的格式不对     报错: check img format err
img = sensor.snapshot()            #默认分辨率为 320*240
img = img.resize(224, 224)         # 修改分辨率为  224*224
objects = kpu.run_yolo2(task, img) #运行yolo2, 返回一个kpu_yolo2_find 列表

#第二种情况: img 的分辨率不对   报错: check img format err
img = sensor.snapshot()            #默认分辨率为 320*240
img1 = img.copy(roi=(0, 0, 300, 240))  #复制一份图像内存,大小为 300*240
objects = kpu.run_yolo2(task, img1) #运行yolo2, 返回一个kpu_yolo2_find 列表

##第二种情况: 若设置sensor.set_framesize(sensor.QQVGA)    # 设置图像分辨率 (160*120) 再执行以下函数,也会报错格式不对
sensor.set_framesize(sensor.QQVGA)   #认分辨率为 160*120 
img = sensor.snapshot()           
objects = kpu.run_yolo2(task, img1) 


objects.rect()
#返回值:返回一个矩形元组(x, y, w, h),用于如 矩形的边界框的 image.draw_rectangle 等其他的 image 方法。
#(143, 46, 83, 111)
#(132, 48, 82, 111)
#(121, 49, 82, 111)


img = sensor.snapshot() 
print(img) 
#{"w":320, "h":240, "type"="rgb565", "size":153600}
#{"w":320, "h":240, "type"="rgb565", "size":153600}

img = sensor.snapshot() 
img = img.copy([roi[, copy_to_fb=False]]#创建一个图像对象的副本。
#Roi 是一个用以复制的矩形的感兴趣区域(x, y, w, h)。如果未指定,ROI即复制整个图像的图像矩形。但这不适用于JPEG图像。
#请记住图像副本储存在MicroPython 堆中而不是帧缓冲区。同样,您需要将图像副本大小控制在8KB以下(OpenMV)或16KB以下(OpenMV Cam M7) 如果您想使用一个复制操作来使用所有的堆空间,这个函数会出现异常。过大的图像极易触发异常。
#如果 copy_to_fb 为True,则该方法将帧缓冲替换为图像。 帧缓冲区具有比堆大得多的空间,并且可以容纳大图像。

参考:
基本图像变换 和 常用操作

MaixPy(3)人脸检测与人脸识别

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年8月8日
下一篇 2023年8月8日

相关推荐