video processing for motion detection

can i track the motion of a motor from a video? i tried histogram plotting but exporting data is hard

12 comentarios

Turlough Hughes
Turlough Hughes el 8 de Dic. de 2019
Depends what footage you have and what you want to track. Are you looking for rpm? You should attach a shortish video.
Saffana Siddiqua
Saffana Siddiqua el 8 de Dic. de 2019
i attached the footage . and yes. i want to measure rpm
Turlough Hughes
Turlough Hughes el 8 de Dic. de 2019
You could do it alright, I would probably look at just processing a single pixel in each image to detect the flash from the laser. Is there are reason have to use video footage? You could set up a photodiode to detect the laser, like a laser tachometer, and that would be much more efficient (MATLAB also supports arduino).
Saffana Siddiqua
Saffana Siddiqua el 8 de Dic. de 2019
the main idea behind this was to generate histogram for each frame , combine them together and then calculate the frequency. i could generate the histograms but can not combine them in one plot to perform further opertaions. how can i do that? or how can i directly measure the rpm form the video?
Do you want each histogram to go into one row or one column, and then build up an image of histograms and then show them with imshow()? Like
histImage = zeros(numberOfFrames, 256);
for k = 1 : numberOfFrames
thisFrame = .......whatever.
counts = histcounts(thisFrame); % Get histogram of this frame.
histImage(row, :) = counts; % Add this frame's histogram to the image.
imshow(histImage, []); % Display the histogram image.
drawnow;
end
workingDir = 'C:\Users\Documents\MATLAB';
mkdir(workingDir);
mkdir(workingDir,'images');
shuttleVideo = VideoReader('20190504_181751.mp4');
for ii = 1:shuttleVideo.NumberOfFrames
img = read(shuttleVideo,ii);
[rows,cols] = size(img);
histogram_values = zeros(256,1);
color('RGB');
for i = 1:rows
for j = 1:cols
p = double(img(i,j)) + 1;
histogram_values(p) = histogram_values(p) + 1;
end
end
%// Show histogram
ll=bar(0:255, histogram_values, 'histc');
saveas(ll, sprintf('HIS%d.png',ii));
% Write out to a JPEG file (img1.jpg, img2.jpg, etc.)
imwrite(img,fullfile(workingDir,'images',sprintf('img%d.jpg',ii)));
end
imageNames = dir(fullfile(workingDir,'images','*.jpg'));
imageNames = {imageNames.name}';
imageStrings = regexp([imageNames{:}],'(\d*)','match');
imageNumbers = str2double(imageStrings);
[~,sortedIndices] = sort(imageNumbers);
sortedImageNames = imageNames(sortedIndices);
Saffana Siddiqua
Saffana Siddiqua el 8 de Dic. de 2019
this is my code, i am getting invidual histgram plot for each frame. what i have to modify here?
Image Analyst
Image Analyst el 8 de Dic. de 2019
How do you want the histograms to appear? As an image where the brightness of the pixel is related to the counts in the bin, or as a bunch of overlapping line plots where you can see a line plot of all the histograms superimposed on each other?
Saffana Siddiqua
Saffana Siddiqua el 8 de Dic. de 2019
a single line plot, where the histograms are plotted side by side. not imposed. they have to be distinguished or else i cant have that one re apprearing frame .
Image Analyst
Image Analyst el 8 de Dic. de 2019
Like concatenated? Stitched end-to-end? Maybe with a vertical line at the place that separates the different line plots?
Saffana Siddiqua
Saffana Siddiqua el 8 de Dic. de 2019
yes, concatenated. separation of plots is not necessery.
Saffana Siddiqua
Saffana Siddiqua el 10 de Dic. de 2019
help me out please :(

Iniciar sesión para comentar.

 Respuesta aceptada

Turlough Hughes
Turlough Hughes el 8 de Dic. de 2019
Editada: Turlough Hughes el 11 de Dic. de 2019
So the method I suggested was to look at a single pixel, though you could also look at a few, or the entire image histogram, up to you. Here I track the R component of the mid pixel of each frame and then find local maxima which are greater than a nominal threshold value.
framerate=29.53; % I don't see how to get this from the video object directly.
threshold=0.15;
v=vision.VideoFileReader('vid.mp4');
c=0;
while ~isDone(v)
c=c+1;
f=step(v);
data(c)=f(360,720,1); % for green just replace the with, data(c)=f(360,720,2);
end
figure(), plot(data)
idx1=find(data(2:end-1) > data(1:end-2) & data(2:end-1) > data(3:end))+1; % find local maxima, 'data2'
data2=data(idx1);
hold on, plot(idx1,data2,'or'); % shows local maxima in plot
idx2=find(data2>threshold); % local maxima satisfying threshold
peakFrame=idx1(idx2);
hold on, plot(peakFrame,data2(idx2),'.k','MarkerSize',15) % shows peaks that pass threshold.
numFrames=peakFrame(end)-peakFrame(1) % number of frames from first to last flash.
revs=length(data2(idx2))-1; % Corresponding number of revolutions.
duration=numFrames/framerate; % numFrames/FramesPerSecond = duration in seconds
rpm=revs/(duration/60)
EDIT: as per comments below.

11 comentarios

For VideoReader it could go something like this:
framerate=29.53;
threshold=50;
v=VideoReader('vid.mp4');
c=0;
while hasFrame(v)
c=c+1;
f=readFrame(v);
data(c)=f(360,720,1);
end
figure(), plot(data)
data2=data(islocalmax(data));
revs=length(data2(data2>threshold));
duration=framerate/c;
rpm=revs/(duration/60)
Saffana Siddiqua
Saffana Siddiqua el 8 de Dic. de 2019
it shows=Undefined function 'hasFrame' for input arguments of type 'VideoReader'.
and with the vision toolbox it shows=Undefined function 'islocalmax' for input arguments of type 'single'.
Sounds like you have an old version of Matlab. Can you confirm what version of MATLAB you have? hasFrame was introduced in 2014b while islocalmax was introduced in 2017b. Just type in
ver
Saffana Siddiqua
Saffana Siddiqua el 9 de Dic. de 2019
2014a
Turlough Hughes
Turlough Hughes el 9 de Dic. de 2019
Editada: Turlough Hughes el 9 de Dic. de 2019
Ok, I used the vision toolbox functions and some logic to replace islocalmax. I've included some plotting for you to step through to see how the code is working. This gets your rpm directly by processing just the middle pixel of the image.
framerate=29.53;
threshold=0.15;
v=vision.VideoFileReader('vid.mp4');
c=0;
while ~isDone(v)
c=c+1;
f=step(v);
data(c)=f(360,720,1);
end
figure(), plot(data)
idx1=find(data(2:end-1) > data(1:end-2) & data(2:end-1) > data(3:end))+1; % find local maxima, 'data2'
data2=data(idx1);
hold on, plot(idx1,data2,'or'); % shows local maxima in plot
idx2=find(data2>threshold); % local maxima satisfying threshold
hold on, plot(idx1(idx2),data2(idx2),'.k','MarkerSize',15) % shows peaks that pass threshold.
revs=length(data2(idx2));
duration=c/framerate; % numFrames/FramesPerSecond = duration in seconds
rpm=revs/(duration/60)
edit; equation for duration was incorrect.
Saffana Siddiqua
Saffana Siddiqua el 9 de Dic. de 2019
it gave me a result but i dont understand how it is working and also the rpm is in exponential form.
Turlough Hughes
Turlough Hughes el 9 de Dic. de 2019
Each frame is a 720 by 1280 by 3 rgb image, ie 720 by 1280 pixel where each pixel an r,g,b component. I nominally chose to study the intensity of the r value of the center pixel of each frame in your video to detect a flash from the laser. You can see these flashes as as prominent peaks in the plot, (red intensity on y axis, frame number on x axis). The next part of the code defines some rules to autmatically locate the peaks in your data, they are:
  • that the intensity of r for this pixel on the given frame is a local max. ie where the r intensity of adjacent frames is less than the current one (results are red circle point plots)
  • that this local max is also greater than a certain threshold value. (results are the black dots)
The revolutions, 'revs', corresponds to the number of laser flashes, and then to get revs per second you divide the number of revolutions by the duration in minutes.
One can get the duration in seconds by dividing the number of frames, c, by the framerate, then dividing again by 60 to convert from seconds to minutes.
Regarding the format that data is printed to the screen, see the following documentation.
Saffana Siddiqua
Saffana Siddiqua el 10 de Dic. de 2019
Editada: Saffana Siddiqua el 10 de Dic. de 2019
what if i want to know the intensity of green or blue light in the center pixel, where will it be changed?
also. the rpm isnt correct. the thing is i will get the duration by multiplying the framerate with number of frames. in the code, u used framerate directly. framerate wasnt calculated. the rpm should be around 217 but it is giving a resul of much higher . cant i extract the info about duration of the video directly?
Saffana Siddiqua
Saffana Siddiqua el 10 de Dic. de 2019
i cant find any function to determine the framerate with vision.videofilereader.
Turlough Hughes
Turlough Hughes el 11 de Dic. de 2019
i cant find any function to determine the framerate with vision.videofilereader.
Neither can I. I took the framerate from looking at file details. Surely there's a way to get it with code but I can't see how. I see you've opened another question on this though.
what if i want to know the intensity of green or blue light in the center pixel
See comments in my edit to my original answer, also have a look at the following documentation.
the thing is i will get the duration by multiplying the framerate with number of frames
you get duration from NumberOfFrames/framerate: . I originally had framerate/NumberOfFrames but had fixed that before my last comment.
Saffana Siddiqua
Saffana Siddiqua el 28 de En. de 2020
hey,
so i could extract the framerate using videoReader.
now, the number of frames is showing 446, wheres the number of frames of the whole video is 265. shouldnt the number be less? cause i am only taking the frames with the flashes, no?

Iniciar sesión para comentar.

Más respuestas (0)

Categorías

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by