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

    %opticalFlowLK Estimate optical flow using Lucas-Kanade algorithm.
%   obj = opticalFlowLK returns an optical flow object, obj, that estimates
%   the direction and speed of object motion from previous video frame to
%   the current one using Lucas-Kanade algorithm with difference filter 
%   [-1 1] for temporal smoothing.
%
%   obj = opticalFlowLK(Name, Value) specifies additional name-value pairs
%   described below:
%
%   'NoiseThreshold' Threshold for noise reduction. It's a positive scalar.
%                    The higher the number, the less small movements impact
%                    the optical flow calculation.
%
%                    Default: 0.0039
%
%   opticalFlowLK properties:
%      NoiseThreshold   - Threshold for noise reduction
%
%   opticalFlowLK 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 = opticalFlowLK('NoiseThreshold', 0.009);
%     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', 10)
%       drawnow
%       hold off 
%     end
%
%   See also opticalFlowHS, 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 opticalFlowLK < handle & vision.internal.EnforceScalarHandle
%#codegen
%#ok<*EMCLS>
%#ok<*EMCA>
%#ok<*MCSUP>
  
  %------------------------------------------------------------------------
  % Public properties which can only be set in the constructor
  %------------------------------------------------------------------------
  properties(SetAccess=public)
    %NoiseThreshold Threshold for noise reduction
    NoiseThreshold = 0.0039;% eigTh
  end
  
  %------------------------------------------------------------------------
  % Hidden properties used by the object
  %------------------------------------------------------------------------
  properties(Hidden, Access=private)
    pInRows = 0;
    pInCols = 0;
    pImageClassID = 0;
    
    pPreviousFrameBuffer;
    pFirstCall;
    
    %% All intermediate buffers
 	pGradCC; 
    pGradRC; 
    pGradRR; 
    pGradCT; 
    pGradRT;
  end
  
  methods

    %----------------------------------------------------------------------
    % Constructor
    %----------------------------------------------------------------------
    function obj = opticalFlowLK(varargin)
        
      % Parse the inputs.
      if nargin>0
          condition = (nargin>0) && (~strcmpi(varargin{1},'NoiseThreshold'));
          coder.internal.errorIf(condition, 'vision:OpticalFlow:paramNoiseTh');

          tmpNoiseThreshold = varargin{2};
          obj.NoiseThreshold = tmpNoiseThreshold;
      end
      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: 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);
      
      noiseThreshold = cast(obj.NoiseThreshold, otherDT);
      
     if isSimMode()
      [outVelReal, outVelImag] = visionOpticalFlowLK( ...
         			tmpImageA, ImageB, ...
					obj.pGradCC, obj.pGradRC, obj.pGradRR, obj.pGradCT, obj.pGradRT, ...
					noiseThreshold ...
         );
     else
      [outVelReal, outVelImag] = vision.internal.buildable.opticalFlowLKBuildable.opticalFlowLK_compute( ...
         			tmpImageA, ImageB, ...
					obj.pGradCC, obj.pGradRC, obj.pGradRR, obj.pGradCT, obj.pGradRT, ...
					noiseThreshold ... 
         );
     end
     
     outFlow = opticalFlow(outVelReal, outVelImag);
     % Update delay buffer  
     obj.pPreviousFrameBuffer = tmpImageA;
    end
    
    %------------------------------------------------------------------
    function set.NoiseThreshold(this, noiseThreshold)
        checkNoiseThreshold(noiseThreshold);
        this.NoiseThreshold = double(noiseThreshold);
    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

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 checkNoiseThreshold(NoiseThreshold)

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

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