您现在的位置是:首页 >技术杂谈 >基于OpenCV和PyQt5的跳绳计数器应用程序网站首页技术杂谈

基于OpenCV和PyQt5的跳绳计数器应用程序

南蓬幽 2024-06-20 18:01:02
简介基于OpenCV和PyQt5的跳绳计数器应用程序

基于OpenCV和PyQt5的跳绳计数器应用程序

介绍

本文将介绍一个基于OpenCV和PyQt5的跳绳计数器应用程序。该程序可以使用计算机摄像头来检测跳绳动作,并计算跳绳次数。本文将介绍程序的实现方法和实现细节,包括背景减除算法和轮廓检测算法的使用。

背景减除算法

背景减除算法是一种常用的图像处理技术,用于从静态摄像头拍摄的视频中提取运动目标。该算法基于假设,即摄像头的背景是静态的,而运动目标是动态的。因此,通过将当前帧图像与背景帧图像进行差分,可以得到运动目标的二值图像。

在本程序中,我们使用了MOG2背景减除算法。该算法是一种基于高斯混合模型的背景减除算法。它将每个像素的灰度值建模为多个高斯分布的混合,其中每个高斯分布表示不同的背景或前景区域。通过比较当前帧图像的像素值与背景模型的像素值来确定每个像素是否属于前景区域。

轮廓检测算法

轮廓检测算法是一种用于检测图像中对象轮廓的算法。在本程序中,我们使用了OpenCV中的findContours函数来检测跳绳动作的轮廓。该函数接受一个二值图像和一些参数,然后返回一个轮廓列表。轮廓是由一系列连续的点组成的,表示对象的边界。通过计算轮廓的数量,我们可以确定跳绳次数。

应用程序实现

本程序使用了Python编程语言和PyQt5 GUI框架。程序界面分为两个部分:视频显示区域和跳绳计数器。

Video类是程序的核心组件,它负责处理视频帧,并使用背景减除算法和轮廓检测算法来检测跳绳动作。Video类继承了QThread类,因此可以在单独的线程中运行,以避免阻塞主线程。

程序的实现基本上是以下几个步骤:

1.初始化程序界面和Video类。

2.启动Video线程并开始视频捕捉。

3.在每个视频帧中,使用背景减除算法提取前景区域。

4.使用轮廓检测算法检测跳绳动作的轮廓。

5.计算跳绳次数并更新计数器。

6.将视频帧显示在界面上。

7.等待下一帧视频并重复上述步骤。

完整代码

import cv2
from PyQt5 import QtCore, QtGui, QtWidgets
import numpy as np

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        # 设置主窗口属性
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)

        # 添加Central Widget
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")

        # 添加Widget用于显示视频
        self.video_widget = QtWidgets.QLabel(self.centralwidget)
        self.video_widget.setGeometry(QtCore.QRect(100, 100, 640, 480))
        self.video_widget.setFrameShape(QtWidgets.QFrame.Box)
        self.video_widget.setText("")
        self.video_widget.setAlignment(QtCore.Qt.AlignCenter)
        self.video_widget.setObjectName("video_widget")

        # 添加Label用于显示跳绳次数
        self.result_label = QtWidgets.QLabel(self.centralwidget)
        self.result_label.setGeometry(QtCore.QRect(275, 30, 250, 50))
        font = QtGui.QFont()
        font.setPointSize(20)
        font.setBold(True)
        font.setWeight(75)
        self.result_label.setFont(font)
        self.result_label.setAlignment(QtCore.Qt.AlignCenter)
        self.result_label.setObjectName("result_label")

        # 设置主窗口的Central Widget为self.centralwidget
        MainWindow.setCentralWidget(self.centralwidget)




class MainWindow(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        # 创建UI对象
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)

        # 创建视频对象并连接信号
        self.video = Video(self.ui.video_widget)
        self.video.frame_update.connect(self.ui.video_widget.setPixmap)
        self.video.count_update.connect(self.ui.result_label.setText)

        # 启动视频
        self.video.readFrame()




class Video(QtCore.QObject):
    frame_update = QtCore.pyqtSignal(QtGui.QPixmap)
    count_update = QtCore.pyqtSignal(str)

    def __init__(self, widget):
        super().__init__()
        self.cap = cv2.VideoCapture("跳绳2.mp4")
        self.fgbg = cv2.createBackgroundSubtractorMOG2()
        self.count = 0
        self.jumping = False
        self.widget = widget
        self.timer = QtCore.QTimer()

        # 连接定时器信号
        self.timer.timeout.connect(self.readFrame)

        # 每100毫秒读取一帧
        self.timer.start(100)

    def readFrame(self):
        ret, frame = self.cap.read()
        if not ret:
            self.timer.stop()
            return

        fgmask = self.fgbg.apply(frame)

        thresh = cv2.threshold(fgmask, 50, 255, cv2.THRESH_BINARY)[1]

        contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        if len(contours) > 0:
            largest_contour = max(contours, key=cv2.contourArea)
            if cv2.contourArea(largest_contour) > 1000:
                if not self.jumping:
                    self.jumping = True
                    self.count += 1
            else:
                self.jumping = False

        cv2.putText(frame, "Count: {}".format(self.count), (10, 50),
                    cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)

        # 将opencv图像格式转换为QPixmap
        h, w, ch = frame.shape
        bytes_per_line = ch * w
        convert_to_Qt_format = QtGui.QImage(frame.data, w, h, bytes_per_line, QtGui.QImage.Format_RGB888)
        p = convert_to_Qt_format.scaled(640, 480, QtCore.Qt.KeepAspectRatio)
        pixmap = QtGui.QPixmap.fromImage(p)

        # 发送新帧信号
        self.frame_update.emit(pixmap)

        # 发送计数信号
        self.count_update.emit("跳绳次数:%d" % self.count)






if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = MainWindow()
    MainWindow.show()
    sys.exit(app.exec_())


检测效果

在这里插入图片描述

结论

本文介绍了一个基于OpenCV和PyQt5的跳绳计数器应用程序的实现方法和实现细节。通过使用背景减除算法和轮廓检测算法,该程序可以准确地检测跳绳动作,并计算跳绳次数。该程序不仅可以用于跳绳计数,还可以用于其他需要检测运动目标的应用程序。

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。