TransWikia.com

guidata not updating in MATLAB GUI

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

3 Answers

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

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP