效果

QQ录屏20240406131651

语音播放

import pygame
pygame.mixer.init()   #初始化
pygame.mixer.music.load(r"7359.wav")   #文件位置
pygame.mixer.music.play(1)   #播放语音
while pygame.mixer.music.get_busy():  # 在音频播放为完成之前不退出程序
    pass

完整代码

1.多线程使语音可以播放完,预防卡音。

2.小于35厘米语音提醒并更换距离提醒字体颜色,一般情况下用蓝色字体显示。

3.使用过程中可以把倒数第二行注释掉,不进行窗口的显示,仅判断距离

import cv2
from cvzone.FaceMeshModule import FaceMeshDetector
import pygame
import threading
from PIL import Image, ImageDraw, ImageFont
import numpy as np

# 初始化pygame.mixer
pygame.mixer.init()
# 加载音频文件
pygame.mixer.music.load('7359.wav')  # 靠的太近啦  #音频文件自行修改
# 设置摄像头
cap = cv2.VideoCapture(0)
detector = FaceMeshDetector(maxFaces=1)
# 定义播放音频的函数
def play_audio():
    pygame.mixer.music.play(1)
    while pygame.mixer.music.get_busy():
        continue
# 开始检测人脸
while True:
    success, img = cap.read()
    img, faces = detector.findFaceMesh(img, draw=False)
    if faces:
        face = faces[0]
        pointLeft = face[145]
        pointRight = face[374]
        w, _ = detector.findDistance(pointLeft, pointRight)
        W = 6.3
        f = 600
        d = (W * f) / w
        print(d)
        # 设置距离颜色
        if d < 35:
            print("过近提醒")
            # 检查是否正在播放音频
            if not pygame.mixer.music.get_busy():
                # 使用线程播放音频,避免阻塞主程序
                audio_thread = threading.Thread(target=play_audio)
                audio_thread.start()
            text_color = (255, 0, 0)  # 红色
        else:
            text_color = (0, 0, 255)  # 蓝色
        # 将 Depth 文本显示为汉语
        pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
        draw = ImageDraw.Draw(pil_img)
        font = ImageFont.truetype("msyh.ttc", 36)  # 使用微软雅黑字体,大小为36
        draw.text((face[10][0] - 95, face[10][1] - 5), f'距离:{int(d)}厘米', font=font, fill=text_color)
        img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
    cv2.imshow("Distance recognition", img)  # 窗口名只能是英文
    cv2.waitKey(1)

UI设计

用pyqt设计了个UI把视频流嵌入

并设计了个进度条用来实时显示距离

输入距离设置 低于xx时自动提醒

import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt, QPoint
from esp32_ui import Ui_Form  # UI
import ping  # qrc生成的py #样式表
import cv2
from cvzone.FaceMeshModule import FaceMeshDetector
import pygame
import threading
from PIL import Image, ImageDraw, ImageFont
import numpy as np
class guWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.gu = Ui_Form()
        self.gu.setupUi(self)
        self.gu.lineEdit.returnPressed.connect(self.gumou)  # lineEdit回车运行
        self.video_label = self.gu.label_2# 2 QLabel2
        self.user_name_qwidget = self.gu.lineEdit
        self.progress_bar = self.gu.progressBar  #进度条
        self.setWindowOpacity(0.90)  # 设置窗口透明度
        self.setWindowFlag(Qt.FramelessWindowHint)  # 去除边框
        self.setAttribute(Qt.WA_TranslucentBackground)  # 去除白色背景
        self.offset = QPoint()  # 记录鼠标按下的初始位置
    def mousePressEvent(self, event):
        self.offset = event.pos()
    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.move(self.pos() + event.pos() - self.offset)  # 移动窗口位置
    def gumou(self):  # 按钮绑定的函数 功能
        cap = cv2.VideoCapture(0)
        detector = FaceMeshDetector(maxFaces=1)
        pygame.mixer.init()
        # 加载音频文件
        pygame.mixer.music.load('7359.wav')  # 靠的太近啦
        def play_audio():
            pygame.mixer.music.play(1)
            while pygame.mixer.music.get_busy():
                continue
        while True:
            success, img = cap.read()
            img, faces = detector.findFaceMesh(img, draw=False)
            if faces:
                face = faces[0]
                pointLeft = face[145]
                pointRight = face[374]
                w, _ = detector.findDistance(pointLeft, pointRight)
                W = 6.5
                f = 600  # 焦距
                d = (W * f) / w
                print(d)
                # 设置距离颜色
                if d < 35:
                    print("过近提醒")
                    # 检查是否正在播放音频
                    if not pygame.mixer.music.get_busy():
                        # 使用线程播放音频,避免阻塞主程序
                        audio_thread = threading.Thread(target=play_audio)
                        audio_thread.start()
                    text_color = (255, 0, 0)  # 红色
                else:
                    text_color = (0, 0, 255)  # 蓝色

                # Update the QProgressBar value
                self.progress_bar.setValue(int(d))

                # 将 Depth 文本显示为汉语
                pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
                draw = ImageDraw.Draw(pil_img)
                font = ImageFont.truetype("msyh.ttc", 36)  # 使用微软雅黑字体,大小为36
                draw.text((face[10][0] - 95, face[10][1] - 5), f'距离:{int(d)}厘米', font=font, fill=text_color)
                img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
            h, w, c = img.shape
            bytesPerLine = c * w
            if c == 3:  # 如果颜色通道为3(BGR)
                q_img = QtGui.QImage(img.data, w, h, bytesPerLine, QtGui.QImage.Format_BGR888)
            else:  # 如果颜色通道为4(BGRA)
                q_img = QtGui.QImage(img.data, w, h, bytesPerLine, QtGui.QImage.Format_BGRA8888)
            # Convert QImage to QPixmap
            pixmap = QtGui.QPixmap.fromImage(q_img)
            # Display QPixmap on QLabel
            self.video_label.setPixmap(pixmap)
            self.video_label.setScaledContents(True)
            self.video_label.update()
            cv2.waitKey(1)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    icon = QtGui.QIcon(':/jay.ico')
    app.setWindowIcon(icon)
    # 创建可拖动窗口实例
    ui = guWindow()  # 函数
    # 显示窗口
    ui.show()
    # 启动应用程序事件循环
    sys.exit(app.exec_())

ui代码

import sys
from PyQt5 import QtGui
from PyQt5.QtWidgets import QApplication, QWidget
from PyQt5.QtCore import Qt, QPoint, pyqtSignal
from esp32_ui import Ui_Form  # UI
import ping  # qrc生成的py #样式表
import cv2
from cvzone.FaceMeshModule import FaceMeshDetector
import pygame
import threading
from PIL import Image, ImageDraw, ImageFont
import numpy as np

class guWindow(QWidget):
    close_signal = pyqtSignal()

    def __init__(self):
        super().__init__()
        self.gu = Ui_Form()
        self.gu.setupUi(self)
        self.gu.lineEdit.returnPressed.connect(self.gumou)  # lineEdit回车运行
        self.video_label = self.gu.label_2# 2 QLabel2
        self.user_name_qwidget = self.gu.lineEdit
        self.progress_bar = self.gu.progressBar  #进度条
        self.setWindowOpacity(0.90)  # 设置窗口透明度
        self.setWindowFlag(Qt.FramelessWindowHint)  # 去除边框
        self.setAttribute(Qt.WA_TranslucentBackground)  # 去除白色背景
        self.offset = QPoint()  # 记录鼠标按下的初始位置
        self.close_signal.connect(self.closeEvent)

    def closeEvent(self, event):
        # 关闭窗口时发送信号
        self.stop_capture()

    def mousePressEvent(self, event):
        self.offset = event.pos()

    def mouseMoveEvent(self, event):
        if event.buttons() == Qt.LeftButton:
            self.move(self.pos() + event.pos() - self.offset)  # 移动窗口位置

    def gumou(self):  # 按钮绑定的函数 功能
        s = self.user_name_qwidget.text()
        self.user_name_qwidget.clear()
        try:
            distance_threshold = float(s)  # 将用户输入的文本转换为浮点数作为距离阈值
        except ValueError:
            print("Invalid input. Please enter a valid number.")
            return
        cap = cv2.VideoCapture(0)
        self.detector = FaceMeshDetector(maxFaces=1)
        pygame.mixer.init()
        # 加载音频文件
        pygame.mixer.music.load('7359.wav')  # 靠的太近啦
        self.capture_active = True

        def play_audio():
            pygame.mixer.music.play(1)
            while pygame.mixer.music.get_busy():
                continue

        while self.capture_active:
            success, img = cap.read()
            img, faces = self.detector.findFaceMesh(img, draw=False)
            if faces:
                face = faces[0]
                pointLeft = face[145]
                pointRight = face[374]
                w, _ = self.detector.findDistance(pointLeft, pointRight)
                W = 6.5
                f = 600  # 焦距
                d = (W * f) / w
                print(d)
                # 设置距离颜色
                if d < distance_threshold:  # 使用用户输入的距离阈值作为判断条件
                    print("过近提醒")
                    # 检查是否正在播放音频
                    if not pygame.mixer.music.get_busy():
                        # 使用线程播放音频,避免阻塞主程序
                        audio_thread = threading.Thread(target=play_audio)
                        audio_thread.start()
                    text_color = (255, 0, 0)  # 红色
                else:
                    text_color = (0, 0, 255)  # 蓝色
                # Update the QProgressBar value
                self.progress_bar.setValue(int(d))
                # 将 Depth 文本显示为汉语
                pil_img = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
                draw = ImageDraw.Draw(pil_img)
                font = ImageFont.truetype("msyh.ttc", 36)  # 使用微软雅黑字体,大小为36
                draw.text((face[10][0] - 95, face[10][1] - 5), f'距离:{int(d)}厘米', font=font, fill=text_color)
                img = cv2.cvtColor(np.array(pil_img), cv2.COLOR_RGB2BGR)
            h, w, c = img.shape
            bytesPerLine = c * w
            if c == 3:  # 如果颜色通道为3(BGR)
                q_img = QtGui.QImage(img.data, w, h, bytesPerLine, QtGui.QImage.Format_BGR888)
            else:  # 如果颜色通道为4(BGRA)
                q_img = QtGui.QImage(img.data, w, h, bytesPerLine, QtGui.QImage.Format_BGRA8888)
            # Convert QImage to QPixmap
            pixmap = QtGui.QPixmap.fromImage(q_img)
            # Display QPixmap on QLabel
            self.video_label.setPixmap(pixmap)
            self.video_label.setScaledContents(True)
            self.video_label.update()
            cv2.waitKey(1)

    def stop_capture(self):
        self.capture_active = False

if __name__ == '__main__':
    app = QApplication(sys.argv)
    icon = QtGui.QIcon(':/jay.ico')
    app.setWindowIcon(icon)
    # 创建可拖动窗口实例
    ui = guWindow()  # 函数
    # 显示窗口
    ui.show()
    # 启动应用程序事件循环
    sys.exit(app.exec_())

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐