【问题标题】:Getting heart rate from simple video: code inside从简单视频中获取心率:内部代码
【发布时间】:2014-08-03 03:01:52
【问题描述】:

我正在尝试从我的皮肤视频中找到心率。为了做到这一点,我从我的视频帧中截取了一个像素的裁剪矩形,并对所有这些像素中的红色(或绿色)分量进行平均(然后,当然,看看这个平均值是如何逐帧变化的)。

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

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

我的最终目标是通过这种分析区分活皮肤和非血管化皮肤。所以理解为什么我会得到这些无生命物体的频率峰值是至关重要的。

谁能在自己的视频上运行此代码并帮助解释我是否只是个白痴?

相机拍摄:

柯达 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')

【问题讨论】:

  • 您有以~60Hz 闪烁的荧光灯吗?或者您所在地区的交流频率如何?或者像电视这样的其他东西,或者具有刷新率并产生反射的东西(即使你自己的眼睛看不到)?
  • 我在自然光(室外)和有荧光灯的办公室都试过。 60Hz 相当快。我似乎无法理解所有信号中似乎出现的 1、2、5 和 10Hz 分量。这些似乎是我正在使用或做的事情所固有的,但我不确定。希望有人以前经历过这种情况,或者有一个他们可以自己播放的视频。
  • 我在想干扰节拍的频率接近但不完全是 30fps 帧速率的倍数(开始时可能正好是 30Hz,也可能不完全是 30Hz)。这将在频域中出现一些突出的频率分量......
  • 我将在本周的某个时间在不同的位置测试自然光,但有些事情告诉我还有更多的故事。如果您通过代码抛出视频,请告诉我您是否看到了我所看到的。感谢您的帮助!
  • 我猜这是视频编码的产物。可能它以 1 Hz(每 30 个)生成 i 帧,并且可能每 3 个(10 Hz)生成 P 帧。 (我在 iPhone 上的视频上尝试了您的代码,但没有看到尖峰)。

标签: ios matlab camera signal-processing video-processing


【解决方案1】:

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

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

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

我会怎么做:

  1. 我会根据帧与帧的差异进行操作。
  2. 大多数视频编解码器的时间间隔不一致。我会得到这些值,以便我可以跟踪实际(非假设)时间的变化。您当前的(可能是错误的)信号可能来自编解码器以及硬件。
  3. 我会制作一部电影,使得每个新帧都是它与前一帧之间的差异。我会看 20 次,看看我的(惊人的)人类视觉处理系统是否能清楚地看到任何与心跳相关的东西,或者明显不是。
  4. 对于“NOT”,通过掩码、过滤器等将它们从处理中移除。 对于相关,想办法使它们成为感兴趣的区域 删除其他所有内容,截断像素强度直方图,或 其他图像增强(模糊、锐化、重新着色、边缘、旋转等 最大的信号是沿着更新的像素轴,然后处理..)

等人的视觉仪器能得到很好的信号后,我会努力让数学/计算机得到信号,清楚地知道人的机器是优越的。

如果我要跟踪随时间移动的点/特征,我会研究亚像素计量方法。我在 10 年前做过其中的一些 (thesis),虽然我认为内容可能是相关的,但它也可能有所不同,值得在复制和运行代码之前先通读一遍。

祝你好运。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-05-31
    • 1970-01-01
    • 2015-12-25
    • 1970-01-01
    • 1970-01-01
    • 2012-12-04
    • 1970-01-01
    相关资源
    最近更新 更多