Innerhlab dieses Repositorys ist ein showcase ausgearbeitet, welcher live die Funktion des EVM Algorithmus darstellt.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ideal_filter.py 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. import scipy.fftpack as fftpack
  2. import numpy as np
  3. import cv2
  4. from scipy.signal import find_peaks
  5. import pyramid
  6. import video
  7. def start(vidFile, alpha, low, high, chromAttenuation, fps, width, height):
  8. '''
  9. Performs color magnification on the video by applying an ideal bandpass filter,
  10. i.e. applies a discrete fourier transform on the gaussian downsapled video and
  11. cuts off the frequencies outside the bandpass filter, magnifies the result and
  12. saves the output video. Additionally, it detects heartbeat and returns BPM.
  13. :param vidFile: Video file
  14. :param alpha: Magnification factor
  15. :param low: Low frequency cut-off
  16. :param high: High frequency cut-off
  17. :param chromAttenuation: Chrominance attenuation factor
  18. :param mode: Processing mode (unused in this example, but kept for compatibility)
  19. :param fps: Frames per second of the video
  20. :param width: Width of the video frame
  21. :param height: Height of the video frame
  22. :return: final processed video, heart rate in BPM
  23. '''
  24. # Convert from RGB to YIQ for better processing of chrominance information
  25. t = video.rgb2yiq(vidFile)
  26. levels = 4
  27. # Build Gaussian pyramid and use the highest level
  28. gauss_video_list = pyramid.gaussian_video(t, levels)
  29. print('Apply Ideal filter')
  30. # Apply discrete Fourier transformation (real)
  31. fft = fftpack.rfft(gauss_video_list, axis=0)
  32. frequencies = fftpack.rfftfreq(fft.shape[0], d=1.0 / fps) # Sample frequencies
  33. mask = np.logical_and(frequencies > low, frequencies < high) # Logical array if values between low and high frequencies
  34. fft[~mask] = 0 # Cutoff values outside the bandpass
  35. filtered = fftpack.irfft(fft, axis=0) # Inverse Fourier transformation
  36. filtered *= alpha # Magnification
  37. # Chromatic attenuation
  38. filtered[:, :, :, 1] *= chromAttenuation
  39. filtered[:, :, :, 2] *= chromAttenuation
  40. print(chromAttenuation)
  41. # Resize last Gaussian level to the frame size
  42. filtered_video_list = np.zeros(t.shape)
  43. for i in range(t.shape[0]):
  44. f = filtered[i]
  45. filtered_video_list[i] = cv2.resize(f, (t.shape[2], t.shape[1]))
  46. final = filtered_video_list
  47. # Add to original
  48. final += t
  49. # Convert back from YIQ to RGB
  50. final = video.yiq2rgb(final)
  51. # Cutoff invalid values
  52. final[final < 0] = 0
  53. final[final > 255] = 255
  54. # Detect heartbeat and return BPM
  55. bpm = detect_heartbeat(filtered_video_list, fps)
  56. return final, bpm
  57. def detect_heartbeat(video_frames, fps):
  58. '''
  59. Detects heartbeat by analyzing pixel intensity variations in the filtered video over time.
  60. :param video_frames: Processed video frames (filtered and magnified)
  61. :param fps: Frames per second of the video
  62. :return: Detected heart rate in BPM (beats per minute)
  63. '''
  64. # Focus on the green channel for heart rate detection (more sensitive to blood flow changes)
  65. green_channel = video_frames[:, :, :, 1] # Extract green channel
  66. # Calculate the average intensity of the green channel for each frame
  67. avg_intensity = np.mean(green_channel, axis=(1, 2)) # Shape: (num_frames,)
  68. # Normalize intensity values
  69. avg_intensity -= np.mean(avg_intensity)
  70. avg_intensity /= np.std(avg_intensity)
  71. # Detect peaks in the intensity signal (peaks correspond to heartbeats)
  72. peaks, _ = find_peaks(avg_intensity, distance=fps // 2) # Ensure at least half a second between peaks
  73. # Calculate the time differences between peaks to compute the heart rate
  74. peak_intervals = np.diff(peaks) / fps # Convert frame intervals to seconds
  75. if len(peak_intervals) > 0:
  76. avg_heartbeat_interval = np.mean(peak_intervals)
  77. bpm = 60 / avg_heartbeat_interval # Convert to beats per minute
  78. else:
  79. bpm = 0 # No peaks detected
  80. return bpm