gusucode.com > vision工具箱matlab源码程序 > vision/+vision/+internal/FeaturePoints.m
classdef FeaturePoints < vision.internal.FeaturePointsImpl properties(Hidden, Access = protected) % Amount to scale unit circle used to represent the smallest scale % of the detected features. PlotScaleFactor = 1; end methods (Access='public') function this = FeaturePoints(varargin) this = this@vision.internal.FeaturePointsImpl(varargin{:}); end %------------------------------------------------------------------ function varargout = size(this, varargin) %SIZE Size of FeaturePoints points. % % SZ = size(V) returns the vector [length(V), 1]. % % SZ = size(V, 1) returns the length of V. % % SZ = size(V, N), for N >= 2, returns 1. % % [M, N] = size(V) returns length(V) for M and 1 for N. % try % Use the builtin function to validate the inputs and % outputs. switch nargout case 0 % size(obj) : ans = [this.Count 1] % size(obj, 1) : ans = this.Count % size(obj, 2) : ans = 1 % size(obj, d > 2): ans = 1 [varargout{1:nargout}] = ... builtin('size', this, varargin{:}); if isempty(varargin) % size(obj) varargout{1}(1) = this.Count; elseif numel(varargin) == 1 && varargin{1} ~= 1 % size(obj, 2), size(obj,n) n~=1 = 1 varargout{1} = 1; else % size(obj, 1) varargout{1} = this.Count; end case 1 % D = size(obj) : D = [this.Count, 1] % n = size(obj, 1) : n = this.Count % m = size(obj, 2) : m = 1 % p = size(obj, d > 2): p = 1 n = builtin('size', this, varargin{:}); if isempty(varargin) % D = size(obj); varargout{1} = [this.Count, 1]; elseif numel(varargin) == 1 && varargin{1} ~= 1 % m = size(obj, 2); % p = size(obj, d > 3); varargout{1} = n; else % n = size(obj, 1); varargout{1} = this.Count; end case 2 % [n, m] = size(obj); % [n, m] = size(obj, d) --> issues error [n, ~] = builtin('size', this, varargin{:}); varargout{1} = this.Count; varargout{2} = n; otherwise % [n, m, p, ...] = size(obj) % [n, m, p, ...] = size(obj, d) ---> issues error % p, ... are always 1 [n, ~, varargout{3:nargout}] = ... builtin('size', this, varargin{:}); varargout{1} = this.Count; varargout{2} = n; end catch e % throwAsCaller(e) in order to prevent the line: % Error using FeaturePoints/size. Issue only % the error message. throwAsCaller(e); end end %------------------------------------------------------------------- function varargout = plot(this, supportsScaleAndOrientation, varargin) %plot Plot feature points % % featurePoints.plot plots feature points in the current axis. % % featurePoints.plot(AXES_HANDLE,...) plots using axes with % the handle AXES_HANDLE instead of the current axes (gca). % nargoutchk(0,1); if nargin == 1 supportsScaleAndOrientation = false; end [axes, inputs] = parsePlotInputs(supportsScaleAndOrientation, ... varargin{:}); ax = newplot(axes); % mark centers with a '+' plot(ax, this.pLocation(:,1), this.pLocation(:,2),'g+'); if inputs.showScale || inputs.showOrientation phi = linspace(0,2*pi); x = cos(phi); % will cause horizontal line +90 for vertical y = sin(phi); if inputs.showOrientation % Plot orientation % the two zeros result in a horizontal line which % will be rotated at a later stage unitCircle = [x 0; y 0]; else unitCircle = [x; y]; end wasHeld = ishold; circlesX = []; circlesY = []; for k = 1:this.Count scale = this.PlotScaleFactor*this.Scale(k); pt = this.Location(k,:)'; % negate the orientation so that it's adjusted for % plotting in the HG's "image" type which assumes that Y % axis is pointing downward orient = -this.Orientation(k); rotationMat = [cos(orient) -sin(orient);... sin(orient) cos(orient)]; featureCircle = scale*rotationMat*unitCircle + ... pt*ones(1,size(unitCircle,2)); % insert the NaNs to separate the individual circles circlesX = [circlesX, featureCircle(1,:), NaN]; %#ok<AGROW> circlesY = [circlesY, featureCircle(2,:), NaN]; %#ok<AGROW> end % turn the hold state on, otherwise the next plot command % will overwrite the previous plot result if k==1 && ~wasHeld hold('on'); end plot(ax, circlesX, circlesY,'g-'); if ~wasHeld hold('off'); % restore original states of hold end end if nargout == 1 varargout{1} = ax; end drawnow(); end %------------------------------------------------------------------- function varargout = subsref(this,s) try switch s(1).type case '()' nargoutchk(0,1); this = subsref_data(this, s(1)); % invocation of plot or disp would result in setting % isDotMethod if numel(s) >= 2 isDotMethod = any(strcmp(s(2).subs, {'plot','disp'})); else isDotMethod = false; end % protect against indexing that would affect integrity % of the object if (~isDotMethod) if ~( size(this.pLocation,2) == 2 && ... size(this.pMetric,2) == 1 && ... ismatrix(this.pMetric) && ... numel(s) <= 2 ) error(message('vision:FeaturePoints:invalidIndexingOperation')); end end if numel(s) <= 1 varargout{1} = this; else if isDotMethod && nargout == 0 % avoid setting "ans" with the following syntax: % pts(1).plot builtin('subsref',this,s(2:end)); else varargout{1} = builtin('subsref',this,s(2:end)); end end case '{}' % use of {} indexing is not supported by FeaturePoints; % let the builtin function error out as appropriate builtin('subsref',this,s); case '.' % don't set "ans" for disp and plot if strcmp(s(1).subs, 'disp') || ... (strcmp(s(1).subs, 'plot') && nargout == 0) builtin('subsref',this,s); else if nargout == 0 varargout{1} = builtin('subsref',this,s); else varargout{1:nargout} = builtin('subsref',this,s); end end end catch e throwAsCaller(e); end end %------------------------------------------------------------------- function out = subsasgn(this,s,in) try switch s(1).type case '()' if numel(s) == 2 % Location is Mx2 and must be handled specially % to make assignment like p(1).Location = [2 3] % work. The code below transforms the (1) index % to (1,:). if strcmp(s(2).subs,'Location') && ... numel( s(1).subs ) == 1 s(1).subs{2} = ':'; end this.(s(2).subs) = subsasgn(this.(s(2).subs), s(1), in); else % Error out if the right hand side of the assignment % is not [] or non-empty FeaturePoints if ~( (isa(in,'vision.internal.FeaturePoints') && ~isempty(in)) || ... (isa(in,'double') && isempty(in)) ) error(message('vision:FeaturePoints:badAssignmentInput',... class(this))); end this = subsasgn_data(this, s, in); end out = this; case {'{}', '.'} out = builtin('subsasgn',this,s,in); end catch e throwAsCaller(e); end end %------------------------------------------------------------------- % All of the methods below have to be managed because they can % create non-scalar arrays of objects and FeaturePoints is strictly % a scalar object. %------------------------------------------------------------------- function out = cat(dim,varargin) try validateattributes(dim, {'numeric'}, {'nonempty','finite',... 'integer'},mfilename,'Dimension'); if dim ~= 2 error(message('vision:FeaturePoints:badCatDim')); end out = vertcat(varargin{:}); catch e throwAsCaller(e) end end % function out = horzcat(varargin) %#ok<STOUT> try error(message('vision:FeaturePoints:noHorzcatAllowed',... class(varargin{1}))); catch e throwAsCaller(e); end end % function out = vertcat(varargin) try if ~all(cellfun(@(x)isa(x,class(varargin{1})),varargin)) error(message('vision:FeaturePoints:badCatTypes',class(varargin{1}))); end out = vertcatObj(varargin{:}); catch e throwAsCaller(e); end end % function out = repmat(varargin) %#ok<STOUT> try error(message('vision:FeaturePoints:noRepmatAllowed',... class(varargin{1}))); catch e throwAsCaller(e); end end end methods (Hidden) function sz = numArgumentsFromSubscript(~, ~, callingContext) switch callingContext.char case 'Statement' % this(1:n).prop, this.plot sz = 0; case {'Assignment', ... % [this(1:n).prop] = val 'Expression'} % sin(this(1:n).prop) sz = 1; end end end methods (Access='protected') %------------------------------------------------------------------ % Copy data for subsref. This method is used in subsref %------------------------------------------------------------------ function this = subsref_data(this, option) % Location is an Mx2 matrix while Metric is an Mx1 matrix. When % the indices for sub-referencing is a 1-D array, we explicitly % specify the size for the second dimension. opt1 = option; opt2 = option; if length(option.subs) == 1 opt1.subs{2} = 1; opt2.subs{2} = 1:2; end this.pMetric = subsref(this.pMetric,opt1); this.pLocation = subsref(this.pLocation,opt2); end %------------------------------------------------------------------ % Copy data for subsasgn. This method is used in subsasgn %------------------------------------------------------------------ function this = subsasgn_data(this, option, in) locS = option; % modify index to access Mx2 location matrix locS.subs{2} = ':'; if isempty(in) this.pLocation = subsasgn(this.pLocation, locS, in); this.pMetric = subsasgn(this.pMetric, option, in); else this.pLocation = ... subsasgn(this.pLocation, locS, in.pLocation); this.pMetric = ... subsasgn(this.pMetric, option, in.pMetric); end end %------------------------------------------------------------------ % Concatenate data for vertcat. This method is used in vertcat. %------------------------------------------------------------------ function obj = vertcatObj(varargin) obj = varargin{1}; for i=2:nargin obj.pLocation = [obj.pLocation; varargin{i}.pLocation]; obj.pMetric = [obj.pMetric ; varargin{i}.pMetric]; end end end end %-------------------------------------------------------------------------- % Plot input parser %-------------------------------------------------------------------------- function [h, inputs] = parsePlotInputs(supportsScaleAndOrientation, varargin) % Parse the PV pairs parser = inputParser; parser.addOptional('AXIS_HANDLE', [], ... @vision.internal.inputValidation.validateAxesHandle) if supportsScaleAndOrientation parser.addParameter('showScale', true, @checkFlag); parser.addParameter('showOrientation', false, @checkFlag); end % Parse input parser.parse(varargin{:}); % Assign return values h = parser.Results.AXIS_HANDLE; if supportsScaleAndOrientation inputs.showScale = logical(parser.Results.showScale); inputs.showOrientation = logical(parser.Results.showOrientation); else inputs.showScale = false; inputs.showOrientation = false; end end %-------------------------------------------------------------------------- function tf = checkFlag(in) validateattributes(in, {'logical','numeric'},... {'nonnan', 'scalar', 'real','nonsparse'},... mfilename); tf = true; end % In order for method help to work properly for subclasses, this classdef % file cannot have a comment block at the top, so the following remark and % copyright/version information are provided here at the end. Please do % not move them. %FeaturePoints Object for storing feature points % % FeaturePoints object describes feature points. % % Copyright 2013 The MathWorks, Inc.