博客专栏

EEPW首页 > 博客 > 在Raspberry Pi 4设计GUI介面,汇入机器学习模型实现人脸辨识篇

在Raspberry Pi 4设计GUI介面,汇入机器学习模型实现人脸辨识篇

发布人:DesignSparkCN 时间:2020-06-08 来源:工程师 发布文章

本文为前篇在"Raspberry Pi 4设计GUI介面来执行商品结账系统"的系列文章,将智能商店功能延伸,结合是否有人接近智慧商店,如果预测出人脸时则会播出欢迎光临的音频的功能,可使前篇文章更加完备。

全部源代码及设计文档,请点击 https://www.rs-online.com/designspark/raspberry-pi-4gui-3-cn


作者

许钰莨/曾俊霖

难度

简单

材料表

Raspberry Pi 4 (4GB)

SD卡(16G)

Mini HDMI传输线

一支网络摄影机

喇叭

屏幕、键盘、鼠标

 

本文章先备知识教学文章

使用Google Teachable Machine来实现Raspberry Pi 4 的影像分类推论

在Raspberry Pi 4设计GUI接口,汇入机器学习模型实现商品结账应用

本篇文章完整范例程序请由本文最下方附件下载

 

笔者在使用Teachable Machine时,发现网站除了可以分辨对象的图像外,也能分辨人脸,故智能商店才将此功能结合进去。本主题会将焦点会放在脸部的图像分类,在Teachable Machine收集人脸资料后,导出人脸的模型档案后,再使用Tkinter 的图形化接口设计一套分辨人脸系统。

 

本文将分成下列几个步骤来完成此专题

1.在Teachable Machine 收集人脸数据,并可以在网站上实时推论人脸图像

2.将模型汇入到RPI4,并可执行人脸图像分类程序

3.设计人脸GUI图形化接口之程序说明,并执行智能商店人脸程序

 

1.在Teachable Machine 收集人脸数据,并可以在网站上实时推论人脸图像

 

先在Teachable Machine网页训练人脸模型,相关步骤可以参考"使用Google Teachable Machine 来实现Raspberry Pi 4 的影像分类推论",考虑到一般的商店的结账系统,只要有人即可结账,并不会去纪录人名,所以在Teachable Machine 的模型卷标只有两种情形,有人和无人。

 

因为只要判别是否有人接近,所以笔者是到网络上收集男性和女性,东方人或西方人的脸孔图片约莫共120张,直接上传至"people"的标签中,读者也可以程序下载区Store-->face_dataset文件夹中找到图片,并且全选上传。另外当初也有想过拍照,但是拍的人数样本太少,不如直接上网收集人脸图片,也考虑到不同的肤色、年龄、地方相关的因素。

而收集没有人脸的图片则是可以直接设定用Webcam拍照即可。

 

设定计算机使用的摄影机,本次使用Webcam的是Logi C170

 

另外,建议可以在计算机外接一个Webcam,收集图片较为方便。

 

按下"Train Model" 即可开始训练模型。

 

 

 

因为在训练集中放入了相同两张有带口罩的人脸,所以即使戴着口罩,推论出来的结果也可以分类得出来是"people"。

 

无人脸接近则是"no_people"

 

但如果人脸太远离镜头,则也会被分类到"no_people"

 

输出模型

 

 

2.将模型汇入到RPI4,并可执行人脸图像分类程序

点选Tensorflow Lite -->Quantized-->Download my model

 

下载得到扩展名[专案名称]+.txt、.tflite的两个档案

 

请将下载的文件夹解压缩后,将两个档名分别改成"label_face.txt"和"model_face.tflite",并传送数据到Rpi4 的"Store"文件夹中。

 

在"Store"文件夹中有"TM2_tflite_new.py",可以执行程序,并将有无人脸的状态显示及预测值显示在窗口上面。

先移动文件夹位置到Store

$ cd Store/

 

执行程序

$ python3 TM2_tflite_new.py --model model_face.tflite --label labels_face.txt

 

在执行程序的窗口中,笔者有将结果显示在窗口上,"0"为标签、"people"为预测出人脸的名称、"0.9921875"为预测值,说明能分辨出人脸类别的预测值为99%。

 

3.设计人脸GUI图形化接口之程序说明,并执行智能商店人脸程序 3-1人脸GUI图形化接口程序说明

设定窗口大小 300*300像素

 self.window.geometry('300x300')
 self.window.resizable(False, False)

 

开启Webcam摄影机

self.vid_0 = MyVideoCapture(self.video_source_0)

 

建立人脸尺寸为240*180像素的图像画布

self.canvas_face = tkinter.Canvas(window, width = 240, height = 180)

 

设置画布尺寸窗口中的于第0行第0列,在grid网格中使用"sticky"参数,是west向左对齐

self.canvas_face.grid(row=0, column=0, sticky="w")

 

建立具有拍照功能按钮,并名称为"Face",排列在第1行第0列

tkinter.Button(window, text="Face", command=self.face).grid(row=1, column=0)

 

Webcam得到影像后,必须使用PIL套件,才能在Tkinter 画布中显示动态影像。

  def face(self):
        ret_0, frame_0 = self.vid_0.get_frame()

        if (ret_0):
            Face_class(frame_0)
            

    def update(self):
        ret_0, frame_0 = self.vid_0.get_frame()
        
        
        #调整Webcam影像之画面大小,需和Tkinter画布同尺寸
        frame_0_small=cv2.resize(frame_0,(240,180))
        
      
        if ret_0:
            self.photo_2 = PIL.ImageTk.PhotoImage(image = PIL.Image.fromarray(frame_0_small))
            self.canvas_face.create_image(241,0,image = self.photo_2, anchor="ne")
   

        self.window.after(self.delay, self.update)

 

Webcam影像画面相关尺寸大小设定

class MyVideoCapture:
    def __init__(self, video_source):
    
        #将原本Webcam影像画面大小设定为320X240
        self.vid = cv2.VideoCapture(video_source)
        self.vid.set(cv2.CAP_PROP_FRAME_WIDTH,320)
        self.vid.set(cv2.CAP_PROP_FRAME_HEIGHT,240)
        

        if not self.vid.isOpened():
            raise ValueError("Unable to open video source", video_source)

        # 设定视讯来源的尺寸
        self.width = self.vid.get(cv2.CAP_PROP_FRAME_WIDTH)
        self.height = self.vid.get(cv2.CAP_PROP_FRAME_HEIGHT)

    def get_frame(self):
        if self.vid.isOpened():
            ret, frame = self.vid.read()
            if ret:
                # 将影像画面转换成RGB格式
                return (ret, cv2.cvtColor(frame, cv2.COLOR_BGR2RGB))
            else:
                return (ret, None)
        else:
            return (ret, None)

    # 释放影像资源
    def __del__(self):
        if self.vid.isOpened():
            self.vid.release()

 

做人脸图像推论,若侦测到人脸时则显示"欢迎光临智能商店",讯息会排序在第2行第0列中显示出来,并播放欢迎词音讯,也同时启动拍照功能。

class Face_class:
    def load_labels(self,path):
        with open(path, 'r') as f:
            return {i: line.strip() for i, line in enumerate(f.readlines())}

    def set_input_tensor(self, interpreter, image):
        tensor_index = interpreter.get_input_details()[0]['index']
        input_tensor = interpreter.tensor(tensor_index)()[0]
        input_tensor[:, :] = image    def classify_image(self, interpreter, image, top_k=1):
        self.set_input_tensor(interpreter, image)
        interpreter.invoke()
        output_details = interpreter.get_output_details()[0]
        output = np.squeeze(interpreter.get_tensor(output_details['index']))

        # If the model is quantized (uint8 data), then dequantize the results
        if output_details['dtype'] == np.uint8:
            scale, zero_point = output_details['quantization']
            output = scale * (output - zero_point)

        ordered = np.argpartition(-output, top_k)
        return [(i, output[i]) for i in ordered[:top_k]]

    def __init__(self,image_src):
        labels = self.load_labels('/home/pi/Store/labels_face.txt')

        interpreter = Interpreter('/home/pi/Store/model_face.tflite')
        interpreter.allocate_tensors()
        _, height, width, _ = interpreter.get_input_details()[0]['shape']

        image=cv2.resize(image_src,(224,224))

        results = self.classify_image(interpreter, image)
        label_id, prob = results[0]
        
        
        if (labels[label_id] == "1 no_people"):
            labelExample = tkinter.Label(text="____________________")
            labelExample.grid(row=2, column=0)
       
            
        else :
            labelExample = tkinter.Label(text="____________________")
            labelExample.grid(row=2, column=0)
            labelExample = tkinter.Label(text="欢迎光临智慧商店")
            labelExample.grid(row=2, column=0)

            #开启拍照功能并存在face_collect文件夹中
            cv2.imwrite("face_collect/" + "face-" + time.strftime("%d-%m-%Y-%H-%M-%S") + ".jpg", cv2.cvtColor(image_src, cv2.COLOR_RGB2BGR))

            #播放欢迎光临音讯文件
            file=r'/home/pi/Store/welcome.mp3'
            while (pygame.mixer.music.get_busy()!=1):
                track = pygame.mixer.music.load(file) 
                pygame.mixer.music.play()#窗口标题为"智能商店"App(tkinter.Tk(), "智慧商店")

 

3-2 执行程序画面及组件位置

 

执行Python程序

$python3 tk_cv_face.py

 

Tkinter排列的组件,分别为画布(Canvas)在第0行第0列、"Face"按钮(Button)在第1行第0列、文字卷标(Label)在第2行第0列。侦测到人脸时,除了可以播放音讯档案外,也同时会开启拍照功能,其目的在于收集使用者脸孔,可以达成两种目的,一、可以大致推论出性别或年龄,哪种族群较多人使用。二、可重新训练模型,虽然google taechable machine在一般的情况下已经可以侦测人脸,但数据集中却没有使用者的照片,会使得预测有稍微的偏差,若要符合真实情形,则需要将收集到的人脸照片到google taechable machine再做一次训练。



*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。



关键词:

相关推荐

技术专区

关闭