I need to retrieve/register/remember last 10 frames from the video file. This is a small version of a bigger project for detecting micro-expressions. Therefore it need to check if "lines" have been showing for last 10 frames (detected) or if it is showing for more than 10 then it not detected. I'm also enforced to work with vision.VideoFileReader
and vision.OpticalFlow
. How to do this?
file = 'MEXTest.mp4'; vid = vision.VideoFileReader(file,'ImageColorSpace','RGB','VideoOutputDataType','single'); optFlo = vision.OpticalFlow('OutputValue','Horizontal and vertical components in complex form','ReferenceFrameDelay',3); shapeInsertOptFloColor = vision.ShapeInserter('Shape','Lines','BorderColor','Custom','CustomBorderColor',[255 255 0]); numFrames = 0; frameList = {}; hasLines = zeros(10, 1, 'logical'); figH = figure; while ~isDone(vid) colorFrame = step(vid); colorFrameRes = imresize(colorFrame,0.3); grayFrame = rgb2gray(colorFrameRes); optFloVectors = step(optFlo, grayFrame); lines = oflo(optFloVectors,20); motionVectors = step(shapeInsertOptFloColor, colorFrameRes, lines); imshow(motionVectors); title('Optical Flow on Frame'); notEmpty = ~isempty(lines); if numel(notEmpty) ~= 1, notEmpty = 1; end hasLines = [hasLines(2:end); notEmpty]; if numFrames >= 10 frameList = [frameList(2:end) colorFrame]; else frameList = [frameList colorFrame]; end numFrames = numFrames + 1; if numFrames >= 10 && all(hasLines) disp('Micro-Expression Detected') else disp('Not detected') end if ~ishghandle(figH) close all break end end release(vid);
2 Answers
Answers 1
If all you are trying to do is find out if any points have been found in each of the last 10 frames, you can do something like this:
vid = vision.VideoFileReader('MEXTest.mp4','ImageColorSpace','Intensity','VideoOutputDataType','uint8'); numFrames = 0; frameList = {} hasPoints = zeros(10, 1, 'logical') while ~isDone(vid) frame = step(vid); points = detectMinEigenFeatures(frame); notEmpty = ~isempty(points) if numel(notEmpty) ~= 1, notEmpty = 1; end % Do the check for 10 frames before this step % if you want to exclude the current frame from the 10 hasPoints = [hasPoints(2:end); notEmpty] % Stashing the frames may not be necessary, this % just shows how to build up a circular buffer if numFrames >= 10 frameList = [frameList(2:end) frame] else frameList = [frameList frame] end % Count last frame now that it has been added numFrames = numFrames + 1; if numFrames >= 10 && all(hasPoints) disp('Detected') else disp('Not Detected') end end release(vid)
The circular buffer frameList
will keep track of the last 10 frames. That step is not really crucial. What is crucial is hasPoints
which stores a flag equal to ~isempty(points)
for each of the last 10 frames. If all(hasPoints)
is true, than all of the last 10 frames detected a feature.
This solution is not super-efficient because it reallocates the accumulation arrays repeatedly, but it only does so for 10 frames using this solution for a circular buffer. You know what they say about premature optimization though.
Keep in mind that I do not check if the points are the ones you want in every case, just that the last 10 frames have some points detected. From your comments, it seems as though this is an acceptable interpretation.
Answers 2
I have not worked so much with videos - but a general procedure would be to store it in an array of structs. Call if frames, then you can initialize it with:
frames(10) = struct('prob1',0,'prob2',0,...,'probn',0);
where prob1, prob2,..., probn is the properties of the frame you want to save. Then every time you load a frame, you save the properties of that frame to a struct frame in the same manner.
frame = struct('prob1',val1,'prob2',val2,...,'probn',valn);
where val1, val2, ..., valn, be be everything, including the frame as a matrix. After this save it to the list
frames = [frames(2:end),frame];
then at every point in time you have the properties you need from the 10 previous frames, which you access by:
frames(2).prob2
which will give you the second property of the frame 8 frames ago. So it is just a minor change from what you already have, but (if I understood your question correctly) it should solve the problem.
0 comments:
Post a Comment