m0_70397448 2022-04-30 19:41 采纳率: 100%
浏览 47
已结题

对以下代码结合实际写个详细的注释,阐述其中的原理?

这是个人脸表情识别的UI界面,麻烦给个详细的注释,最好是行注释,因为对这些库都不太熟悉

import operator
import os
import time
import cv2
from PySide2 import QtGui
from PySide2.QtWidgets import QFileDialog, QApplication
from PySide2.QtUiTools import QUiLoader
import numpy as np
import torch
import torch.nn as nn
from torchvision import models, transforms
from PIL import Image


def cvImgtoQtImg(cvImg, isConvertToGray=False):
    if isConvertToGray:
        QtImgBuf = cv2.cvtColor(cvImg, cv2.COLOR_BGR2GRAY)
        QtImg = QtGui.QImage(QtImgBuf.data, QtImgBuf.shape[1], QtImgBuf.shape[0], QtGui.QImage.Format_Grayscale8)
    else:
        QtImgBuf = cv2.cvtColor(cvImg, cv2.COLOR_BGR2RGBA)
        QtImg = QtGui.QImage(QtImgBuf.data, QtImgBuf.shape[1], QtImgBuf.shape[0], QtGui.QImage.Format_RGBA8888)
    return QtImg


class Stats:

    def __init__(self):
        self.open = False
        self.ui_face = QUiLoader().load('ui/demo.ui')
        self.ui_face.setFixedSize(1239, 824)
        self.ui_face.btn_open_cap.clicked.connect(self.opt_cap)
        self.ui_face.btn_predict.clicked.connect(self.cap)
        self.ui_face.btn_open_res.clicked.connect(self.load_pic)
        self.model, self.model_ft = self.load_model()

    def load_pic(self):
        filePaths, _ = QFileDialog.getOpenFileName(
            self.ui_face,
            "请选择将要转换的文件",
            os.path.join(os.path.expanduser('~'), "Desktop"),
            "文件类型 (*.jpg)"
        )
        self.ui_face.edt_res.setText(filePaths)
        self.img = cv2.imread(filePaths)
        show = cv2.resize(self.img, (640, 480))
        show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)
        showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)
        self.ui_face.ImgDisp.setPixmap(QtGui.QPixmap.fromImage(showImage))


    def opt_cap(self):
        if self.open == True:
            self.open = False
            self.ui_face.edt_cap.setText('摄像头已关闭')
        else:
            self.open = True
            self.ui_face.edt_cap.setText('摄像头已打开')
            self.start()

    def start(self):
        self.cap = cv2.VideoCapture(0)
        self.cap.set(3, 640)
        self.cap.set(4, 480)
        self.cap.set(10, 100)
        while True:
            success, self.img = self.cap.read()
            self.img = cv2.flip(self.img, 1)
            show = cv2.resize(self.img, (640, 480))
            show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)
            showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)
            self.ui_face.ImgDisp.setPixmap(QtGui.QPixmap.fromImage(showImage))
            cv2.waitKey(0)
            if self.open == False:
                break
        print('展示图片')

    def cap(self):
        try:
            image = Image.fromarray(cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB))
            output = self.predict(image, self.model_ft)
            ret = []
            emo = ['surprized', 'happy', 'disgust', 'normal', 'fear', 'anger', 'sad']
            for index, value in enumerate(self.model):
                dis = np.linalg.norm(value - output)  # 欧氏距离
                ret.append({'category': emo[index], 'dis': dis})
            ret = sorted(ret, key=operator.itemgetter('dis'), reverse=False)
            print(ret)
            self.ui_face.label_ret.setText('识别结果为:' + ret[0]['category'])
            self.ui_face.label_ret_0.setText('0:' + ret[0]['category'])
            self.ui_face.label_ret_1.setText('1:' + ret[1]['category'])
            self.ui_face.label_ret_2.setText('2:' + ret[2]['category'])
            self.ui_face.label_ret_3.setText('3:' + ret[3]['category'])
            self.ui_face.label_ret_4.setText('4:' + ret[4]['category'])
            self.ui_face.label_ret_5.setText('5:' + ret[5]['category'])
            self.ui_face.label_ret_6.setText('6:' + ret[6]['category'])
        except:
            pass

    def load_model(self):
        # 这一块是对图片特征进行提取
        model_path = 'model/weights.pth'
        # build model
        model_ft = models.resnet34(pretrained=False)
        num_ftrs = model_ft.fc.in_features
        model_ft.fc = nn.Sequential(
            nn.Dropout(0.5),
            nn.Linear(num_ftrs, 7),
            nn.Softmax(dim=1)
        )
        model_ft.load_state_dict(torch.load(model_path))
        model_ft.eval()
        # 参数写到这里,得到的中心点遍历一下  然后写到这里
        model = [
            [2.0667151e-04, 3.4240412e-04, 1.4473200e-02, 8.0134422e-03, 6.0332119e-03,
             7.7563822e-03, 9.6317458e-01],
            [2.5990081e-04, 2.7968729e-04, 1.8215105e-02, 9.3163711e-01, 5.1174462e-03,
             6.0818493e-03, 3.8408846e-02],
            [0.00336622, 0.00619731, 0.10314032, 0.20358741, 0.27171963, 0.26114,
             0.1508491],
            [2.0508033e-04, 3.2301957e-04, 8.1134737e-03, 5.8690608e-03, 9.5963997e-01,
             1.0704219e-02, 1.5145153e-02],
            [4.1064431e-04, 1.2989613e-03, 8.9172471e-01, 2.3929298e-02, 1.7944381e-02,
             2.8446108e-02, 3.6245927e-02],
            [0.0014531, 0.00288311, 0.21803668, 0.1291624, 0.06903042, 0.04348047,
             0.5359538],
            [2.0752930e-04, 4.1509242e-04, 8.1426501e-03, 7.6724142e-03, 8.2466751e-03,
             9.6485263e-01, 1.0462716e-02]
        ]
        return model, model_ft

    def predict(self, image, model):
        time_s = time.time()
        transform = transforms.Compose([
            transforms.Resize(224),
            transforms.ToTensor(),
            transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
        img = transform(image)
        img = torch.unsqueeze(img, 0)
        output = model(img)[0].data.numpy()
        time_e = time.time() - time_s
        self.ui_face.label_time.setText('用时:' + ('%.3f' % time_e) + 's')
        return output


if __name__ == '__main__':
    app = QApplication([])
    stats = Stats()
    stats.ui_face.show()
    app.exec_()

  • 写回答

1条回答 默认 最新

  • 不会长胖的斜杠 后端领域新星创作者 2022-04-30 20:52
    关注
    
    #import 要用到的库
    import operator
    import os
    import time
    import cv2
    from PySide2 import QtGui
    from PySide2.QtWidgets import QFileDialog, QApplication
    from PySide2.QtUiTools import QUiLoader
    import numpy as np
    import torch
    import torch.nn as nn
    from torchvision import models, transforms
    from PIL import Image
     
     
    def cvImgtoQtImg(cvImg, isConvertToGray=False):                                                                   #opencv图转成qt图
        if isConvertToGray:                                                                                           #是否转成灰度图
            QtImgBuf = cv2.cvtColor(cvImg, cv2.COLOR_BGR2GRAY)                                                        #转换颜色空间
            QtImg = QtGui.QImage(QtImgBuf.data, QtImgBuf.shape[1], QtImgBuf.shape[0], QtGui.QImage.Format_Grayscale8) #返回QTimg格式
        else:
            QtImgBuf = cv2.cvtColor(cvImg, cv2.COLOR_BGR2RGBA)                                                        #转换颜色空间
            QtImg = QtGui.QImage(QtImgBuf.data, QtImgBuf.shape[1], QtImgBuf.shape[0], QtGui.QImage.Format_RGBA8888)   #返回QTimg格式
        return QtImg
     
     
    class Stats:  #Stats类定义
     
        def __init__(self):                                             #初始化函数,创建类时自动调用,以下皆为参数
            self.open = False                                           #open参数定义
            self.ui_face = QUiLoader().load('ui/demo.ui')               #加载ui文件
            self.ui_face.setFixedSize(1239, 824)                        #窗口设置固定的尺寸
            self.ui_face.btn_open_cap.clicked.connect(self.opt_cap)     #设置btn_open_cap按钮点击函数opt_cap,鼠标点击触发此函数
            self.ui_face.btn_predict.clicked.connect(self.cap)          #设置btn_predict按钮点击函数cap
            self.ui_face.btn_open_res.clicked.connect(self.load_pic)    #设置btn_open_res按钮点击函数load_pic
            self.model, self.model_ft = self.load_model()               #加载模型
                                                                        #可回到147行
        def load_pic(self):                                             #加载图片函数
            filePaths, _ = QFileDialog.getOpenFileName(                 #打开一个对话框,给用户选择文件,通过
                self.ui_face,                                           #此句获取打开的文件路径
                "请选择将要转换的文件",
                os.path.join(os.path.expanduser('~'), "Desktop"),       #格式化路径
                "文件类型 (*.jpg)"                                       #格式化文件类型
            )
            self.ui_face.edt_res.setText(filePaths)                     #edt_res设置文本内容为文件路径
            self.img = cv2.imread(filePaths)                            #opencv读取图片
            show = cv2.resize(self.img, (640, 480))                     #调整图片大小为640 480
            show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)                #从一种颜色空间BGR转换为另一种颜色空间RGB
            showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)  #显示图片,括号内图像参数
            self.ui_face.ImgDisp.setPixmap(QtGui.QPixmap.fromImage(showImage))   #设置显示图片的位置
     
     
        def opt_cap(self):                                              #摄像头控制
            if self.open == True:                                       #如果已经打开
                self.open = False                                       #调整为关闭
                self.ui_face.edt_cap.setText('摄像头已关闭')             #输出”摄像头已关闭“
            else:
                self.open = True                                        #如果已经关闭,调整为打开
                self.ui_face.edt_cap.setText('摄像头已打开')             #输出”摄像头已打开“
                self.start()                                            #调用start函数       
     
        def start(self):                                                #shart函数
            self.cap = cv2.VideoCapture(0)                              #VideoCapture()中参数是0,表示打开笔记本的内置摄像头
            self.cap.set(3, 640)                                        #设置分辨率
            self.cap.set(4, 480)                                        #设置分辨率
            self.cap.set(10, 100)                                       #设置分辨率
            while True:                                                                                         #循环
                success, self.img = self.cap.read()                                                             #图像进行翻转
                self.img = cv2.flip(self.img, 1)                                                                #读取摄像头内容
                show = cv2.resize(self.img, (640, 480))                                                         #调整摄像大小
                show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)                                                    #转换颜色空间
                showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)   #展示图片
                self.ui_face.ImgDisp.setPixmap(QtGui.QPixmap.fromImage(showImage))                              #设置图片位置
                cv2.waitKey(0)                                                                                  #图片停留在界面
                if self.open == False:                                                                          #如果open未打开,则跳出循环
                    break   
            print('展示图片')       
     
        def cap(self):                                                                                          #cap函数
            try:                                                                                                #try except语句
                image = Image.fromarray(cv2.cvtColor(self.img, cv2.COLOR_BGR2RGB))                              #调整图片格式
                output = self.predict(image, self.model_ft)                                                     #调用predict函数
                ret = []                                                                                        #定义ret列表
                emo = ['surprized', 'happy', 'disgust', 'normal', 'fear', 'anger', 'sad']                       #定义表情库
                for index, value in enumerate(self.model):                                                      #遍历model函数的结果
                    dis = np.linalg.norm(value - output)  # 欧氏距离                                            #计算欧式距离
                    ret.append({'category': emo[index], 'dis': dis})                                            #将表情的种类和欧氏距离写入列表
                ret = sorted(ret, key=operator.itemgetter('dis'), reverse=False)                                #ret根据欧氏距离排序
                print(ret)                                                                                      #打印ret
                self.ui_face.label_ret.setText('识别结果为:' + ret[0]['category'])                              #ui展示打印结果
                self.ui_face.label_ret_0.setText('0:' + ret[0]['category'])                                    #ui展示打印第一个结果
                self.ui_face.label_ret_1.setText('1:' + ret[1]['category'])                                    #ui展示打印第二个结果                                       #ui展示打印第一个结果
                self.ui_face.label_ret_2.setText('2:' + ret[2]['category'])                                    #ui展示打印第三个结果
                self.ui_face.label_ret_3.setText('3:' + ret[3]['category'])                                    #ui展示打印第四个结果
                self.ui_face.label_ret_4.setText('4:' + ret[4]['category'])                                    #ui展示打印第五个结果
                self.ui_face.label_ret_5.setText('5:' + ret[5]['category'])                                    #ui展示打印第六个结果
                self.ui_face.label_ret_6.setText('6:' + ret[6]['category'])                                    #ui展示打印第七个结果
            except:                                                                                             #如果代码出现问题,执行pass
                pass    
     
        def load_model(self):                                                                   #总结,这个函数所有语句都是为了加载深度学习模型
            # 这一块是对图片特征进行提取
            model_path = 'model/weights.pth'
            # build model
            model_ft = models.resnet34(pretrained=False)
            num_ftrs = model_ft.fc.in_features
            model_ft.fc = nn.Sequential(
                nn.Dropout(0.5),
                nn.Linear(num_ftrs, 7),
                nn.Softmax(dim=1)
            )
            model_ft.load_state_dict(torch.load(model_path))
            model_ft.eval()
            # 参数写到这里,得到的中心点遍历一下  然后写到这里
            model = [
                [2.0667151e-04, 3.4240412e-04, 1.4473200e-02, 8.0134422e-03, 6.0332119e-03,
                 7.7563822e-03, 9.6317458e-01],
                [2.5990081e-04, 2.7968729e-04, 1.8215105e-02, 9.3163711e-01, 5.1174462e-03,
                 6.0818493e-03, 3.8408846e-02],
                [0.00336622, 0.00619731, 0.10314032, 0.20358741, 0.27171963, 0.26114,
                 0.1508491],
                [2.0508033e-04, 3.2301957e-04, 8.1134737e-03, 5.8690608e-03, 9.5963997e-01,
                 1.0704219e-02, 1.5145153e-02],
                [4.1064431e-04, 1.2989613e-03, 8.9172471e-01, 2.3929298e-02, 1.7944381e-02,
                 2.8446108e-02, 3.6245927e-02],
                [0.0014531, 0.00288311, 0.21803668, 0.1291624, 0.06903042, 0.04348047,
                 0.5359538],
                [2.0752930e-04, 4.1509242e-04, 8.1426501e-03, 7.6724142e-03, 8.2466751e-03,
                 9.6485263e-01, 1.0462716e-02]
            ]
            return model, model_ft
     
        def predict(self, image, model):                                                                #根据模型预测结果函数
            time_s = time.time()                                                                        #获取当前时间
            transform = transforms.Compose([                                                            #图像预处理,包含多个步骤:调整大小,变成张量,标准化
                transforms.Resize(224),
                transforms.ToTensor(),
                transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
            img = transform(image)                                                                     #预处理图像
            img = torch.unsqueeze(img, 0)                                                              #作用:扩展维度,返回一个新的张量,对输入的既定位置插入维度 1
            output = model(img)[0].data.numpy()                                                         #将图片输入到模型,进行预测
            time_e = time.time() - time_s                                                               #得出处理时间
            self.ui_face.label_time.setText('用时:' + ('%.3f' % time_e) + 's')                         #输出处理时间
            return output                                                                                #返回输出结果
     
     #从这里开始看
    if __name__ == '__main__':
        app = QApplication([])   #初始化,基于QWidget,用于处理QWidget特有的初始化和结束收尾工作。
        stats = Stats()          #创建Stats类并初始化,命名为stats,可以跳转到27行
        stats.ui_face.show()     #展示Stats类的ui_face,也就是展示界面
        app.exec_()              #运行程序
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 5月8日
  • 已采纳回答 4月30日
  • 修改了问题 4月30日
  • 赞助了问题酬金5元 4月30日
  • 展开全部

悬赏问题

  • ¥15 关于#网络安全#的问题:求ensp的网络安全,不要步骤要完成版文件
  • ¥15 可否在不同线程中调用封装数据库操作的类
  • ¥20 使用Photon PUN2解决游戏得分同步的问题
  • ¥15 微带串馈天线阵列每个阵元宽度计算
  • ¥15 keil的map文件中Image component sizes各项意思
  • ¥20 求个正点原子stm32f407开发版的贪吃蛇游戏
  • ¥15 划分vlan后,链路不通了?
  • ¥20 求各位懂行的人,注册表能不能看到usb使用得具体信息,干了什么,传输了什么数据
  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 Centos / PETGEM