gusucode.com > vision工具箱matlab源码程序 > vision/opticalFlow.m

    %opticalFlow Object for storing optical flow.
%
%   opticalFlow object describes optical flow.
%
%   flow = opticalFlow(Vx, Vy) constructs an opticalFlow object from two
%   equal-sized matrices, Vx and Vy. Vx and Vy are the x and y components
%   of velocity.
%
%   opticalFlow properties:
%      Vx          - x component of velocity
%      Vy          - y component of velocity
%      Orientation - Phase angles of flow in radians of size M-by-N, where 
%                    M-by-N is the size of Vx or Vy
%      Magnitude   - Magnitude of flow of size M-by-N
%
%   opticalFlow methods:
%      plot   - Plots the velocity.
%
%   Class Support
%   -------------
%   Vx and Vy can be double or single.
%
%   Example
%   -------
%   % Construct object
%   flow = opticalFlow(randn(100,100),randn(100,100));
%   % Plot velocity as quiver plot
%   plot(flow, 'ScaleFactor', 5);
%
% See also opticalFlowHS, opticalFlowLK, opticalFlowLKDoG, quiver

% Copyright 2014 The MathWorks, Inc.

classdef opticalFlow
%#codegen
   
    properties (SetAccess='private', GetAccess='public', Dependent = true)
        %Vx x component of velocity
        Vx; 
        %Vy y component of velocity
        Vy;  
        %Orientation Phase angles of flow in radians of size M-by-N, where 
        %            M-by-N is the size of Vx or Vy
        Orientation;
        %Magnitude Magnitude of flow of size M-by-N
        Magnitude;
    end   
    
    properties (Access='private')
        pVx;
        pVy;
    end
    
    methods % Accessors for Dependent properties
        %-------------------------------------------------
        function this = set.Vx(this, in)
            this.pVx = in;            
        end
        %-----------------------------------------------
        function out = get.Vx(this)
            out = this.pVx;
        end        
        %-------------------------------------------------
        function this = set.Vy(this, in)
            this.pVy = in;
        end
        %-----------------------------------------------
        function out = get.Vy(this)
            out = this.pVy;
        end  
        %-----------------------------------------------
        function out = get.Orientation(this)
            out = computeAngle(this.pVx, this.pVy);
        end     
        %-----------------------------------------------
        function out = get.Magnitude(this)
            out = computeMagnitude(this.pVx, this.pVy);
        end       
    end 
    
    %-----------------------------------------------------------------------
    methods (Access='public')
        function this = opticalFlow(varargin)
            %MSERRegions constructor
            if (nargin ~= 0) && (nargin ~= 2)
                % user specified one of Vx, Vy, or only either param name
                % or value => all these are error case
                coder.internal.errorIf((nargin ~= 0) && (nargin ~= 2), ...
                    'vision:OpticalFlow:numArgInvalid');
            elseif (nargin == 0)
                this.pVx = zeros(0,1);
                this.pVy = zeros(0,1);
            elseif nargin == 2
                % first argument must be Vx or Param name of a P-V pair
                checkVelocityComponent(varargin{1}, 'Vx', 1);
                checkVelocityComponent(varargin{2}, 'Vy', 2);
                crossCheckVelocityComponents(varargin{1}, varargin{2});
                this.pVx = varargin{1};
                this.pVy = varargin{2};
            end
        end
        
        %------------------------------------------------------------------
        function varargout = plot(this, varargin)
            % plot Plots the velocity
            %   plot(flow) plots the flow vectors
            %
            %   plot(..., Name, Value) specifies additional name-value pairs
            %   described below: 
            %
            %   'DecimationFactor'  A two element vector, [XDecimFactor YDecimFactor] 
            %                       specifies the decimation factor of velocity vectors
            %                       along x and y directions. Use larger values
            %                       to get less-cluttered quiver plot.
            %
            %                       Default: [1 1]
            %
            %   'ScaleFactor'       Scaling factor for velocity vector display. Use 
            %                       larger values to get longer vectors in display.
            %
            %                       Default: 1
            %
            %   'Parent'            Specify an output axes for displaying the visualization.
            %
            %                       Default: gca      
            
            coder.internal.errorIf(~isSimMode(), 'vision:OpticalFlow:plotNotSupported');
            nargoutchk(0,1);
            [h, inputs] = parsePlotInputs(varargin{:});
            XDecimationFactor = inputs.DecimationFactor(1);
            YDecimationFactor = inputs.DecimationFactor(2);

            borderOffset = 1; % this could be user input

            [R, C] = size(this.Vx);
            RV = borderOffset:YDecimationFactor:(R-borderOffset+1);   
            CV = borderOffset:XDecimationFactor:(C-borderOffset+1);   
            [X, Y] = meshgrid(CV,RV);

            velocityX = this.Vx;
            velocityY = this.Vy;
            
            tmpVx = velocityX(RV,CV);
            tmpVy = velocityY(RV,CV);
            tmpVx = tmpVx.*inputs.ScaleFactor;
            tmpVy = tmpVy.*inputs.ScaleFactor;
 
            quiver(h, X(:), Y(:), tmpVx(:), tmpVy(:), 0); 
            
            if nargout == 1
                varargout{1} = h;
            end            
        end        
    end
end    

%--------------------------------------------------------------------------
% Plot input parser
%--------------------------------------------------------------------------
function [h, inputs] = parsePlotInputs(varargin)

% Parse the PV pairs
parser = inputParser;

parser.addParameter('Parent', [], ...
    @vision.internal.inputValidation.validateAxesHandle)

parser.addParameter('DecimationFactor', [1 1], @checkDecimationFactor);
parser.addParameter('ScaleFactor', 1, @checkScaleFactor);

% Parse input
parser.parse(varargin{:});

% Assign return values
h = parser.Results.Parent;

if isempty(h)
    h = gca;
end

inputs.DecimationFactor = parser.Results.DecimationFactor;
inputs.ScaleFactor  = parser.Results.ScaleFactor;

end

function crossCheckVelocityComponents(Vx, Vy)
    crossCheckSizes(Vx, Vy);
    crossCheckDataTypes(Vx, Vy);
end

function  crossCheckSizes(Vx, Vy)
    coder.internal.errorIf(~isequal(size(Vx), size(Vy)), ...
        'vision:OpticalFlow:VxVySizeMismatch');
end

function  checkVelocityComponent(V, name, id)
   validateattributes(V,{'double','single'}, ...
    {'real','nonsparse','2d'}, mfilename, name, id);
end

function  crossCheckDataTypes(Vx, Vy)
    coder.internal.errorIf(~isequal(class(Vx), class(Vy)), ...
        'vision:OpticalFlow:VxVyClassMismatch');
end

function  checkDecimationFactor(decimFactor)
    validateattributes(decimFactor, {'numeric'}, ...
    {'nonempty', 'integer', 'nonsparse', 'vector', 'numel', 2, '>', 0}, ...
    mfilename, 'DecimationFactor'); %#ok<*EMCA>
end

function  checkScaleFactor(scaleFactor)
    validateattributes(scaleFactor, {'numeric'}, ...
    {'nonempty', 'integer', 'nonsparse', 'scalar', '>=', 1}, ...
    mfilename, 'ScaleFactor');
end
            
function ang = computeAngle(Vx, Vy)
    % ang = angle(Vx + sqrt(-1)*Vy);
    % To avoid 'Domain Error' in codegen, use atan2 directly (instead of
    % angle function)
    ang = atan2(Vy, Vx);
end

function mag = computeMagnitude(Vx, Vy)
    mag = sqrt(Vx.*Vx + Vy.*Vy);
end

function flag = isSimMode()

    flag = isempty(coder.target);
end