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

    %opticalFlowHS Estimate optical flow using Horn-Schunck algorithm.
%   obj = opticalFlowHS returns an optical flow object, obj, that estimates
%   the direction and speed of object motion from previous video frame to
%   the current one using Horn-Schunck algorithm.
%
%   obj = opticalFlowHS(Name, Value) specifies additional name-value pairs
%   described below:
%
%   'Smoothness'    Expected smoothness of optical flow. It's a positive
%                   scalar. Use higher value if the relative motion between
%                   two consecutive frames are higher. Typical value is
%                   around 1.
%
%                   Default: 1
%
%   'MaxIteration'  Maximum number of iterations to perform in the optical
%                   flow iterative solution. It's a positive integer-valued
%                   scalar. Use higher value to estimate flow of objects
%                   with lower velocity.
%
%                   Default: 10
%
%   'VelocityDifference'   Minimum absolute velocity difference to stop  
%                          iterative computation. It's a non-negative scalar.
%                          The value depends on input data type. Use
%                          smaller value to estimate flow of objects with
%                          lower velocity. 
%
%                          Default: 0
%
%   Notes
%   -----
%   Iterative computation stops when 'MaxIteration' is reached or
%   'VelocityDifference' is attained.
%   * To use only 'MaxIteration', set 'VelocityDifference' to 0.
%   * To use only 'VelocityDifference', set 'MaxIteration' to Inf.
%
%   opticalFlowHS properties:
%      Smoothness         - Smoothness of optical flow
%      MaxIteration       - Maximum number of iterations for iterative solution
%      VelocityDifference - Minimum absolute velocity difference for iterative solution
%
%   opticalFlowHS methods:
%      estimateFlow - Estimates the optical flow
%      reset        - Resets the internal state of the object
%
%   Example - Compute and display optical flow  
%   ------------------------------------------
%     vidReader = VideoReader('visiontraffic.avi', 'CurrentTime', 11);
%     opticFlow = opticalFlowHS;
%     while hasFrame(vidReader)
%       frameRGB = readFrame(vidReader);
%       frameGray = rgb2gray(frameRGB);
%       % Compute optical flow
%       flow = estimateFlow(opticFlow, frameGray); 
%       % Display video frame with flow vectors
%       imshow(frameRGB) 
%       hold on
%       plot(flow, 'DecimationFactor', [5 5], 'ScaleFactor', 60)
%       drawnow
%       hold off 
%     end
%
%   See also opticalFlowLK, opticalFlowLKDoG, opticalFlowFarneback, 
%            opticalFlow, opticalFlow>plot.

%   Copyright 2014 MathWorks, Inc.
%
% References: 
%    Barron, J.L., D.J. Fleet, S.S. Beauchemin, and T.A.
%    Burkitt. "Performance of optical flow techniques". CVPR, 1992.

classdef opticalFlowHS < handle & vision.internal.EnforceScalarHandle
%#codegen
%#ok<*EMCLS>
%#ok<*EMCA>
%#ok<*MCSUP>
  
  %------------------------------------------------------------------------
  % Public properties which can only be set in the constructor
  %------------------------------------------------------------------------
  properties(SetAccess=public)
    %Smoothness Smoothness of optical flow
    Smoothness = 1;
    %MaxIteration Maximum number of iterations for iterative solution
    MaxIteration = int32(10);
    %VelocityDifference Minimum absolute velocity difference for iterative solution
    VelocityDifference = 0;    
  end
  
  %------------------------------------------------------------------------
  % Hidden properties used by the object
  %------------------------------------------------------------------------
  properties(Hidden, Access=private)
    pInRows = 0;
    pInCols = 0;
    pImageClassID = 0;
    
    pPreviousFrameBuffer;
    pFirstCall;
    
    %% All intermediate buffers
    pBuffCprev; 
    pBuffCnext; 
    pBuffRprev; 
    pBuffRnext; 
	pGradCC; 
    pGradRC; 
    pGradRR; 
    pGradCT; 
    pGradRT;
    pAlpha;
    pVelBufCcurr; 
    pVelBufCprev; 
    pVelBufRcurr; 
    pVelBufRprev;
  end
  
  methods

    %----------------------------------------------------------------------
    % Constructor
    %----------------------------------------------------------------------
    function obj = opticalFlowHS(varargin)
        
      % Parse the inputs.
      if isSimMode()
       [tmpSmoothness, tmpMaxIteration, tmpVelocityDifference] ...
        = parseInputsSimulation(obj, varargin{:});
      else % Code generation
        [tmpSmoothness, tmpMaxIteration, tmpVelocityDifference] ...
        = parseInputsCodegen(obj, varargin{:});
      end
      
      obj.Smoothness = tmpSmoothness;
      obj.MaxIteration = tmpMaxIteration;
      obj.VelocityDifference = tmpVelocityDifference;
      obj.pFirstCall = true;
    end
    
    %----------------------------------------------------------------------
    % Predict method
    %----------------------------------------------------------------------
    function outFlow = estimateFlow(obj, ImageA) %, varargin)
        % estimateFlow Estimates the optical flow
        %   flow = estimateFlow(obj, I) estimates the optical flow between 
        %   the current frame I and the previous frame. 
        %    
        %   Notes
        %   -----
        %   - output flow is an object of class <a href="matlab:help('opticalFlow')">opticalFlow</a> that stores
        %     velocity matrices.
        %   - Class of input, I, can be double, single, uint8, int16, or logical.
        %   - For the very first frame, the previous frame is set to black.
        
     checkImage(ImageA);
     if (~isSimMode())
         % compile time error if ImageA is not fixed sized
         eml_invariant(eml_is_const(size(ImageA)), ...
                      eml_message('vision:OpticalFlow:imageVarSize'));
     end
     
     if (obj.pFirstCall) 
         obj.pInRows = coder.const(size(ImageA,1));
         obj.pInCols = coder.const(size(ImageA,2));
         obj.pImageClassID = coder.const(getClassID(ImageA));
     else         
         inRows_ = size(ImageA,1);
         inCols_ = size(ImageA,2);
         condition = (obj.pInRows ~= inRows_) || (obj.pInCols ~= inCols_);
         coder.internal.errorIf(condition, 'vision:OpticalFlow:inputSizeChange');
         
         condition = obj.pImageClassID ~= getClassID(ImageA);
         coder.internal.errorIf(condition, 'vision:OpticalFlow:inputDataTypeChange');          
     end

     if isa(ImageA, 'double') 
         otherDT = coder.const('double');
         tmpImageA = ImageA;
     else
         otherDT = coder.const('single');
         if isa(ImageA, 'uint8') 
             tmpImageA = ImageA;
         else
             tmpImageA = im2single(ImageA);
         end
     end    
     
     if((obj.pInRows==0) || (obj.pInCols==0))
         velComponent = zeros(size(tmpImageA), otherDT);
         outFlow = opticalFlow(velComponent, velComponent);
         return;
     end
     
     if (obj.pFirstCall) 
        obj.pPreviousFrameBuffer = zeros(size(tmpImageA), 'like', tmpImageA);
        obj.pFirstCall = false;
     else
        coder.assertDefined(obj.pPreviousFrameBuffer);        
     end
     ImageB = obj.pPreviousFrameBuffer;          
      
      % Temporary memory: ALPHA_IDX
      obj.pAlpha = zeros(size(ImageA), otherDT);
      
      % Temporary memory: MEM{C0,C1,R0,R1}_IDX
      obj.pBuffCprev = zeros(obj.pInRows, 1, otherDT);
      obj.pBuffCnext = zeros(obj.pInRows, 1, otherDT);
      obj.pBuffRprev = zeros(obj.pInCols, 1, otherDT);
      obj.pBuffRnext = zeros(obj.pInCols, 1, otherDT);
      
      % Temporary memory: GRAD{CC,RC,RR,CT,RT}_IDX
      obj.pGradCC = zeros(size(ImageA), otherDT);
      obj.pGradRC = zeros(size(ImageA), otherDT);
      obj.pGradRR = zeros(size(ImageA), otherDT);
      obj.pGradCT = zeros(size(ImageA), otherDT);
      obj.pGradRT = zeros(size(ImageA), otherDT);

      % Temporary memory: VELBUFF{C0,C1,R0,R1}_IDX
      obj.pVelBufCcurr = zeros(obj.pInRows, 1, otherDT);
      obj.pVelBufCprev = zeros(obj.pInRows, 1, otherDT);
      obj.pVelBufRcurr = zeros(obj.pInRows, 1, otherDT);
      obj.pVelBufRprev = zeros(obj.pInRows, 1, otherDT);
      
      useMaxIter = (obj.MaxIteration < intmax('int32'));
      useMaxAllowableAbsDiffVel = (obj.VelocityDifference > 0);
      smoothness = cast(obj.Smoothness, otherDT);
      velocityDifference = cast(obj.VelocityDifference, otherDT);

     if isSimMode()
      [outVelReal, outVelImag] = visionOpticalFlowHS( ...
         			tmpImageA, ImageB, ...
					obj.pBuffCprev, obj.pBuffCnext, obj.pBuffRprev, obj.pBuffRnext, ...
					obj.pGradCC, obj.pGradRC, obj.pGradRR, obj.pGradCT, obj.pGradRT, ...
					obj.pAlpha, ...
					obj.pVelBufCcurr, obj.pVelBufCprev, obj.pVelBufRcurr, obj.pVelBufRprev, ...
					smoothness, ... % Smoothness is Lambda
					useMaxIter, useMaxAllowableAbsDiffVel, ... 
					obj.MaxIteration, velocityDifference ...
         );
     else
      [outVelReal, outVelImag] = vision.internal.buildable.opticalFlowHSBuildable.opticalFlowHS_compute( ...
         			tmpImageA, ImageB, ...
					obj.pBuffCprev, obj.pBuffCnext, obj.pBuffRprev, obj.pBuffRnext, ...
					obj.pGradCC, obj.pGradRC, obj.pGradRR, obj.pGradCT, obj.pGradRT, ...
					obj.pAlpha, ...
					obj.pVelBufCcurr, obj.pVelBufCprev, obj.pVelBufRcurr, obj.pVelBufRprev, ...
					smoothness, ... % Smoothness is Lambda
					useMaxIter, useMaxAllowableAbsDiffVel, ... 
					obj.MaxIteration, velocityDifference ... 
         );
     end
     
     outFlow = opticalFlow(outVelReal, outVelImag);
     % Update delay buffer  
     obj.pPreviousFrameBuffer = tmpImageA;
    end
    
    %------------------------------------------------------------------
    function set.Smoothness(this, smoothness)
        checkSmoothness(smoothness);
        this.Smoothness = double(smoothness);
    end
        
    %------------------------------------------------------------------
    function set.MaxIteration(this, maxIteration)
        checkMaxIteration(maxIteration);
        this.MaxIteration = int32(maxIteration);
    end
    
    %------------------------------------------------------------------
    function set.VelocityDifference(this, velocityDifference)
        checkVelocityDifference(velocityDifference);
        this.VelocityDifference = double(velocityDifference);
    end    
    
    %----------------------------------------------------------------------
    % Correct method
    %----------------------------------------------------------------------
    function reset(obj)
        % reset Reset the internal state of the object
        %
        %   reset(flow) resets the internal state of the object. It sets 
        %   the previous frame to black.
        
        obj.pFirstCall = true;
    end    
      
  end
  
  methods(Access=private)
    %----------------------------------------------------------------------
    % Parse inputs for simulation
    %----------------------------------------------------------------------
    function [tmpSmoothness, tmpMaxIteration, tmpVelocityDifference] ...
        = parseInputsSimulation(obj, varargin)
      
      % Instantiate an input parser
      parser = inputParser;
      parser.FunctionName = mfilename;
      
      % Specify the optional parameters
      parser.addParameter('Smoothness',          obj.Smoothness);
      parser.addParameter('MaxIteration',       obj.MaxIteration);
      parser.addParameter('VelocityDifference', obj.VelocityDifference);
      
      % Parse parameters
      parse(parser, varargin{:});
      r = parser.Results;
      
      tmpSmoothness         = r.Smoothness;
      tmpMaxIteration       = r.MaxIteration;
      tmpVelocityDifference = r.VelocityDifference;     

    end
    
    %----------------------------------------------------------------------
    % Parse inputs for code generation
    %----------------------------------------------------------------------
    function [tmpSmoothness, tmpMaxIteration, tmpVelocityDifference] ...
        = parseInputsCodegen(obj, varargin)

      defaultsNoVal = struct( ...
        'Smoothness',            uint32(0), ...
        'MaxIteration',     uint32(0), ...
        'VelocityDifference', uint32(0));
      
      properties = struct( ...
        'CaseSensitivity', false, ...
        'StructExpand',    true, ...
        'PartialMatching', false);
      
     optarg = eml_parse_parameter_inputs(defaultsNoVal, properties, varargin{:});
    
      tmpSmoothness = eml_get_parameter_value(optarg.Smoothness, ...
        obj.Smoothness, varargin{:});
      tmpMaxIteration = eml_get_parameter_value(optarg.MaxIteration, ...
        obj.MaxIteration, varargin{:});
      tmpVelocityDifference = eml_get_parameter_value(optarg.VelocityDifference, ...
        obj.VelocityDifference, varargin{:});    

    end
  end
end
               
%========================================================================== 
function flag = isSimMode()

flag = isempty(coder.target);
end

%==========================================================================
function checkImage(I)
% Validate input image

validateattributes(I,{'uint8', 'int16', 'double', 'single', 'logical'}, ...
    {'real','nonsparse', '2d'}, mfilename, 'ImageA', 1)

end

%==========================================================================
function checkSmoothness(Smoothness)

validateattributes(Smoothness, {'numeric'}, {'nonempty', 'nonnan', ...
    'finite', 'nonsparse', 'real', 'scalar', '>', 0}, ...
    mfilename, 'Smoothness');

end

%==========================================================================
function checkMaxIteration(MaxIteration)

% allow inf
is_inf = isnumeric(MaxIteration) && ...
        (numel(MaxIteration)==1) && isinf(MaxIteration);
if ~is_inf
 validateattributes(MaxIteration, {'numeric'}, ...
    {'nonempty', 'real', 'integer', 'nonnan', 'nonsparse', 'scalar', '>=', 1}, ...
    mfilename, 'MaxIteration');
end

end

%==========================================================================
function checkVelocityDifference(VelocityDifference)

validateattributes(VelocityDifference, {'numeric'}, {'nonempty', 'nonnan', ...
    'finite', 'nonsparse', 'real', 'scalar', '>=', 0}, ...
    mfilename, 'VelocityDifference');

end

%==========================================================================
function id = getClassID(img)
    id = 0;
    if isa(img,'double')
        id = 0;
    elseif isa(img,'single')
        id = 1;
    elseif isa(img,'uint8')
        id = 2;
    elseif isa(img,'int16')
        id = 3;
    elseif isa(img,'logical')
        id = 4;
    end
end