【DigiKey创意大赛】家庭共享智能药盒04+人脸分辨程序设计
[复制链接]
本帖最后由 oet 于 2024-10-18 20:57 编辑
上一贴介绍了设计PCB和调试BME280,给OPENMV增加了显示模块和传感器。本帖介绍人脸分辨程序的设计过程。
基于OPENMV的人脸分辨程序设计在星瞳官网有一个专门的教程,链接如下:
里面还有对应的视频,将原理讲解的比较明白。主要是使用OPENMV系统自带的LBP算法实现人脸分辨。
最开始我使用官网例程进行学习,请家人做模特照相,调试程序。如下图是试验的文件。
效果基本和官网视频介绍的相当,但是需要手工在TF卡上建立文件,然后分别录入图片,整个操作流程繁琐,结构松散,想整合到我这次作品中,有点无从下手。
思虑后我打算参考例程自己从新写个程序,实现我这次特定的功能。我先把程序需求想好了,然后备忘就在记事本上记下来了。恰好当时正在给孩子处理作业的事情,使用Kimi找算术题,造句等,借助AI给孩子辅导作业很方便。这个弄完我突然想到,何不让AI帮我写程序呢,试试又不花钱,说干就干。
我把之前写好的需求直接输入Kimi,经过它的一通查询,果然给我弄出一篇代码,我仔细读后发现有些问题,开始手动修改代码。然后出来第一版能凑合运行的框架程序,但是距离能用还差很远。
本来打算放弃了,但是又有点不甘心,就又尝试告诉Kimi,指明它生成的代码有哪些不足,让它自己修改,然后我就发现它果然能改好,这让我大喜,我就按照和同事沟通一样,不停的多次沟通,它就不停的迭代生成的代码。如下图是某次沟通截图。
使用Kimi关键是文字需求描述要清晰准确,下图是我三次更改描述语句,让Kimi进行程序生成。
经过七次大版本迭代,终于搞出一版在程序结构,功能实现上基本都能满足要求的代码。下图是我保存的历次大版本代码。
直接生成的代码,在编译运行时还是有些问题的,下面是直接生成的代码,大家可以看看有什么问题。
代码1:
-
- import sensor, image, time, pyb, os
- from fpioa_manager import fm, board_info
- from Maix import GPIO
- from display import SPIDisplay
-
-
- sensor.reset()
- sensor.set_pixformat(sensor.GRAYSCALE)
- sensor.set_framesize(sensor.QVGA)
- sensor.skip_frames(time=2000)
- sensor.set_auto_gain(False)
- sensor.set_auto_whitebal(False)
-
-
- uos.mount(sdcard, '/sd')
-
-
- led = pyb.LED(1)
-
-
- uart3 = pyb.UART(3, 115200)
-
-
- lcd = SPIDisplay(width=132, height=132, bgr=True)
- lcd.init()
-
-
- THRESHOLD = 50
-
-
- def capture_face(index):
- if not os.path.exists('/sd/{}'.format(index)):
- os.mkdir('/sd/{}'.format(index))
- for i in range(10):
- img = sensor.snapshot()
- img = img.resize(128, 128)
- lcd.display(img)
- lbp = img.find_lbp((0, 0, img.width(), img.height()))
- lbp.save('/sd/{}/face_{}.lbp'.format(index, i))
- led.on()
- time.sleep(100)
- led.off()
- time.sleep(900)
-
-
- def receive_and_capture():
- while True:
- data = uart3.read()
- if data:
- cmd = data.decode()[0]
- if cmd.isdigit() and int(cmd) in range(1, 7):
- capture_face(cmd)
- elif cmd == 'r':
- face_recognition()
-
-
- def face_recognition():
- img = sensor.snapshot()
- img = img.resize(128, 128)
- lcd.display(img)
- lbp = img.find_lbp((0, 0, img.width(), img.height()))
- min_diff = 999999
- recognized = None
- for folder in range(1, 7):
- for i in range(10):
- template_file = '/sd/{}/face_{}.lbp'.format(folder, i)
- if os.path.exists(template_file):
- template = image.load(template_file)
- diff = image.match_descriptors(lbp, template)
- if diff < min_diff:
- min_diff = diff
- recognized = folder
- if min_diff < THRESHOLD:
- uart3.write('{}\n'.format(recognized))
- else:
- uart3.write('0\n')
-
- img.draw_string(10, 10, "Recognizing...", color=(255), scale=2)
- if recognized:
- img.draw_string(10, 40, "Match Found!", color=(255), scale=2)
- else:
- img.draw_string(10, 40, "No Match Found", color=(255), scale=2)
- lcd.display(img)
-
-
- def main():
- while True:
- data = uart3.read()
- if data:
- cmd = data.decode()[0]
- if cmd == 'r':
- face_recognition()
- elif cmd.isdigit() and int(cmd) in range(1, 7):
- capture_face(cmd)
-
- if __name__ == '__main__':
- main()
经过我的修改,最终能运行的代码:
代码2:
-
-
-
-
-
-
- import time, os, pyb
- import display
- import sensor, image, machine
-
-
- sensor.reset()
- sensor.set_pixformat(sensor.GRAYSCALE)
-
-
- sensor.set_framesize(sensor.B128X128)
- sensor.skip_frames(time=200)
- sensor.set_auto_gain(False)
- sensor.set_auto_whitebal(False)
-
-
-
-
-
- led = pyb.LED(1)
-
-
- uart3 = pyb.UART(3, 115200)
-
-
- lcd = display.SPIDisplay( width=132, height=132,bgr=True)
-
-
- print("start ok")
-
- THRESHOLD = 2600
-
-
- def capture_face(index):
- if not '{}'.format(index) in os.listdir():
- os.mkdir('{}'.format(index))
- print("mkdir ok")
-
- for i in range(10):
- led.on()
- time.sleep_ms(100)
- img = sensor.snapshot()
- lcd.write(img)
- img.save('/{}/face_{}.pgm'.format(index, i))
- print('/{}/face_{}.pgm'.format(index, i))
- led.off()
- time.sleep_ms(900)
-
-
- def receive_and_capture():
- while True:
- data = uart3.read()
- if data:
- cmd = data.decode()[0]
- if cmd.isdigit() and int(cmd) in range(1, 7):
- capture_face(cmd)
- elif cmd == 'r':
- face_recognition()
-
-
- def face_recognition():
- img = sensor.snapshot()
- lcd.write(img)
- lbp = img.find_lbp((0, 0, img.width(), img.height()))
- min_diff = 999999
- recognized = None
- img_temp = img
- for folder in range(1, 7):
- for i in range(10):
- if '{}'.format(folder) in os.listdir():
- template_file = '/{}/face_{}.pgm'.format(folder, i)
- img = image.Image(template_file)
- template = img.find_lbp((0, 0, img.width(), img.height()))
- diff = image.match_descriptor(lbp, template)
- if diff < min_diff:
- min_diff = diff
- recognized = folder
- print(min_diff,recognized)
- img_temp = img
- else:
- print("no dir:"+template_file)
- if min_diff < THRESHOLD:
- uart3.write('{}\n'.format(recognized))
- print('{}\n'.format(recognized))
- img_temp.draw_string(5, 120, "Match Found!", color=(255), scale=1)
- else:
- uart3.write('0\n')
- print('0\n')
- img_temp.draw_string(5, 120, "No Match Found", color=(255), scale=1)
-
- lcd.write(img_temp)
-
-
- def main():
- img = sensor.snapshot()
- lcd.write(img)
- while True:
- data = uart3.read()
- if data:
- cmd = data.decode()[0]
- if cmd == 'r':
- face_recognition()
- elif cmd.isdigit() and int(cmd) in range(1, 7):
- capture_face(cmd)
-
- if __name__ == '__main__':
- main()
-
代码编辑好后就是做实验了。这个时候再找家人不停地拍照太麻烦了,我就想直接从网上找现成的照片进行测试也一样啊。经过资料查找,最终确定使用《CK表情分类数据集》。这个数据集中,包含多个人的各种表情图片,每种表情记录了几张到十几张图片不等,其中每个人图片总数都在几十张以上,我选取了7个人,使用每个人部分图片作为训练对比参考,剩余的作为测试图片,这样一下子解决了需要不同人拍照问题。
我只需在另外一个显示器上显示参考或测试图片,把摄像头调整好距离,就能完美测试了。下图是实际调试拍照,测试效果很好。
在OpenMV IDE输出调试信息显示程序运行正确无误。
在串口终端也完全实现了预期的发送指令和接收结果的功能。
通过以上测试,确认这个AI生成的程序完全实现了预期的功能。
从此之后,我又多了一个好帮手,编写简单程序,只需要把需求写清楚,让Kimi帮忙实现,不但效率高,还省脑细胞!
|