gusucode.com > vision工具箱matlab源码程序 > vision/+vision/+internal/MSERRegions_cg.m

    %MSERRegions_cg Object used during codegen instead of MSERRegions
%
%   MSERRegions_cg replaces MSERRegions during codegen.

%   Outputs and inputs are different for MSERRegions and MSERRegions_cg
%
%   REGIONS = MSERRegions(PIXELLIST) (simulation path)
%   --------------------------------
%   PIXELLIST is an M-by-1 cell array representing M regions. Each region
%   contains L-by-2 array of [x y] coordinates. L is not same for each
%   region.
%   REGIONS is an object with following public properties
%           Count: M scalar double (M >= 0)
%        Location: [Mx2 single]
%            Axes: [Mx2 single]
%     Orientation: [Mx1 single]
%       PixelList: {Mx1 cell}; each cell [Li-by-2 int32] i=1,2,...,M
%                  PixelList = {L1 x 2, L2 x 2, L3 x 2, ....LM x 2}'
%
%   REGIONS = MSERRegions(PIXELLIST, LENGTHS) (uses MSERRegions_cg in codegen)
%   -----------------------------------------
%   PIXELLIST is an M*N-by-2 array representing M regions. Each region
%   contains P-by-2 array of [x y] coordinates. P is not same for each
%   region. Here N = P1+P2+....+PM, Pi is the number of pixels in i-th
%   region
%   REGIONS is an object with following public properties
%           Count: M scalar double (M >= 0)
%        Location: [Mx2 single]
%            Axes: [Mx2 single]
%     Orientation: [Mx1 single]
%       PixelList: [M*LL-by-2 int32]; each "region" [Li-by-2 int32] i=1,2,...,M
%                                     And LL = L1+L2+...+LM
%                  PixelList = [L1 x 2; L2 x 2; L3 x 2; ....LM x 2]
%         Lengths: [Mx1 int32]-each value represents number of pixels in each region
%                  Lengths = [L1 L2 L3 ... LM]'

% Copyright 2012 The MathWorks, Inc.

%#codegen
%#ok<*EMCA>

classdef MSERRegions_cg
    
    properties (SetAccess='private', GetAccess='public')
        %Count Number of stored regions
        Count = 0;
        %Location Array of [x y] center coordinates of ellipses
        Location    = ones(0,2,'single');
    end
    
    properties (SetAccess='private', GetAccess='public', Hidden=true)
        %Centroid Array of [x y] center coordinates of ellipses
        Centroid    = ones(0,2,'single');
    end
    
    properties (SetAccess='private', GetAccess='public')
        %Axes Array of [majorAxis minorAxis] of ellipses
        Axes        = ones(0,2,'single');
        %Orientation Orientation of the ellipses
        Orientation = ones(0,1,'single');
    end
    
    properties (Access='public')
%   PixelList: [M*LL-by-2 int32]; each "region" [Li-by-2 int32] i=1,2,...,M
%                                 And LL = L1+L2+...+LM
%              PixelList = [L1 x 2; L2 x 2; L3 x 2; ....LM x 2]
%     Lengths: [Mx1 int32]-each value represents number of pixels in each region
%              Lengths = [L1 L2 L3 ... LM]'

        PixelList = ones(0,2,'int32');
        Lengths = ones(0,1,'int32');;
    end
    
%     % Internal properties that are accessible only indirectly through
%     % dependent properties
%     properties (Access='private')
%         pPixelList     = zeros(0,2,'int32');
%         pLengths       = zeros(0,1,'int32');
%     end
    
    methods % Accessors for Dependent properties

    end
   
    %-----------------------------------------------------------------------
    methods (Access='public')
        function this = MSERRegions_cg(varargin)
            %MSERRegions_cg constructor
            if nargin >= 1
                if isstruct(varargin{1})
                    inputs = varargin{1};
                    
                    checkPixelList(inputs.PixelList);
                    checkLengths(inputs.Lengths);
                    crossCheckPixelListAndLengths(inputs.PixelList, inputs.Lengths);
                    
                    this.Lengths     = inputs.Lengths;
                    this.PixelList   = inputs.PixelList;                    
                    this.Count       = inputs.Count;
                    this.Centroid    = inputs.Centroid;
                    this.Location    = inputs.Location;
                    this.Axes        = inputs.Axes;
                    this.Orientation = inputs.Orientation;
                else
                    inputs = parseInputs(varargin{:});
                    
                    % Value classes with set.prop method are not supported for
                    % code generation; so set/get methods are removed
                    this.Lengths   = inputs.Lengths;
                    this.PixelList = inputs.PixelList;
                    
                    % pixelListLen is the number of regions
                    pixelListLen     = length(this.Lengths);%size(this.pPixelList,1);
                    
                    this.Count = size(this.Lengths,1);
                    this.Centroid    = single(zeros(pixelListLen,2));
                    this.Location    = this.Centroid;
                    this.Axes        = single(zeros(pixelListLen,2));
                    this.Orientation = single(zeros(pixelListLen,1));
                    
                    startIdx = int32(1);
                    for idx = 1:pixelListLen
                        len = int32(this.Lengths(idx));
                        endIdx = startIdx + len - int32(1);
                        thisRegion = this.PixelList(startIdx:endIdx,:);
                        ellipseStruct           = computeEllipseProps(thisRegion);
                        this.Centroid(idx,:)    = single(ellipseStruct.Centroid);
                        this.Axes(idx,:)        = single(ellipseStruct.Axes);
                        this.Orientation(idx,1) = single(ellipseStruct.Orientation);
                        startIdx = startIdx + len;
                    end
                    this.Location    = this.Centroid;
                end
            end
        end
    end
    methods(Hidden)
        %-------------------------------------------------------------------
        % Returns feature points at specified indices
        %-------------------------------------------------------------------
        function obj = getIndexedObj(this, idx)
            
            validateattributes(idx, {'numeric'}, {'vector', 'integer'}, ...
                'MSERRegions');
                        
            % unpack MSER region data and copy into OBJ. This avoids
            % recomputing the ellipse data for an index operation.
            
            % index to the start of each region in PixelList
            cs = cumsum(this.Lengths);            
            thisStartIdx = [0; cs(:)] + 1; 
            
            len1 = this.Lengths(idx);
            r.Lengths   = this.Lengths(idx);
            r.PixelList = coder.nullcopy(zeros(sum(len1),2,'int32'));                
            
            cs2 = cumsum(len1);
            objStartIdx = [0; cs2(:)] + 1; 
            
            % copy pixel data for indexed region
            for k = 1:numel(idx)
                i   = thisStartIdx(idx(k));
                len = this.Lengths(idx(k));
                j   = objStartIdx(k);
                r.PixelList(j:j+len-1,:) = this.PixelList(i:i+len-1,:);                
            end
            
            r.Count       = size(idx,1);            
            r.Centroid    = this.Centroid(idx,:);
            r.Location    = this.Location(idx,:);
            r.Axes        = this.Axes(idx,:);
            r.Orientation = this.Orientation(idx);
            
            obj = vision.internal.MSERRegions_cg(r);
        end
                
    end  
end

%--------------------------------------------------------------------------
% Main parser for the class
%--------------------------------------------------------------------------
function inputs = parseInputs(varargin)

if nargin<2
    % output object is empty
    inputs.PixelList = zeros(0,2,'int32');
    inputs.Lengths   = zeros(0,1,'int32');
else
    inputs.PixelList = varargin{1};
    inputs.Lengths = varargin{2};
    checkPixelList(inputs.PixelList);
    checkLengths(inputs.Lengths);
    crossCheckPixelListAndLengths(inputs.PixelList, inputs.Lengths);
end

end

%--------------------------------------------------------------------------
function tf = checkPixelList(in)

validateattributes(in,{'int32'}, {'nonnan', 'finite', ...
    'nonsparse', 'finite', 'nonsparse', 'real', 'size',[NaN,2]}, ...
    mfilename);

tf = true;
end

%--------------------------------------------------------------------------
function tf = checkLengths(in)

validateattributes(in, {'int32'}, {'nonnan', 'finite', 'nonsparse',...
            'real', 'vector'}, mfilename);

tf = true;
end

%--------------------------------------------------------------------------
function tf = crossCheckPixelListAndLengths(PixelList, Lengths)
sz1 = sum(Lengths(:));
sz2 = size(PixelList,1);
coder.internal.errorIf(sz1 ~= sz2, ...
    'Coder:builtins:SizeMismatch',sz1,sz2);

tf = true;
end

%==========================================================================
% Calculate Ellipse parameters
%==========================================================================
function EllipseStruct = computeEllipseProps(region)
%computeEllipseProps  Calculate ellipse properties 
%
%   Find the ellipse that has the same normalized second central moments as 
%   the region. Compute the axes lengths and orientation of the ellipse. 

%   Reference:
%       Haralick and Shapiro, Computer and Robot Vision vol I, 
%       Addison-Wesley 1992, Appendix A.

EllipseStruct.Centroid = mean(region, 1);
EllipseStruct.Axes = [0 0]; %[majorAxis minorAxis]
EllipseStruct.Orientation = 0;

% Assign X and Y variables so that we're measuring orientation
% counterclockwise from the horizontal axis.

xbar = EllipseStruct.Centroid(1);
ybar = EllipseStruct.Centroid(2);

x =   region(:,1) - xbar;
y = -(region(:,2) - ybar); % This is negative for the
% orientation calculation (measured in the
% counter-clockwise direction).

N = length(x);

% Calculate normalized second central moments for the region. 1/12 is
% the normalized second central moment of a pixel with unit length.
uxx = sum(x.^2)/N + 1/12;
uyy = sum(y.^2)/N + 1/12;
uxy = sum(x.*y)/N;

% Calculate major axis length, minor axis length.
common = sqrt((uxx - uyy)^2 + 4*uxy^2);
EllipseStruct.Axes(1) = 2*sqrt(2)*sqrt(uxx + uyy + common);
EllipseStruct.Axes(2) = 2*sqrt(2)*sqrt(uxx + uyy - common);

% Calculate orientation.
if (uyy > uxx)
    num = uyy - uxx + sqrt((uyy - uxx)^2 + 4*uxy^2);
    den = 2*uxy;
else
    num = 2*uxy;
    den = uxx - uyy + sqrt((uxx - uyy)^2 + 4*uxy^2);
end

if (num == 0) && (den == 0)
    EllipseStruct.Orientation = 0;
else
    EllipseStruct.Orientation = atan(num/den);
end

end
% LocalWords:  OpenCV