要实现人脸追踪,第一步就是要实现人脸的检测。
人脸检测属于机器学习里非常常规的应用。一般情况下,我们不需要去自己训练模型,可以试用官方准备好的模型,在下面链接下载face_model_at_0x300000.kfpkg模型文件:
https://dl.sipeed.com/MAIX/MaixPy/model
下载完成后,需要通过和上一期更新固件时同样的工具kflash_gui把模型刷写到开发板上:
不需要担心这个刷写会覆盖掉我们之前刷写的bin固件。因为这次刷写的文件是kfpkg文件,这个文件中有记载文件应该被刷写道flash的什么位置。
MaixPy 中的存储介质主要由 Flash,SD 卡组成,分为三块区域,分别是 MaixPy.bin 固件区,xxx.kmodel 模型区,文件系统区:Flash 上为 spiffs(SPI Flash File System),SD 卡为 Fatfs(FAT file system)。可以从下图中看到储存系统的分配,因此相互之间不会影响。
接下来加载模型,只需要把模型的刷鞋地址作为参数传递给函数即可。
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)
其中,anchor元组是锚点参数,这个参数与模型是一一对应的,也就是说,这个元组我们不可以去做任何自行修改,一定要保持一模一样。
init_yolo2这个函数可以初始化模型。我们可以看到中间有两个浮点数参数。其中第一个参数是概率阈值, 只有是这个物体的概率大于这个值才会输出结果, 取值范围:[0, 1];第二个参数是box_iou 门限, 为了防止同一个物体被框出多个框,当在同一个物体上框出了两个框,这两个框的交叉区域占两个框总占用面积的比例 如果小于这个值时, 就取其中概率最大的一个框。
接着我们准备好想要识别的图片实体,这个图片通过摄像头获得。首先我们初始化摄像头:
import sensor
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
接着,通过下面这个函数就可以抓取到照片,并保存为img变量
img = sensor.snapshot()
得到照片后,将照片放入模型中进行识别,识别出的结果是一个可以遍历的实体,里面每一个元素就是我们识别到的每一个人脸。 因为图像中的人脸可能不止一个,但追踪时我们只能选择最近的追踪。因此我们可以遍历每一个识别到的人脸,选择最大的哪个,把它的框画在图上。
objects = kpu.run_yolo2(self.task, img)
if objects:
max_area = 0
max_i = 0
for i, j in enumerate(objects):
a = j.w()*j.h()
if a > max_area:
max_i = i
max_area = a
img.draw_rectangle(objects[max_i].rect())
最后,我们可以把识别到的图像显示在LCD上。同样的,先要初始化LCD,只需一行代码即可完成。接着显示图片即可。
import lcd
lcd.init(type=1)
lcd.display(img)
如果一切顺利,逐行运行上述代码,如果图像中有人脸,我们可以看到LCD上显示出了对应的识别结果:
完整代码如下:
import sensor, image, lcd, time
import KPU as kpu
import gc, sys
def lcd_show_except(e):
import uio
err_str = uio.StringIO()
sys.print_exception(e, err_str)
err_str = err_str.getvalue()
img = image.Image(size=(224, 224))
img.draw_string(0, 10, err_str, scale=1, color=(0xFF, 0x00, 0x00))
lcd.display(img)
def main(model_addr=0x300000, lcd_rotation=2, sensor_hmirror=False, sensor_vflip=False):
try:
sensor.reset()
except Exception as e:
raise Exception(
"sensor reset fail, please check hardware connection, or hardware damaged! err: {}".format(
e
)
)
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_hmirror(sensor_hmirror)
sensor.set_vflip(sensor_vflip)
lcd.init(type=1)
lcd.rotation(lcd_rotation)
clock = time.clock()
anchors = (
1.889,
2.5245,
2.9465,
3.94056,
3.99987,
5.3658,
5.155437,
6.92275,
6.718375,
9.01025,
)
try:
task = kpu.load(model_addr)
kpu.init_yolo2(task, 0.5, 0.3, 5, anchors) # threshold:[0,1], nms_value: [0, 1]
while True:
clock.tick()
img = sensor.snapshot()
objects = kpu.run_yolo2(task, img)
if objects:
for obj in objects:
img.draw_rectangle(obj.rect())
center = (
round(obj.x() + obj.w() / 2, 1),
round(obj.y() + obj.h() / 2, 1),
)
else:
center = "N/A"
img.draw_string(0, 200, "FPS: %f" % (clock.fps()), scale=2)
img.draw_string(0, 220, "Center: %s" % str(center), scale=2)
lcd.display(img)
except Exception as e:
raise e
finally:
if not task is None:
kpu.deinit(task)
if __name__ == "__main__":
try:
main()
except Exception as e:
sys.print_exception(e)
lcd_show_except(e)
finally:
gc.collect()