Stack Overflow Asked by Matias Andina on January 2, 2021
I have a MATLAB GUI with:
1) A VLC window controlled by activex.
2) A bunch of radiobuttons to “annotate” the video on particular frames.
I have working code, but I’m missing the output from the function that is called for annotation. This function, Annotate
, should substitute the annotated values into a previously created table final_data
. I can display the substituted values to console, I would expect guidata
to update handles
, so the output of my main function should contain a .final_data
field with the updated values. However, calling .final_data
on the output object returns the empty placeholder values.
function Annotate(varargin)
hFigure = findobj('tag', 'VideoPlay');
handles = guidata(hFigure);
% change value of the orther button to 0
set(handles.hNotAnnotateButton, 'Value', 0);
mypos = handles.vlc.input.Position; % >> proxy to calculate frame
behavior = handles.Behavior; % >>> Tag to be annotated
% Calculate frame
myframe = ceil(handles.vlc.input.Time/1000 * handles.frameRate) - 1;
handles.final_data.behavior(myframe) = behavior;
display(handles.final_data(myframe, :)) % displays properly
guidata(handles.hFigure, handles) % not updating handles??
end
Just in case, here’s the full function
function handles = AnnotateVideo(filepath)
% Get some initial data from the video
filepath = fullfile(filepath);
% Get file duration
v = VideoReader(filepath);
handles.duration = v.Duration;
handles.frameRate = v.FrameRate;
delete(v)
total_frames = ceil(handles.duration * handles.frameRate) - 1;
%% Make some variables
handles.final_data.frameID = (1:total_frames)';
handles.final_data.behavior = strings(total_frames, 1);
% change format to table
handles.final_data = struct2table(handles.final_data);
% Place Holder for behavior
%% Build the Figure/GUI
% Video will be kept on handle
handles.filepath = filepath;
% Create figure to receive activex
handles.hFigure = figure('position', [50 50 1300 560], ...
'menubar', 'none', 'numbertitle', 'off', ...
'name', ['Video: ' filepath],...
'tag', 'VideoPlay', 'resize', 'on');
% Create play/pause and seek to 0 button
handles.hTogglePlayButton = uicontrol(handles.hFigure, ...
'position', [0 540 80 21], ...
'string', 'play/pause', 'callback',...
@TogglePlayPause);
handles.hSeekToZeroButton = uicontrol(handles.hFigure, ...
'position', [81 540 80 21], ...
'string', 'begining', 'callback',...
@SeekToZero);
handles.hGoToStartFrameButton = uicontrol(handles.hFigure, ...
'position', [161 540 80 21], ...
'string', 'StartFrame', 'callback',...
@SeekToStartFrame);
handles.hGoToEndFrameButton = uicontrol(handles.hFigure, ...
'position', [241 540 80 21], ...
'string', 'EndFrame', 'callback',...
@SeekToEndFrame);
%% Annotate button
handles.hAnnotateButton = uicontrol(handles.hFigure, ...
'Style', 'radiobutton', ...
'position', [980 320 100 41], ...
'String', 'Annotate', 'callback',...
@Annotate);
handles.hNotAnnotateButton = uicontrol(handles.hFigure, ...
'Style', 'radiobutton', ...
'position', [1100 320 100 41], ...
'String', 'Not-Annotate', ...
'Value', 1, ...
'callback', @NotAnnotate);
%% Make radio buttons for ethogram
handles.radio(1) = uicontrol('Style', 'radiobutton', ...
'Callback', @myRadio, ...
'Units', 'pixels', ...
'Position', [980, 500, 80, 22], ...
'String', 'Non-specific', ...
'Value', 0);
handles.radio(2) = uicontrol('Style', 'radiobutton', ...
'Callback', @myRadio, ...
'Units', 'pixels', ...
'Position', [980, 480, 80, 22], ...
'String', 'Rearing', ...
'Value', 0);
handles.radio(3) = uicontrol('Style', 'radiobutton', ...
'Callback', @myRadio, ...
'Units', 'pixels', ...
'Position', [980, 460, 80, 22], ...
'String', 'Snif', ...
'Value', 0);
handles.radio(4) = uicontrol('Style', 'radiobutton', ...
'Callback', @myRadio, ...
'Units', 'pixels', ...
'Position', [980, 440, 80, 22], ...
'String', 'Retrieving', ...
'Value', 0);
handles.radio(5) = uicontrol('Style', 'radiobutton', ...
'Callback', @myRadio, ...
'Units', 'pixels', ...
'Position', [1100, 500, 80, 22], ...
'String', 'Self-Groom', ...
'Value', 0);
%% Activex control for VLC player
% Create activex control
handles.vlc = actxcontrol('VideoLAN.VLCPlugin.2', [0 0 960 540], handles.hFigure);
% Format filepath so that VLC can use it
% Read into vlc
filepath = ['file://localhost/' filepath];
% Add file to playlist
handles.vlc.playlist.add(filepath);
% Play file
handles.vlc.playlist.play();
% Deinterlace
handles.vlc.video.deinterlace.enable('x');
% Go back to begining of file
handles.vlc.input.time = 0;
% Register an event to trigger when video is being played regularly
handles.vlc.registerevent({'MediaPlayerTimeChanged', @MediaPlayerTimeChanged});
% Position changed
handles.vlc.registerevent({'MediaPlayerPositionChanged', @MediaPlayerPositionChanged});
% Save handles
guidata(handles.hFigure, handles);
%% Helper functions and button callbacks
function MediaPlayerPositionChanged(varargin)
hFigure = findobj('tag', 'VideoPlay');
handles = guidata(hFigure);
% Get position
handles.mypos = handles.vlc.input.Position;
% Get frame
handles.myframe = handles.vlc.input.Time;
% If position is changing AND annotate button is 'ON' (value == 1)
% Annotate
will_annotate = get(handles.hAnnotateButton, 'Value');
if(will_annotate)
Annotate
end
end
%% Display running time in application title
function MediaPlayerTimeChanged(varargin)
hFigure = findobj('tag', 'VideoPlay');
handles = guidata(hFigure);
myframe = handles.vlc.input.Time;
set(hFigure, 'name', [handles.filepath ' ; ' num2str(myframe/1000) ' sec.']);
end
%% Annotate: MAIN 'Looping' Function
% called when position is changed and annotate button
function Annotate(varargin)
hFigure = findobj('tag', 'VideoPlay');
handles = guidata(hFigure);
% change value of the orther button to 0
set(handles.hNotAnnotateButton, 'Value', 0);
mypos = handles.vlc.input.Position;
behavior = handles.Behavior;
% Calculate frame
myframe = ceil(handles.vlc.input.Time/1000 * handles.frameRate) - 1;
handles.final_data.behavior(myframe) = behavior;
display(handles.final_data(myframe, :))
guidata(handles.hFigure, handles)
end
%% Not annotate, basic placeholder to not annotate
function NotAnnotate(varargin)
hFigure = findobj('tag', 'VideoPlay');
handles = guidata(hFigure);
% change value of the orther button to 0
set(handles.hAnnotateButton, 'Value', 0);
end
function TogglePlayPause(varargin)
% Toggle Play/Pause
hFigure = findobj('tag', 'VideoPlay');
handles = guidata(hFigure);
handles.vlc.playlist.togglePause();
end
function SeekToZero(varargin)
% Seek to begining of file
hFigure = findobj('tag', 'VideoPlay');
handles = guidata(hFigure);
handles.vlc.input.Time = 0;
end
function SeekToStartFrame(varargin)
% Seek StartFrame of file
hFigure = findobj('tag', 'VideoPlay');
handles = guidata(hFigure);
handles.vlc.input.Time = StartFrame;
end
function SeekToEndFrame(varargin)
% Seek to EndFrame of file
hFigure = findobj('tag', 'VideoPlay');
handles = guidata(hFigure);
handles.vlc.input.Time = EndFrame;
end
function myRadio(RadioH, EventData)
handles = guidata(RadioH);
otherRadio = handles.radio(handles.radio ~= RadioH);
set(otherRadio, 'Value', 0);
set(handles.hAnnotateButton, 'Value', 0);
handles.Behavior = RadioH.String;
sprintf('Switching to...%s', handles.Behavior)
guidata(handles.hFigure, handles)
end
% End of global function
end
drawnow updates figures and processes any pending callbacks. Use this command if you modify graphics objects and want to see the updates on the screen immediately.
drawnow
Answered by niko on January 2, 2021
This is because the output variable is never updated with the new guidata...
Running your program with:
handles = AnnotateVideo(<filepath>)
You can update the structure handle with (from the commandline):
handles = guidata(handles.hFigure);
Answered by Daniel Aldrich on January 2, 2021
This is a mix of updates and answers. I explored 2 options. First was leaving everything as is but running a global output data
from the console before running the GUI
and having things go there. The second approach is similar, but I unnested all the functions into separate .m
files. Instead of a global, I have Annotate
to call a assign('base', 'outputdata', outputdata)
. It is nasty and I don't fully like it, but it partially gets the job done. I welcome any suggestions to make it better.
Answered by Matias Andina on January 2, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP