gusucode.com > vision工具箱matlab源码程序 > vision/+vision/+internal/+calibration/+tool/ImageCaptureTab.m
classdef ImageCaptureTab < vision.internal.uitools.AbstractTab % ImageCaptureTab Defines key UI elements of the Image Capture Tab of Camera Calibrator App % % This class defines all key UI elements and sets up callbacks that % point to methods inside the CameraCalibrationTool class. % Copyright 2014 The MathWorks, Inc. properties (Access=private) %% Device Section DeviceComboBox PropertiesButton PropertiesPanel %% Settings Section CaptureIntervalEdit CaptureIntervalSlider % Number of images NumImagesCaptureEdit NumImagesCaptureSlider SaveLocationEdit CurrentSaveLocation BrowseButton %% Capture Section CaptureButton %% Close Section CloseButton %% Listeners CaptureIntervalSliderListener CaptureIntervalEditListener SaveLocationEditListener NumImagesCaptureEditListener NumImagesCaptureSliderListener % Track button status CurrentButtonState end properties (GetAccess=public, SetAccess=private) % Current status of Image Capture Tab CaptureFlag % Store device name SavedCamera % All images that image capture tab has acquired in a session % (emptied when you close Image Capture Tab). Images % Corresponds to images captured in current Start/Stop NumImagesCaptured % Flag to indicate if any images were captured since tab was open AnyImagesCaptured % Icons for images to show up in the Data Browser ImageIcons % Labels for images to show up in the Data Browser ImageLabels % Index where the unsaved images begin. StartIndex % Timer object for capture TimerObj % Timer object for status text StatusTimerObj TimeRemaining % @TODO: Timer object for countdown end properties (Access=private) CameraObject = [] PreviewObject ToolGroupName end properties (Constant) MinInterval = 1 MaxInterval = 60 MinImages = 2 MaxImages = 100 end events % Event for Closing Image Capture Tab. CloseTab end methods (Access=public) % Constructor function this = ImageCaptureTab(tool) this = this@vision.internal.uitools.AbstractTab(tool, ... vision.getMessage('vision:caltool:ImageCaptureTabName'), ... vision.getMessage('vision:caltool:ImageCaptureTab')); this.CaptureFlag = false; this.ToolGroupName = tool.getGroupName(); this.AnyImagesCaptured = false; % Initialize this.reset(); this.createWidgets(); this.installListeners(); end % Implement as inheriting from AbstractTab - do not see use at all % now. function testers = getTesters(~) testers = []; end % Creates and starts a preview. function createDevice(this) if strcmpi(this.SavedCamera, this.DeviceComboBox.SelectedItem) constructWithResolution = true; else constructWithResolution = false; this.PropertiesPanel = []; end this.updateDeviceSection(this.DeviceComboBox, constructWithResolution); end % Close preview function closePreview(this) if ~isempty(this.CameraObject) && isvalid(this.CameraObject) closePreview(this.CameraObject); % Stops the timer end end % Preview function preview(this) if ~isempty(this.CameraObject) && isvalid(this.CameraObject) [width, height] = this.getResolution; tool = this.getParent; drawImage(tool.ImagePreviewDisplay, width, height); replaceImage(tool.ImagePreviewDisplay, width, height); preview(this.CameraObject, tool.ImagePreviewDisplay.ImHandle); end end % Update property states. function updatePropertyStates(this) % Disable ability to change devices if images have been % captured. if this.AnyImagesCaptured this.DeviceComboBox.Enabled = false; this.DeviceComboBox.Peer.setToolTipText(vision.getMessage('vision:caltool:DisabledCameraDropDownToolTip')); if ~isempty(this.PropertiesPanel) this.PropertiesPanel.DevicePropObjects.Resolution.ComboControl.Enabled = false; this.PropertiesPanel.DevicePropObjects.Resolution.ComboControl.Peer.setToolTipText(vision.getMessage('vision:caltool:DisabledResolutionDropDownToolTip')); end else this.DeviceComboBox.Enabled = true; this.DeviceComboBox.Peer.setToolTipText(vision.getMessage('vision:caltool:EnabledCameraDropDownToolTip')); if ~isempty(this.PropertiesPanel) this.PropertiesPanel.DevicePropObjects.Resolution.ComboControl.Enabled = true; this.PropertiesPanel.DevicePropObjects.Resolution.ComboControl.Peer.setToolTipText(vision.getMessage('vision:caltool:EnabledResolutionDropDownToolTip')); end end end function resetAll(this) this.AnyImagesCaptured = false; % Reset properties panel here. this.PropertiesPanel = []; this.SavedCamera = []; reset(this); end end methods (Access=private) function createWidgets(this) % Creates the widgets on the toolstrip %% Create Device Widgets createDeviceWidgets(this); %% Create Settings Widgets createSettingsWidgets(this); %% Create Capture Widgets createCaptureWidgets(this); %% Create Close Widgets createCloseWidgets(this); %% Update button states. updateButtonStates(this, this.CurrentButtonState); end function createDeviceWidgets(this) %% Toolstrip sections deviceSection = toolpack.desktop.ToolSection('DeviceSection',... vision.getMessage('vision:caltool:DeviceSection')); devicePanel = toolpack.component.TSPanel(... '10px,f:p,10px,f:p,10px',... '10px,f:p,10px,f:p,10px'); devicePanel.Name = 'DevicePanel'; % Device drop down deviceLabel = toolpack.component.TSLabel(vision.getMessage('vision:caltool:DeviceDropDown')); % Get available webcams cams = this.enumerateCameras; this.DeviceComboBox = toolpack.component.TSComboBox(cams); this.DeviceComboBox.Name = 'DeviceCombo'; this.DeviceComboBox.Peer.setToolTipText(vision.getMessage('vision:caltool:EnabledCameraDropDownToolTip')); % Create buttons. this.PropertiesButton = toolpack.component.TSButton(vision.getMessage('vision:caltool:PropertiesButton'),toolpack.component.Icon.SETTINGS_16); this.PropertiesButton.Name = 'PropertiesButton'; this.PropertiesButton.Peer.setToolTipText(vision.getMessage('vision:caltool:EnabledCameraPropertiesToolTip')); % Add labels to panel. devicePanel.add(deviceLabel, 'xy(2,2)'); devicePanel.add(this.DeviceComboBox, 'xy(4,2)'); devicePanel.add(this.PropertiesButton, 'xyw(2,4,3)'); % Add the section to the Panel. add(deviceSection, devicePanel); tab = this.getToolTab(); add(tab,deviceSection); end function createSettingsWidgets(this) settingsSection = toolpack.desktop.ToolSection('Settings',... vision.getMessage('vision:caltool:SettingsSection')); % Create the panel. settingsPanel = toolpack.component.TSPanel('10px,f:p,5px,f:p,5px,f:p,5px,f:p,10px', '1px,f:p,3px,f:p,3px,f:p,1px'); % Create Save location widgets. saveLocationLabel = toolpack.component.TSLabel(vision.getMessage('vision:caltool:SaveLocationEdit')); if (this.hasWritePermissions(pwd, false)) startDir = pwd; else startDir = ''; end this.CurrentSaveLocation = startDir; this.SaveLocationEdit = toolpack.component.TSTextField(startDir, 4); this.SaveLocationEdit.Name = 'SaveLocationEdit'; this.SaveLocationEdit.Peer.setToolTipText(vision.getMessage('vision:caltool:EnabledSaveLocationToolTip')); this.BrowseButton = toolpack.component.TSButton(vision.getMessage('vision:caltool:BrowseButton'), toolpack.component.Icon.OPEN_16); this.BrowseButton.Name = 'BrowseButton'; this.BrowseButton.Orientation = toolpack.component.ButtonOrientation.HORIZONTAL; this.BrowseButton.Peer.setToolTipText(vision.getMessage('vision:caltool:BrowseButtonToolTip')); add(settingsPanel, saveLocationLabel, 'xy(2,2)'); add(settingsPanel, this.SaveLocationEdit, 'xyw(4,2,3)'); add(settingsPanel, this.BrowseButton, 'xy(8,2)'); % Create the label. captureIntervalLabel = toolpack.component.TSLabel(vision.getMessage('vision:caltool:CaptureIntervalEdit')); % Create slider component for capture interval control. defValue = 5; % Set slider tick spacing and create label table. this.CaptureIntervalSlider = toolpack.component.TSSlider(this.MinInterval, this.MaxInterval, defValue); this.CaptureIntervalSlider.MajorTickSpacing = 5; this.CaptureIntervalSlider.MinorTickSpacing = 1; this.CaptureIntervalSlider.Name = 'CaptureIntervalSlider'; this.CaptureIntervalSlider.Peer.setToolTipText(vision.getMessage('vision:caltool:EnabledCaptureIntervalToolTip')); % Create text field to enter slider. this.CaptureIntervalEdit = toolpack.component.TSTextField(num2str(defValue), 5); this.CaptureIntervalEdit.Name = 'CaptureIntervalEdit'; this.CaptureIntervalEdit.Peer.setToolTipText(vision.getMessage('vision:caltool:EnabledCaptureIntervalToolTip')); add(settingsPanel, captureIntervalLabel, 'xy(2,4)'); add(settingsPanel, this.CaptureIntervalEdit, 'xy(4,4)'); add(settingsPanel, this.CaptureIntervalSlider, 'xy(6,4)'); % Create number images to capture label numImagesCaptureLabel = toolpack.component.TSLabel(vision.getMessage('vision:caltool:ImagesToCaptureEdit')); this.NumImagesCaptureEdit = toolpack.component.TSTextField(num2str(20), 4); this.NumImagesCaptureEdit.Name = 'NumImagesCaptureEdit'; this.NumImagesCaptureEdit.Peer.setToolTipText(vision.getMessage('vision:caltool:EnabledNumImagesCaptureToolTip')); % Create slider component for num images to capture control. defValue = 20; % Set slider tick spacing and create label table. this.NumImagesCaptureSlider = toolpack.component.TSSlider(this.MinImages, this.MaxImages, defValue); this.NumImagesCaptureSlider.MajorTickSpacing = 5; this.NumImagesCaptureSlider.MinorTickSpacing = 1; this.NumImagesCaptureSlider.Name = 'NumImagesCapture'; this.NumImagesCaptureSlider.Peer.setToolTipText(vision.getMessage('vision:caltool:EnabledNumImagesCaptureToolTip')); add(settingsPanel, numImagesCaptureLabel, 'xy(2,6)'); add(settingsPanel, this.NumImagesCaptureEdit, 'xy(4,6)'); add(settingsPanel, this.NumImagesCaptureSlider, 'xy(6,6)'); % Add the section to the Panel. add(settingsSection, settingsPanel); tab = this.getToolTab(); add(tab,settingsSection); end function createCaptureWidgets(this) this.CaptureButton = toolpack.component.TSButton(vision.getMessage('vision:caltool:StartCaptureButton'),toolpack.component.Icon.RUN_24); this.CaptureButton.Name = 'CaptureButton'; this.CaptureButton.Orientation = toolpack.component.ButtonOrientation.VERTICAL; if isempty(this.CurrentSaveLocation) this.CaptureButton.Peer.setToolTipText(vision.getMessage('vision:caltool:DisabledStartCaptureButtonToolTip')); else this.CaptureButton.Peer.setToolTipText(vision.getMessage('vision:caltool:StartCaptureButtonToolTip')); end capturePanel = toolpack.component.TSPanel('f:p','f:p'); capturePanel.Name = 'CapturePanel'; add(capturePanel,this.CaptureButton,'xy(1,1)'); captureSection = toolpack.desktop.ToolSection('CaptureSection', ... vision.getMessage('vision:caltool:CaptureSection')); add(captureSection,capturePanel); tab = this.getToolTab(); add(tab, captureSection); end function createCloseWidgets(this) this.CloseButton = toolpack.component.TSButton(vision.getMessage('vision:caltool:CloseImageCaptureButton'),toolpack.component.Icon.CLOSE_24); this.CloseButton.Name = 'CloseButton'; this.CloseButton.Orientation = toolpack.component.ButtonOrientation.VERTICAL; this.CloseButton.Peer.setToolTipText(vision.getMessage('vision:caltool:CloseButtonToolTip')); closePanel = toolpack.component.TSPanel('f:p','f:p'); closePanel.Name = 'ClosePanel'; add(closePanel,this.CloseButton,'xy(1,1)'); closeSection = toolpack.desktop.ToolSection('CloseSection', ... vision.getMessage('vision:caltool:CloseSection')); add(closeSection,closePanel); tab = this.getToolTab(); add(tab,closeSection); end function installListeners(this) % Device Section addlistener(this.DeviceComboBox,'ActionPerformed',@(~,evt)this.updateDeviceSection(evt.Source)); addlistener(this.PropertiesButton,'ActionPerformed',@(~,~) this.cameraPropertiesCallback()); % Settings Section this.CaptureIntervalSliderListener = addlistener(this.CaptureIntervalSlider,'StateChanged',@(hobj,evt)updateCaptureIntervalSlider(this,hobj)); this.CaptureIntervalEditListener = addlistener(this.CaptureIntervalEdit,'TextEdited',@(hobj,evt)updateCaptureIntervalEdit(this,hobj)); this.NumImagesCaptureEditListener = addlistener(this.NumImagesCaptureEdit,'TextEdited',@(hobj,evt)updateNumImagesCaptureEdit(this,hobj)); this.NumImagesCaptureSliderListener = addlistener(this.NumImagesCaptureSlider,'StateChanged',@(hobj,evt)updateNumImagesCaptureSlider(this,hobj)); this.SaveLocationEditListener = addlistener(this.SaveLocationEdit,'TextEdited',@(hobj, evt)this.updateSaveLocationEditCallback(hobj)); % Browse button addlistener(this.BrowseButton,'ActionPerformed',@(es,ed)browseCallback(this)); % Capture button. addlistener(this.CaptureButton,'ActionPerformed',@(es,ed)capture(this)); % Add listener for Closing image capture tab. addlistener(this.CloseButton,'ActionPerformed',@(es,ed)closeTab(this)); end end %% Callback methods methods(Access=private) % Capture button callback function capture(this) if (~this.hasWritePermissions(this.SaveLocationEdit.Text, true)) return; end % Error for image size inconsistencies. parent = getParent(this); currentSession = parent.getSession; if currentSession.hasAnyBoards imInfoBase = imfinfo(currentSession.BoardSet.FullPathNames{1}); [width, height] = getResolution(this); if (imInfoBase.Width ~= width) || ... (imInfoBase.Height ~= height) % issue an error message uiwait(errordlg(vision.getMessage('vision:caltool:imageSizeInconsistent'), ... vision.getMessage('vision:caltool:GenericErrorTitle'), ... 'modal')); return; end end this.CaptureFlag = ~this.CaptureFlag; % Update the icons updateCaptureIcon(this); % Update toolstrip status. updateToolstripStatus(this); if this.CaptureFlag % Mode: Starting a Capture this.TimerObj = internal.IntervalTimer(this.CaptureIntervalSlider.Value); addlistener(this.TimerObj, 'Executing', @(src, event)this.getSnapshot(src, event)); start(this.TimerObj); % Start the status timer obj. this.TimeRemaining = this.CaptureIntervalSlider.Value; this.StatusTimerObj = internal.IntervalTimer(1); addlistener(this.StatusTimerObj, 'Executing', @(src, event)this.statusTimerCallback(src, event)); start(this.StatusTimerObj); % Update status text. this.setStatusText(); else % Mode: Stopping a capture % Stop and delete timer object. this.stopTimers; % No images captured, return. if (this.NumImagesCaptured==0) this.reset(); return; end % Save images to file lastFileID = this.getLastFileID; fullPathFileNames = cell(1,this.NumImagesCaptured); for idx = 1:this.NumImagesCaptured fName = strcat('Image', num2str(lastFileID+idx), '.png'); fullPathFileName = fullfile(this.SaveLocationEdit.Text, fName); % Index into Images array. index = this.StartIndex + idx - 1; imwrite (this.Images(:,:,:,index), fullPathFileName, 'png'); % Update the image strip. this.makeLabel(fName, index); % Create cell of full path file names. fullPathFileNames{idx} = fullPathFileName; % Create the icon. icon = this.createIcon(this.Images(:,:,:,index), this.ImageLabels(index)); this.ImageIcons{index} = icon; % Append images to the strip. this.appendImagesToStrip(false); end % @TODO: Run detection and add to BoardSet parent = getParent(this); currentSession = parent.getSession; prevBoardCount = 0; if currentSession.hasAnyBoards prevBoardCount = currentSession.BoardSet.NumBoards; end parent.addImagesFromCameraToSession(fullPathFileNames); % Get the new board count. currentBoardCount = 0; if currentSession.hasAnyBoards currentBoardCount = currentSession.BoardSet.NumBoards; end numBoardsAdded = currentBoardCount - prevBoardCount; if (numBoardsAdded) this.AnyImagesCaptured = true; this.updatePropertyStates(); end % Remove status text. this.setStatusText(); % Reset Capture settings. this.reset(); end end function setStatusText(this) %% Set status text statusStr{1} = vision.getMessage ('vision:caltool:NumImagesAcquired',... num2str(this.NumImagesCaptured), this.NumImagesCaptureEdit.Text); if (this.TimeRemaining == 1) statusStr{2} = vision.getMessage ('vision:caltool:NextCaptureCountdownSingular',... num2str(this.TimeRemaining)); else statusStr{2} = vision.getMessage ('vision:caltool:NextCaptureCountdownPlural',... num2str(this.TimeRemaining)); end % Combine the two messages. statusStr = strjoin(statusStr, ' '); md = com.mathworks.mlservices.MatlabDesktopServices.getDesktop; f = md.getFrameContainingGroup(this.ToolGroupName); if this.CaptureFlag javaMethodEDT('setStatusText', f, statusStr); else javaMethodEDT('setStatusText', f, ''); end end function cams = enumerateCameras(this) % Initialize Button status flag. this.CurrentButtonState = false; % Find the location of webcam. webcamLoc = which('webcam.m'); expectedLoc = fullfile(matlabroot, 'toolbox', 'matlab', 'webcam'); if strcmpi(expectedLoc, fileparts(webcamLoc)) cams = {vision.getMessage('vision:caltool:NoWebcamsDetected')}; uiwait(errordlg(vision.getMessage('vision:caltool:SupportPkgNotInstalledMsg'), ... vision.getMessage('vision:caltool:GenericErrorTitle'), ... 'modal')); return; end % Get available webcams try cams = webcamlist; if isempty(cams) cams = {vision.getMessage('vision:caltool:NoWebcamsDetected')}; return; end catch excep cams = {vision.getMessage('vision:caltool:NoWebcamsDetected')}; uiwait(errordlg(excep.message, ... vision.getMessage('vision:caltool:GenericErrorTitle'), ... 'modal')); return; end % Cameras available - so enable them. this.CurrentButtonState = true; end function getSnapshot(this, ~, evt) % Acquire an image and store it. imgCount = evt.ExecutionCount; if isempty(this.Images) this.Images(:,:,:,1) = snapshot(this.CameraObject); else this.Images(:,:,:,end+1) = snapshot(this.CameraObject); end if isempty(this.StartIndex) this.StartIndex = size(this.Images, 4); end this.NumImagesCaptured = this.NumImagesCaptured + 1; this.makeLabel; % Updates the require label to ImageLabels. % Create icons this.generateIcons; % Append images to the strip. this.appendImagesToStrip(true); % Update status text. this.setStatusText(); % Check if we have acquired completely. if (imgCount >= this.NumImagesCaptureSlider.Value) % Call capture to STOP acquisition. capture(this); end end function statusTimerCallback(this, ~, ~) % Initiate countdown. this.TimeRemaining = this.TimeRemaining - 1; % Reset time. if (this.TimeRemaining==0) % Update status text. this.setStatusText(); this.TimeRemaining = this.CaptureIntervalSlider.Value; end % Update status text. this.setStatusText(); end function appendImagesToStrip(this, showLatest) % Update the image strip. parent = getParent(this); % Append image icons with existing board icons. currentSession = parent.getSession; if showLatest if currentSession.hasAnyBoards parent.updateImageStrip([currentSession.BoardSet.BoardIcons this.ImageIcons], length(currentSession.BoardSet.BoardIcons)+length(this.ImageIcons)-1); else parent.updateImageStrip(this.ImageIcons, length(this.ImageIcons)-1); end else if currentSession.hasAnyBoards parent.updateImageStrip([currentSession.BoardSet.BoardIcons this.ImageIcons], length(currentSession.BoardSet.BoardIcons)); else parent.updateImageStrip(this.ImageIcons); end end end function fileID = getLastFileID(this) fileID = 0; out = dir(fullfile(this.SaveLocationEdit.Text, 'Image*.png')); if ~isempty(out) [~, fname]= cellfun(@fileparts, {out.name}, 'UniformOutput', false); fNum = cellfun(@(s) (str2double(s(6:end))), fname, 'UniformOutput', false); fileID = max([fNum{:}]); end end function stopTimers(this) % Stop timer object. if ( ~isempty(this.TimerObj) && isvalid(this.TimerObj) ) stop(this.TimerObj); this.TimerObj = []; end % Stop status timer object. if ( ~isempty(this.StatusTimerObj) && isvalid(this.StatusTimerObj) ) stop(this.StatusTimerObj); this.StatusTimerObj = []; end end function closeTab(this) % Reset the images. this.reset(); % Delete the Camera Object. if (~isempty(this.CameraObject) && isvalid(this.CameraObject) ) delete(this.CameraObject); end % Delete timer object. this.stopTimers; % Notify listener of Close operation. notify(this,'CloseTab'); end function reset(this) % Reset the images. this.NumImagesCaptured = 0; this.Images = uint8([]); this.ImageIcons = []; this.ImageLabels = []; this.StartIndex = []; end function browseCallback(this) % Call to select directory path = uigetdir(this.SaveLocationEdit.Text, vision.getMessage('vision:caltool:FolderOpenDialogTitle')); if ~path % No selection was made. return; end if hasWritePermissions(this, path, true) % Update the path in the text field. this.SaveLocationEdit.Text = path; this.CurrentSaveLocation = this.SaveLocationEdit.Text; this.CaptureButton.Enabled = true; this.CaptureButton.Peer.setToolTipText(vision.getMessage('vision:caltool:StartCaptureButtonToolTip')); return; end end function tf = hasWritePermissions(~, path, throwError) tf = false; % Create random folder name to try writing. [~, tempFolderName] = fileparts(tempname); dirExists = exist(path, 'dir'); if (dirExists) writable = mkdir(fullfile(path, tempFolderName)); if writable % Delete the temp dir. rmdir(fullfile(path, tempFolderName)); tf = true; return; end % @TODO: Error here. if throwError uiwait(errordlg(vision.getMessage('vision:caltool:PathWithInvalidPermissionsMsg'), ... vision.getMessage('vision:caltool:PathWithInvalidPermissionsTitle'), ... 'modal')); end return; end % Error. if throwError uiwait(errordlg(vision.getMessage('vision:caltool:InvalidPathMsg'), ... vision.getMessage('vision:caltool:InvalidPathTitle'), ... 'modal')); end end function generateIcons(this) % Loop over images to generate icons. numImages = size(this.Images, 4); for idx = 1:numImages icon = this.createIcon(this.Images(:,:,:,idx), this.ImageLabels(idx)); this.ImageIcons{idx} = icon; end end function icon = createIcon(~, im, label) thumbnailHeight = 72; im = imresize(im, [thumbnailHeight, NaN]); javaImage = im2java2d(im); icon = javax.swing.ImageIcon(javaImage); icon.setDescription(label); end function makeLabel(this, varargin) if (nargin>1) fileName = varargin{1}; loc = varargin{2}; [~, fname, ext] = fileparts(fileName); label = [fname, ext]; this.ImageLabels{loc} = label; else label = 'Not yet saved to disk'; this.ImageLabels{end+1} = label; end end function updateCaptureIntervalEdit(this, obj) % Move slider position to otsu level and update text. val = floor(str2double(obj.Text)); if isnan(val) % TODO: Do we need an unnecessary error message? this.CaptureIntervalEdit.Text = num2str(this.CaptureIntervalSlider.Value); return; end % Valid value - continue if val > this.MaxInterval val = this.MaxInterval; elseif val < this.MinInterval val = this.MinInterval; end this.CaptureIntervalEdit.Text = num2str(val); this.CaptureIntervalSlider.Value = val; end function updateCaptureIntervalSlider(this, ~) % Update text. this.CaptureIntervalEdit.Text = num2str(this.CaptureIntervalSlider.Value); end function updateNumImagesCaptureEdit(this, obj) % Min and Max are 1 and 100. val = floor(str2double(obj.Text)); if isnan(val) % TODO: Do we need an unnecessary error message? this.NumImagesCaptureEdit.Text = num2str(this.NumImagesCaptureSlider.Value); return; end % Valid value - Continue if val < this.MinImages val = this.MinImages; elseif val > this.MaxImages val = this.MaxImages; end this.NumImagesCaptureEdit.Text = num2str(val); this.NumImagesCaptureSlider.Value = val; end function updateNumImagesCaptureSlider(this, ~) % Update text. this.NumImagesCaptureEdit.Text = num2str(this.NumImagesCaptureSlider.Value); end function updateSaveLocationEditCallback(this, evt) if this.hasWritePermissions(evt.Text, true) this.SaveLocationEdit.Text = evt.Text; this.CurrentSaveLocation = this.SaveLocationEdit.Text; this.CaptureButton.Enabled = true; this.CaptureButton.Peer.setToolTipText(vision.getMessage('vision:caltool:StartCaptureButtonToolTip')); else this.SaveLocationEdit.Text = this.CurrentSaveLocation; end end function updateDeviceSection(this, devComboBox, varargin) % If no device exists, do nothing and return. if ismember(devComboBox.SelectedItem, {vision.getMessage('vision:caltool:SPPKGNotInstalled'), vision.getMessage('vision:caltool:NoWebcamsDetected')}) % Empty the properties panel. this.PropertiesPanel = []; return; end % Create device try if (~isempty(this.CameraObject) && isvalid(this.CameraObject) ) delete(this.CameraObject); this.CameraObject = []; this.PropertiesPanel = []; this.closePreview(); end if (nargin==3) useResolution = varargin{1}; if useResolution this.CameraObject = webcam(devComboBox.SelectedIndex, 'Resolution', this.PropertiesPanel.DevicePropObjects.Resolution.ComboControl.SelectedItem); else this.CameraObject = webcam(devComboBox.SelectedIndex); end else this.CameraObject = webcam(devComboBox.SelectedIndex); end this.preview(); % Save the device. this.SavedCamera = devComboBox.SelectedItem; % Create properties panel. this.createPropertiesPanel(); % Disable buttons this.updateButtonStates(true); catch excep % The camera is in use by another application. uiwait(errordlg(excep.message, ... vision.getMessage('vision:caltool:CameraInUseTitle'), ... 'modal')); % Disable buttons this.updateButtonStates(false); end end function updateButtonStates(this, flag) this.PropertiesButton.Enabled = flag; this.CaptureIntervalSlider.Enabled = flag; this.CaptureIntervalEdit.Enabled = flag; this.NumImagesCaptureSlider.Enabled = flag; this.NumImagesCaptureEdit.Enabled = flag; this.BrowseButton.Enabled = flag; this.SaveLocationEdit.Enabled = flag; this.CaptureButton.Enabled = flag; end function updateToolstripStatus(this) this.DeviceComboBox.Enabled = ~this.CaptureFlag; this.CaptureIntervalSlider.Enabled = ~this.CaptureFlag; this.CaptureIntervalEdit.Enabled = ~this.CaptureFlag; this.PropertiesButton.Enabled = ~this.CaptureFlag; this.BrowseButton.Enabled = ~this.CaptureFlag; this.CloseButton.Enabled = ~this.CaptureFlag; this.NumImagesCaptureSlider.Enabled = ~this.CaptureFlag; this.NumImagesCaptureEdit.Enabled = ~this.CaptureFlag; this.SaveLocationEdit.Enabled = ~this.CaptureFlag; end function updateCaptureIcon(this) if this.CaptureFlag % Currently capture started, hence show STOP icon. this.CaptureButton.Icon = toolpack.component.Icon.END_24; this.CaptureButton.Peer.setToolTipText(vision.getMessage('vision:caltool:StopCaptureButtonToolTip')); else % Currently stop initiated, hence show START icon. this.CaptureButton.Icon = toolpack.component.Icon.RUN_24; this.CaptureButton.Peer.setToolTipText(vision.getMessage('vision:caltool:StartCaptureButtonToolTip')); end end function cameraPropertiesCallback(this) this.createPropertiesPanel(); this.PropertiesPanel.popup.Floating = false; this.PropertiesPanel.popup.show(this.PropertiesButton,'SOUTH'); this.updatePropertyStates(); end function createPropertiesPanel(this) tool = this.getParent; if isempty(this.PropertiesPanel) this.PropertiesPanel = vision.internal.calibration.tool.CameraPropertiesPanel(this.CameraObject, tool.ImagePreviewDisplay); else this.PropertiesPanel.updateCameraObject(this.CameraObject, tool.ImagePreviewDisplay); end end function [width, height] = getResolution(this) res = this.CameraObject.Resolution; idx = strfind(res, 'x'); width = str2double(res(1:idx-1)); height = str2double(res(idx+1:end)); end end end