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)
您的目的是“从我的皮肤视频中找到心率”和“...通过此分析区分活体皮肤与非血管化皮肤”,但您的方法是“拍摄视频...裁剪...平均红色(或绿色)分量..看看它如何变化”。
我觉得前提有问题。平均意味着多数信号占主导地位。人类视觉是视觉数据的(令人惊奇的)处理器,通常需要数十年的努力才能让机器达到他们所做的哪怕一小部分。如果您无法用眼睛观察周围 90% 的人并测量他们的心率,那么平均方法可能不是最佳选择。
您可以使用无数的统计数据来查看分布如何随时间变化,而平均值只是其中之一。如果您只查看平均值,您可能会丢失信息。
我将如何做到这一点:
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.
| 归档时间: |
|
| 查看次数: |
1382 次 |
| 最近记录: |