Rope skipping counter application based on OpenCV and PyQt5
Introduction
This article will introduce a jump rope counter application based on OpenCV and PyQt5. The program can use a computer camera to detect rope skipping and count the number of skips. This article will introduce the implementation method and implementation details of the program, including the use of background subtraction algorithm and contour detection algorithm.
Background subtraction algorithm
Background subtraction algorithm is a commonly used image processing technique for extracting moving objects from videos captured by static cameras. The algorithm is based on the assumption that the background of the camera is static and the moving object is dynamic. Therefore, by taking the difference between the current frame image and the background frame image, a binary image of the moving target can be obtained.
In this procedure, we used the MOG2 background subtraction algorithm. This algorithm is a background subtraction algorithm based on Gaussian mixture model. It models the gray value of each pixel as a mixture of multiple Gaussian distributions, where each Gaussian distribution represents a different background or foreground region. Whether each pixel belongs to the foreground area is determined by comparing the pixel value of the current frame image with the pixel value of the background model.
Contour detection algorithm
A contour detection algorithm is an algorithm for detecting the contours of objects in an image. In this program, we use the findContours function in OpenCV to detect the contour of the rope skipping action. This function takes a binary image and some parameters, and returns a list of contours. A contour is a series of consecutive points that represent the boundaries of an object. By counting the number of contours, we can determine the number of jumps.
Application implementation
This program uses the Python programming language and the PyQt5 GUI framework. The program interface is divided into two parts: the video display area and the skipping rope counter.
The Video class is the core component of the program, which is responsible for processing the video frames and using the background subtraction algorithm and contour detection algorithm to detect the rope skipping action. The Video class inherits the QThread class, so it can run in a separate thread to avoid blocking the main thread.
The implementation of the program is basically the following steps:
1. Initialize the program interface and Video class.
2. Start the Video thread and start video capture.
3. In each video frame, extract the foreground region using a background subtraction algorithm.
4. Use the contour detection algorithm to detect the contour of the rope skipping action.
5. Count the number of rope skipping and update the counter.
6. Display the video frame on the interface.
7. Wait for the next frame of video and repeat the above steps.
Complete code
import cv2 from PyQt5 import QtCore, QtGui, QtWidgets import numpy as np class Ui_MainWindow(object): def setupUi(self, MainWindow): # Set the main window properties MainWindow. setObjectName("MainWindow") MainWindow. resize(800, 600) #Add Central Widget self.centralwidget = QtWidgets.QWidget(MainWindow) self.centralwidget.setObjectName("centralwidget") # Add Widget to display video 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") # Add a Label to display the number of skipping ropes 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") # Set the Central Widget of the main window to self.centralwidget MainWindow.setCentralWidget(self.centralwidget) class MainWindow(QtWidgets. QMainWindow): def __init__(self): super().__init__() # Create the UI object self.ui = Ui_MainWindow() self.ui.setupUi(self) # create video object and connect signal 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) # start video 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("jumping rope 2.mp4") self.fgbg = cv2.createBackgroundSubtractorMOG2() self.count = 0 self. jumping = False self.widget = widget self.timer = QtCore.QTimer() # connect timer signal self.timer.timeout.connect(self.readFrame) # read a frame every 100 milliseconds 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) # Convert opencv image format to 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) # Send a new frame signal self.frame_update.emit(pixmap) # send count signal self.count_update.emit("Rope skipping times: %d" % self.count) if __name__ == "__main__": import sys app = QtWidgets. QApplication(sys. argv) MainWindow = MainWindow() MainWindow. show() sys. exit(app. exec_())
Detection effect
Conclusion
This article introduces the implementation method and implementation details of a skipping rope counter application based on OpenCV and PyQt5. By using the background subtraction algorithm and the contour detection algorithm, the program can accurately detect the rope skipping action and count the number of rope skipping. This program can be used not only for jump rope counting, but also for other applications that need to detect moving objects.