Clear Filters
Clear Filters

Plot a single pixel's (or pixel region's) intensity over frame number of a monochrome video

6 views (last 30 days)
I have been trying to simply plot one pixel's intensity value throughout a video for a while now and have not found anything that works.
I have tried using "Image Analyst's" demo that does almost this, and cannot get passed the error "MAP requires a 3xm array"
I'd imagine this shouldn't take too much code to get to work.
laurent jalabert
laurent jalabert on 17 Dec 2022
yes thank you, my mistake. I would say that x=y=100 does not change the philosophy of my question. I will use drawpoint function.
DGM on 18 Dec 2022
Edited: DGM on 18 Dec 2022
The reason for the static values is simply that interactive graphics tools (ginput(), getpts(), drawpoint(), etc) can't be demonstrated on the forum. The dummy values are to be removed and the ginput() line uncommented.
Unless the goal is a mask-based workflow, there really isn't any big advantage to using ROI objects. It offers extra functionality, but I don't see the point in managing the created object if all that's needed are coordinates.
ginput() Get one or more points, returning x,y coordinates and optional keypress info. Part of base MATLAB.
getpts() Similar to ginput(), but controls are slightly different. Requires Image Processing Toolbox.
drawpoint() Full object-oriented tool for interactive generation of point ROI objects. Requires R2018b+ and IPT

Sign in to comment.

Accepted Answer

Image Analyst
Image Analyst on 10 Jun 2018
The attached demo works just fine and there is no map issue. If you still have a problem, attach your movie in a .zip file.

More Answers (1)

laurent jalabert
laurent jalabert on 27 Dec 2022
I would like to improve this program, because when I create about 20 points to be monitored, the loop duration can reach 50sec per frame (Macbook pro i7, 16Gb DRAM, 1To SSD, Matlab 2021a with Image processing toolbox), and I have 4500 frames in my video. So it takes forever. Therefore I introduced step_frame to analyse a part of the main video, that is 450 frames. Even that, the loop is not optimized.
subplot (221) is showing the actual frame, I want to overlay the array of points selected by the user. Same on subplot(223) and subplot(224). The subplot(222) is a plot of all the selected array of blue intensity data.
This blue intensity is generated from im2gray function.
This program is indeed inspired from the movie_plot_intensity.m, but I adapted to my concern.
Any help for improving the computing time will be welcome.
%% Program that is doing :
% 1- play a video
% 2- place Npts points on this video
% 3- analyse the averaged Gray, R, G, B
% 4- add the BLUE intensity of the Npts points and associate a color
% 5- save as jpeg the figure containing the frames and plot
% 6- export the plot data to excel file.
% the problem of this program is mainly that it takes a lot of time when Npts =10 or 20 !
% how to improve it ?
clc; % Clear the command window.
close all; % Close all figures
imtool close all; % Close all imtool figures.
clear; % Erase all existing variables.
workspace; % Make sure the workspace panel is showing.
% declaration of constants
%Npts =20;
start_frame = 1; % start at frame 1
step_frame = 10; % display every 10 frames
fontSize = 16;
folder = fileparts(which('yourvideo.mp4'));
movieFullFileName = fullfile(folder, 'yourvideo.mp4');
if ~exist(movieFullFileName, 'file')
strErrorMessage = sprintf('File not found:\n%s\nYou can choose a new one, or cancel', movieFullFileName);
response = questdlg(strErrorMessage, 'File not found', 'OK - choose a new movie.', 'Cancel', 'OK - choose a new movie.');
if strcmpi(response, 'OK - choose a new movie.')
[baseFileName, folderName, FilterIndex] = uigetfile('*.mp4');
if ~isequal(baseFileName, 0)
movieFullFileName = fullfile(folderName, baseFileName);
videoObject = VideoReader(movieFullFileName);
numberOfFrames = videoObject.NumberOfFrames;
vidHeight = videoObject.Height;
vidWidth = videoObject.Width;
numberOfFramesWritten = 0;
[folder, baseFileName, extentions] = fileparts(movieFullFileName);
% open the video reader and run the video.
%CurrentFrameNumber = vid.DataSource.Controls.CurrentFrame
% place points onto the video frame and get coordinates array [x,y]
[x,y] = getpts(vid.Visual.Axes);
X=x; Y=y;
% the total number of points that were created is Npts
Npts = length(X);
% define 1 color for each points
couleur = parula(Npts);
% this is to discretize 1 line into Npts points (not used here)
%[x,y] = getline(vid.Visual.Axes);
%X=linspace(x(1),x(2),Npts); X=round(X);
%Y=linspace(y(1),y(2),Npts); Y=round(Y);
%hpt = drawline('Position',[x(1),y(1);x(2),y(2)],'StripeColor','white');
%hpt = drawpoint('Position',[x;y]);
% create the legend text relative to the points label 1,2, ... Npts.
% in this program, the Gray, R, G, B averaged values are also displayed.
for k = 1:Npts
txt = ['Gray','R','G','B',num2str(1:k)];
% for variable names in table (to export to excel)
% when exporting a table to excel, the variablenames VN have to be created.
C2 = arrayfun(@(x) sprintf('pt%d', x), 1:Npts, 'UniformOutput', false);
VN = [{'time','Gy','R','G','B'},C2{:}];
VN1 = VN';
variablenames = [string(VN1)];
% the video will start from start_frame number
nb = length(start_frame:step_frame:numberOfFrames);
% xx is the time array.
xx = (1./videoObject.FrameRate).*(start_frame:step_frame:numberOfFrames-start_frame+1);
% initialize the arrays
meanGrayLevels = zeros(nb, 1);
meanRedLevels = zeros(nb, 1);
meanGreenLevels = zeros(nb, 1);
meanBlueLevels = zeros(nb, 1);
SPBLUE = zeros(nb, Npts);
%% step 2 - record the figure sub 4 subplots and make a video
analyse_day= datestr(now,'CP_yyyymmdd_hhMMss'); % data treatment day
% output_video_name = strcat(analyse_day,'');
% v = VideoWriter(output_video_name,'Archival');
% v.VideoCompressionMethod
% open(v);
% the background is the first frame (start_frame)
background2 = read(videoObject, start_frame);
%% Main loop to read each frane and compute pixel intensities
hFIG = figure;
set(hFIG, 'units','normalized','outerposition',[0 0 1 1]);
for thisframe = start_frame : step_frame : numberOfFrames
kk = kk+1;
% Extract the frame from the movie structure.
thisFrame = read(videoObject, thisframe);
subplot(2, 2, 1);
caption = sprintf('Frame %4d of %d.', thisframe, numberOfFrames);
title(caption, 'FontSize', fontSize);
% if I place the labels on this frame, the program is taking more time
% if thisframe == start_frame
% for jj=1:Npts
% hpt(jj) = drawpoint('Position',[X(jj),Y(jj)],'Color',couleur(jj,:));
% hpt(jj).Label = num2str(jj);
% end
% end
% Calculate the mean gray level.
grayImage = im2gray(thisFrame);
meanGrayLevels(kk) = mean(grayImage(:));
% Npts Blue pixel intensity (:,:,3)
for jj=1:Npts
a = round(Y(jj)); b=round(X(jj));
spBlue = im2gray(thisFrame(a, b, 3));
SPBLUE(kk,jj) = spBlue;
% Calculate the averaged R, G, and B levels.
meanRedLevels(kk) = mean(mean(thisFrame(:, :, 1)));
meanGreenLevels(kk) = mean(mean(thisFrame(:, :, 2)));
meanBlueLevels(kk) = mean(mean(thisFrame(:, :, 3)));
% Plot the mean gray levels.
subplot(2, 2, 2);
hold off;
plot(xx,(meanGrayLevels), 'k-', 'LineWidth', 2,'DisplayName','Gray');hold on;
plot(xx,(meanRedLevels), 'r-', 'LineWidth', 2,'DisplayName','R');hold on;
plot(xx,(meanGreenLevels),'g-', 'LineWidth', 2,'DisplayName','G');hold on;
plot(xx,(meanBlueLevels), 'b-', 'LineWidth', 2,'DisplayName','B');hold on;
for jj=1:Npts
plot(xx,((SPBLUE(:,jj))),'Color',couleur(jj,:),'LineWidth', 1,'DisplayName',num2str(jj));hold on;
grid on;
% Put title back because plot() erases the existing title.
title('Mean Pixel Intensity', 'FontSize', fontSize);
%xlabel('Time (s)');
%ylabel('Pixel Intensity (a.u)');
numberOfFramesWritten = numberOfFramesWritten + 1
% Display the background image.
subplot(2, 2, 3);
title('background', 'FontSize', fontSize);
% if I place the labels on this frame, the program is taking even more time
% if thisframe == start_frame
% for jj=1:Npts
% hpt(jj) = drawpoint('Position',[X(jj),Y(jj)],'Color',couleur(jj,:));
% hpt(jj).Label = num2str(jj);
% end
% end
% plot difference image
subplot(2, 2, 4);
% Calculate a difference between this frame and the background.
J = imsubtract(thisFrame,background2);
zb = J(:,:,3); %get the blue intensity array
I3 = flipdim(zb ,1); %# vertical flip
I4 = flipdim(I3,2); %# horizontal+vertical flip
I5 = flipdim(I3,1);
myImage = imshow(I5, 'Colormap', jet(256));
axis on;
caxis([0, 200]);
hold on
% if thisframe == start_frame
for jj=1:Npts
textLabel = sprintf('(%.0f)', jj);
text(X(jj),Y(jj), textLabel);
hold on
%hpt(jj) = drawpoint('Position',[X(jj),Y(jj)],'Color',couleur(jj,:));
%hpt(jj).Label = num2str(jj);
% end
%drawnow; % Force it to refresh the window
title('Image - Background', 'FontSize', fontSize);
% making a video from the figure is generating some error randomly.
%F = getframe(hFIG);
cd('your output folder')
savedir = strcat(analyse_day,'_',sprintf('%04d',thisframe),'.jpg');
% array to be saved
data = [xx',meanGrayLevels,meanRedLevels,meanGreenLevels,meanBlueLevels,SPBLUE]
% find any remaining zeros and remove them
IND = find(data(:,2)==0);
%% create the plot shown in of subplot(222) to check the data to be exported.
% this is not mandatory and it is done outside of the loop, so it is not
% time consuming.
couleur = parula(Npts);
size_data = size(data,2);
'landscape','Color',[1 1 1], 'OuterPosition',[1 1 800 800]);
xx = data(:,1);
plot(xx,data(:,2),'k-', 'LineWidth', 2,'DisplayName','Gray');hold on;
plot(xx,data(:,3),'r-', 'LineWidth', 2,'DisplayName','R');hold on;
plot(xx,data(:,4),'g-', 'LineWidth', 2,'DisplayName','G');hold on;
plot(xx,data(:,5),'b-', 'LineWidth', 2,'DisplayName','B');hold on;
for jj=1:Npts
plot(xx,((data(:,5+jj))),'Color',couleur(jj,:),'LineWidth', 1,'DisplayName',num2str(jj));hold on;
HANDLE = gca;
get( HANDLE );
set( HANDLE, 'Color','w');% [0.8,0.8,0.8] )
grid on;
xlabel('time (s)'); ylabel('Blue Intensity');
grid on
for jj = 1:Npts
xpos = data(end,1);
ypos = data(end,5+jj);
labels = num2str(jj) ;
h = text(xpos, ypos, labels,'FontSize',16)
output_name = strcat(analyse_day,'_',baseFileName,'_','GrRGB_',num2str(Npts),'pts.xlsx');
laurent jalabert
laurent jalabert on 27 Dec 2022
thank you for the advices. Indeed, the aim of displaying everything in the loop is that I record the figure and I later, I gather those images to create a movie, showing nicely what is happening during this video. It is indeed easy to save only 1 figure once, at the end, but this does not show the evolution of some events happening during this video.
laurent jalabert
laurent jalabert on 27 Dec 2022
the "cla" in subplot(224) was added, and it is amazingly solving my initial problem. Really thanks a lot !
subplot(2, 2, 4);

Sign in to comment.

Community Treasure Hunt

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

Start Hunting!