Spaces:
Sleeping
Sleeping
| import numpy as np | |
| import cv2 | |
| import time | |
| from cvzone.FaceDetectionModule import FaceDetector | |
| # Initialization | |
| videoWidth = 160 | |
| videoHeight = 120 | |
| videoChannels = 3 | |
| videoFrameRate = 15 | |
| # Helper Methods | |
| def buildGauss(frame, levels): | |
| pyramid = [frame] | |
| for level in range(levels): | |
| frame = cv2.pyrDown(frame) | |
| pyramid.append(frame) | |
| return pyramid | |
| def reconstructFrame(pyramid, index, levels): | |
| filteredFrame = pyramid[index] | |
| for level in range(levels): | |
| filteredFrame = cv2.pyrUp(filteredFrame) | |
| filteredFrame = filteredFrame[:videoHeight, :videoWidth] | |
| return filteredFrame | |
| # Main heart rate function | |
| def heart(video_file_path): | |
| levels = 3 | |
| alpha = 170 | |
| minFrequency = 1.0 | |
| maxFrequency = 2.0 | |
| bufferSize = 150 | |
| bufferIndex = 0 | |
| detector = FaceDetector() | |
| video = cv2.VideoCapture(video_file_path) | |
| firstFrame = np.zeros((videoHeight, videoWidth, videoChannels)) | |
| firstGauss = buildGauss(firstFrame, levels + 1)[levels] | |
| videoGauss = np.zeros((bufferSize, firstGauss.shape[0], firstGauss.shape[1], videoChannels)) | |
| fourierTransformAvg = np.zeros((bufferSize)) | |
| frequencies = (1.0 * videoFrameRate) * np.arange(bufferSize) / (1.0 * bufferSize) | |
| mask = (frequencies >= minFrequency) & (frequencies <= maxFrequency) | |
| bpmCalculationFrequency = 10 | |
| bpmBufferIndex = 0 | |
| bpmBufferSize = 10 | |
| bpmBuffer = np.zeros((bpmBufferSize)) | |
| bpmList = [] | |
| startTime = time.time() | |
| frameCount = 0 | |
| while True: | |
| ret, frame = video.read() | |
| if not ret: | |
| break | |
| elapsedTime = time.time() - startTime | |
| if elapsedTime >= 30: | |
| break | |
| frame, bboxs = detector.findFaces(frame, draw=False) | |
| frameCount += 1 | |
| if bboxs: | |
| x1, y1, w1, h1 = bboxs[0]['bbox'] | |
| # Check if the bounding box is valid | |
| if x1 >= 0 and y1 >= 0 and w1 > 0 and h1 > 0: | |
| detectionFrame = frame[y1:y1 + h1, x1:x1 + w1] | |
| # Check if detectionFrame is valid and not empty before resizing | |
| if detectionFrame.size != 0: | |
| detectionFrame = cv2.resize(detectionFrame, (videoWidth, videoHeight)) | |
| videoGauss[bufferIndex] = buildGauss(detectionFrame, levels + 1)[levels] | |
| fourierTransform = np.fft.fft(videoGauss, axis=0) | |
| fourierTransform[mask == False] = 0 | |
| if bufferIndex % bpmCalculationFrequency == 0: | |
| for buf in range(bufferSize): | |
| fourierTransformAvg[buf] = np.real(fourierTransform[buf]).mean() | |
| hz = frequencies[np.argmax(fourierTransformAvg)] | |
| bpm = 60.0 * hz | |
| bpmBuffer[bpmBufferIndex] = bpm | |
| bpmBufferIndex = (bpmBufferIndex + 1) % bpmBufferSize | |
| bpmList.append(bpmBuffer.mean()) | |
| bufferIndex = (bufferIndex + 1) % bufferSize | |
| else: | |
| # If no face is detected, skip to the next frame | |
| continue | |
| avgBPM = np.mean(bpmList) if bpmList else 0 | |
| video.release() | |
| return avgBPM, frameCount | |