基于pyqt5实现的照片特征传入mysql数据库

前言

暑假学校软工实践项目,节选了一部分上传,可以实现手动上传图片和拍照保存,数据库的表需要name, encoding_str两个字段
代码如下:

from PyQt5 import QtCore, QtGui, QtWidgets
import sys
import cv2
import face_recognition
import pymysql
import numpy as np


class Ui_MainWindow(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)  # 父类的构造函数

        self.timer_camera = QtCore.QTimer()  # 定义定时器,用于控制显示视频的帧率
        self.cap = cv2.VideoCapture()  # 视频流
        self.CAM_NUM = 0  # 为0时表示视频流来自笔记本内置摄像头

        self.set_ui()  # 初始化程序界面
        self.slot_init()  # 初始化槽函数

    '''程序界面布局'''

    def set_ui(self):
        self.__layout_main = QtWidgets.QHBoxLayout()  # 总布局
        self.__layout_fun_button = QtWidgets.QVBoxLayout()  # 按键布局
        self.__layout_data_show = QtWidgets.QVBoxLayout()  # 数据(视频)显示布局
        self.button_open_camera = QtWidgets.QPushButton('打开相机')  # 建立用于打开摄像头的按键
        self.button_close = QtWidgets.QPushButton('退出')  # 建立用于退出程序的按键
        self.button_save = QtWidgets.QPushButton('保存')
        self.button_load = QtWidgets.QPushButton('上传')

        self.nameLineEdit = QtWidgets.QLineEdit("请输入姓名")


        self.button_open_camera.setMinimumHeight(50)  # 设置按键大小
        self.button_close.setMinimumHeight(50)
        self.button_save.setMinimumHeight(50)
        self.button_load.setMinimumHeight(50)

        self.button_close.move(10, 100)  # 移动按键

        '''信息显示'''
        self.label_show_camera = QtWidgets.QLabel()  # 定义显示视频的Label
        self.label_show_camera.setFixedSize(641, 481)  # 给显示视频的Label设置大小为641x481
        '''把按键加入到按键布局中'''
        self.__layout_fun_button.addWidget(self.nameLineEdit)
        self.__layout_fun_button.addWidget(self.button_open_camera)  # 把打开摄像头的按键放到按键布局中
        self.__layout_fun_button.addWidget(self.button_load)
        self.__layout_fun_button.addWidget(self.button_close)  # 把退出程序的按键放到按键布局中


        '''把某些控件加入到总布局中'''
        self.__layout_main.addLayout(self.__layout_fun_button)  # 把按键布局加入到总布局中
        self.__layout_main.addWidget(self.label_show_camera)  # 把用于显示视频的Label加入到总布局中
        '''总布局布置好后就可以把总布局作为参数传入下面函数'''
        self.setLayout(self.__layout_main)  # 到这步才会显示所有控件

    '''初始化所有槽函数'''

    def slot_init(self):
        self.button_open_camera.clicked.connect(
            self.button_open_camera_clicked)  # 若该按键被点击,则调用button_open_camera_clicked()
        self.timer_camera.timeout.connect(self.show_camera)  # 若定时器结束,则调用show_camera()
        self.button_close.clicked.connect(self.close)  # 若该按键被点击,则调用close(),注意这个close是父类QtWidgets.QWidget自带的,会关闭程序
        self.button_save.clicked.connect(self.save_photo)
        self.button_load.clicked.connect(self.load_photo)

    '''槽函数之一'''

    def load_photo(self):
        path, _ = QtWidgets.QFileDialog.getOpenFileName(self, '选择图片', 'c:\\', 'Image files(*.jpeg *.jpg *.gif *.png)')
        name = self.nameLineEdit.text()
        if name=="":
            print("保存失败")
        elif path=="":
            print("保存失败")
        else:
            load_image(path, name)
            print("上传成功")


    def save_photo(self):
        ret, frame = self.cap.read()
        name = self.nameLineEdit.text()
        # cv2.imwrite("fangjian.jpg", frame)
        if name=="":
            print("保存失败")
        else:
            load_image_video(frame, name)
            print("保存成功")

    def button_open_camera_clicked(self):
        if self.timer_camera.isActive() == False:  # 若定时器未启动
            flag = self.cap.open(self.CAM_NUM)  # 参数是0,表示打开笔记本的内置摄像头,参数是视频文件路径则打开视频
            if flag == False:  # flag表示open()成不成功
                msg = QtWidgets.QMessageBox.warning(self, 'warning', "请检查相机于电脑是否连接正确", buttons=QtWidgets.QMessageBox.Ok)
            else:
                self.timer_camera.start(30)  # 定时器开始计时30ms,结果是每过30ms从摄像头中取一帧显示
                self.button_save.setHidden(False)
                self.button_open_camera.setText('关闭相机')
        else:
            self.timer_camera.stop()  # 关闭定时器
            self.cap.release()  # 释放视频流
            self.label_show_camera.clear()  # 清空视频显示区域
            self.button_save.setHidden(True)
            self.button_open_camera.setText('打开相机')


    def show_camera(self):
        self.__layout_fun_button.addWidget(self.button_save)
        flag, self.image = self.cap.read()  # 从视频流中读取

        show = cv2.resize(self.image, (640, 480))  # 把读到的帧的大小重新设置为 640x480
        show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)  # 视频色彩转换回RGB,这样才是现实的颜色
        showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0],
                                 QtGui.QImage.Format_RGB888)  # 把读取到的视频数据变成QImage形式
        self.label_show_camera.setPixmap(QtGui.QPixmap.fromImage(showImage))  # 往显示视频的Label里 显示QImage


# 加载图像及获取人脸特征
def load_image(input_image, input_name):
    # 加载本地图像文件到一个numpy ndarray类型的对象上
    image = cv2.imread(input_image)

    # 返回图像中每个面的128维人脸编码
    # 图像中可能存在多张人脸,取下标为0的人脸编码,表示识别出来的最清晰的人脸
    image_face_encoding = face_recognition.face_encodings(image)[0]

    # 将numpy array类型转化为列表
    encoding__array_list = image_face_encoding.tolist()

    # 将列表里的元素转化为字符串
    encoding_str_list = [str(i) for i in encoding__array_list]

    # 拼接列表里的字符串
    encoding_str = ','.join(encoding_str_list)

    # 被识别者姓名
    name = input_name

    # 将人脸特征编码存进数据库
    save_encoding(encoding_str, name)

def load_image_video(image, input_name):
    # 返回图像中每个面的128维人脸编码
    # 图像中可能存在多张人脸,取下标为0的人脸编码,表示识别出来的最清晰的人脸
    image_face_encoding = face_recognition.face_encodings(image)[0]

    # 将numpy array类型转化为列表
    encoding__array_list = image_face_encoding.tolist()

    # 将列表里的元素转化为字符串
    encoding_str_list = [str(i) for i in encoding__array_list]

    # 拼接列表里的字符串
    encoding_str = ','.join(encoding_str_list)

    # 被识别者姓名
    name = input_name

    # 将人脸特征编码存进数据库
    save_encoding(encoding_str, name)


# 人脸特征信息保存
def save_encoding(encoding_str, name):
    # 创建数据库连接对象
    conn = pymysql.connect(
        # 数据库的IP地址
        host="127.0.0.1",
        # 数据库用户名称
        user="root",
        # 数据库用户密码
        password="123",
        # 数据库名称
        db="hd_faces",
        # 数据库端口名称
        port=3306,
        # 数据库的编码方式 注意是utf8
        charset="utf8"
    )

    # 使用 cursor() 方法创建一个游标对象 cursor
    cursor = conn.cursor()

    # SQL插入语句
    query_sql = 'select * from face where name='+'"'+name+'"'
    print("query sql:",query_sql)
    # 执行sql语句
    cursor.execute(query_sql)
    results = cursor.fetchall()
    if len(results) == 0:
        # SQL插入语句
        insert_sql = "insert into face(name,encoding) values(%s,%s)"
        try:
            # 执行sql语句
            cursor.execute(insert_sql, (name, encoding_str))
            # 提交到数据库执行
            conn.commit()
        except Exception as e:
            # 如果发生错误则回滚并打印错误信息
            conn.rollback()
            print(e)
    else:
        print("已有记录,勿重复添加!")
    # 关闭游标
    cursor.close()
    # 关闭数据库连接
    conn.close()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)  # 固定的,表示程序应用
    ui = Ui_MainWindow()  # 实例化Ui_MainWindow
    ui.show()  # 调用ui的show()以显示。同样show()是源于父类QtWidgets.QWidget的
    sys.exit(app.exec_())  # 不加这句,程序界面会一闪而过

你可能感兴趣的:(python,pyqt5,mysql,照片特征)