【发布时间】:2018-04-03 22:18:23
【问题描述】:
我有一个 MATLAB GUI:
1) 一个由activex控制的VLC窗口。
2) 一组单选按钮,用于在特定帧上“注释”视频。
我有工作代码,但我缺少调用注释的函数的输出。此函数Annotate 应将带注释的值替换为先前创建的表final_data。我可以将替换的值显示到控制台,我希望guidata 更新handles,所以我的主函数的输出应该包含一个带有更新值的.final_data 字段。但是,在输出对象上调用 .final_data 会返回空的占位符值。
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
以防万一,这是完整的功能
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
【问题讨论】:
-
你试过
guidata(hFigure, handles)吗?也许handles的hFigure字段在某处被覆盖。另外,如果你不使用任何输入参数,为什么你的所有函数中都有varargin?你可以说function Annotate。但更好的是function Annotate(hFigure),调用时可以传递图形句柄。这样您就不需要一直寻找它。 -
@CrisLuengo
guidata(hFigure, handles)产生相同的结果。我有varargin,因为随着事情的发展,我将传递更多的论据,这是对我自己的一个提醒。没错,我可以通过hFigure,但你认为问题与不通过有关吗? -
我不知道可能是什么问题。如果我是你,我会在这个函数中设置一个断点,看看
hFigure的值是什么,看看它是否正确设置了guidata,然后看看调用这个函数后还会发生什么。如果您设置断点(您可以在编辑器中执行此操作),您的程序将在该行停止。然后在 MATLAB 命令提示符下,您可以正常执行命令,但您将在函数的工作区中,因此您可以随意检查和修改变量。您可以逐行执行程序。这是弄清楚发生了什么的最好方法。 -
@CrisLuengo 我会尝试这种方法。应该注意的是,
display(...)调用将正确的替换打印到控制台。一定是guidata没有按预期更新 -
... 或其他东西稍后将其改回。
标签: matlab video activex matlab-guide