从简单视频获取心率:内部代码

use*_*804 9 matlab camera signal-processing video-processing ios

我试图通过我的皮肤视频找到心率.为了做到这一点,我从我的视频帧中取出一个裁剪的像素矩形,并对所有这些像素中的红色(或绿色)分量求平均值(当然,看看这个平均值如何在帧到帧之间变化).

我对矢量进行快速傅立叶变换(每帧裁剪部分的平均颜色值),以查看哪些频率最突出.我希望看到静息的人类心率,~1Hz,非常突出.

作为一个测试,我拍摄了一个只有墙壁的视频,或其他应该没有周期性颜色变化的物体.我使用了三脚架和三种不同品牌的不同相机.它们中的每一个具有相似但不相同的背景频率峰值,特别是在1Hz,2Hz,5Hz和10Hz.我在自然光和荧光下拍摄,但它仍然存在.

我的最终目标是通过这种分析来区分来自非血管化皮肤的活皮肤.因此理解为什么我为无生命物体获得这些频率峰值是VITAL.

您是否可以在自己的视频中运行此代码并帮助解释我是否只是一个白痴?

相机拍摄:

柯达Playsport

1920x1080 30fps(60i)进口为mp4

佳能Vixia HF200 1440x1080 30fps(60i)12mbps比特率导入.mts我重新编码为mp4

代码基于:

http://www.ignaciomellado.es/blog/Measuring-heart-rate-with-a-smartphone-camera#video

clear all
close all
clc

%% pick data file name to be analyzed, set directory it is found in
dataDir = './data';
vidname = ['Filename.MP4'];

%% define path to file and pull out video
inFile = fullfile(dataDir,vidname);
video = VideoReader(inFile);

%% make 1D array with length equal to number of frames (time)

brightness = zeros(1, video.NumberOfFrames);
video_framerate = round( video.FrameRate); % note some places in the code must use integer value for framerate, others we directly use the unrounded frame rate

%% set region of interest for what you want to get average brightness of
frame = read(video, 1);
imshow(frame)
rect = getrect;
close all

xmin_pt = round(rect(1));
ymin_pt = round(rect(2)); 
section_width = round(rect(3)); 
section_height = round(rect(4));

%% select component of video (red green or blue)
component_selection = 1; % pick red , green, or blue

%% make 1D array of ROI averages
 for i = 1:video.NumberOfFrames,
     frame = read(video, i);
     section_of_interest = frame(ymin_pt:ymin_pt+section_height,xmin_pt:xmin_pt+section_width,:);
     colorPlane = section_of_interest(:, :, component_selection);
     brightness(i) = sum(sum(colorPlane)) / (size(frame, 1) * size(frame, 2));
 end


%% Filter out non-physiological frequencies
BPM_L = 40;    % Heart rate lower limit [bpm]
BPM_H = 600;   % Heart rate higher limit [bpm] This is currently set high to investigate the signal

% Butterworth frequencies must be in [0, 1], where 1 corresponds to half the sampling rate
[b, a] = butter(2, [((BPM_L / 60) / video_framerate * 2), ((BPM_H / 60) / video_framerate * 2)]);
filtBrightness = filter(b, a, brightness);


%% Trim the video to exlude the time where the camera is stabilizing
FILTER_STABILIZATION_TIME = 3;    % [seconds]
filtBrightness = filtBrightness((video_framerate * FILTER_STABILIZATION_TIME + 1):size(filtBrightness, 2));

%% Do FFT on filtered/trimmed signal
fftMagnitude = abs(fft(filtBrightness));

%% Plot results

figure(1)
subplot(3,1,1)
plot([1:length(brightness)]/video.FrameRate,brightness)
xlabel('Time (seconds)')
ylabel('Color intensity')
title('original signal')

subplot(3,1,2)
plot([1:length(filtBrightness)]/video.FrameRate,filtBrightness)
xlabel('Time (seconds)')
ylabel('Color intensity')
title('after butterworth filter and trim')


freq_dimension = ((1:round(length(filtBrightness)))-1)*(video_framerate/length(filtBrightness));

subplot(3,1,3)
plot(freq_dimension,fftMagnitude)
axis([0,15,-inf,inf])
xlabel('Frequency (Hz)')
ylabel('|Y(f)|')
title('Fft of filtered signal')
Run Code Online (Sandbox Code Playgroud)

Eng*_*ica 1

您的目的是“从我的皮肤视频中找到心率”和“...通过此分析区分活体皮肤与非血管化皮肤”,但您的方法是“拍摄视频...裁剪...平均红色(或绿色)分量..看看它如何变化”。

我觉得前提有问题。平均意味着多数信号占主导地位。人类视觉是视觉数据的(令人惊奇的)处理器,通常需要数十年的努力才能让机器达到他们所做的哪怕一小部分。如果您无法用眼睛观察周围 90% 的人并测量他们的心率,那么平均方法可能不是最佳选择。

您可以使用无数的统计数据来查看分布如何随时间变化,而平均值只是其中之一。如果您只查看平均值,您可能会丢失信息。

我将如何做到这一点:

  1. 我会根据帧与帧之间的差异进行操作。
  2. 大多数视频编解码器的时间间隔不均匀。我将获取这些值,以便我可以跟踪实际(非假设)时间的变化。您当前的(可能是错误的)信号可能来自编解码器以及硬件。
  3. 我会制作一部电影,使每个新帧都是它与前一帧之间的差异。我会看 20 遍,看看我的(令人惊叹的)人类视觉处理系统是否能看到任何明显与心跳相关或明显不相关的东西。
  4. For the "NOT" remove them from processing, by mask, filter or such. For related, find way to make them the region of interest by removing everything else, truncating pixel intensity histogram, or other image enhancements (blur, sharpen, re-color, edge, rotate so largest signal is along updated pixel axes and then process..)

AFTER the human vision apparatus can get a good signal, then I would work on making math/computer get the signal with the clear knowledge that the human apparatus is superior.

If I were tracking points/features that move over time, I would look at sub-pixel metrology methods. I did some of this a decade ago (thesis) and while I think the content might be relevant, it also might be different enough to merit a first read-through before copying and running code.

Best of luck.