gusucode.com > vision工具箱matlab源码程序 > vision/bboxOverlapRatio.m
function overlapRatio = bboxOverlapRatio(varargin) %bboxOverlapRatio Compute bounding box overlap ratio. % overlapRatio = bboxOverlapRatio(bboxA, bboxB) returns the overlap ratio % between each pair of bounding boxes contained in bboxA and bboxB. Each % row of bboxA and bboxB is a [x y width height] vector, where x and y are % an upper left corner of a bounding box. If bboxA is an M-by-4 matrix and % bboxB is an N-by-4 matrix, overlapRatio is an M-by-N matrix, with the % (I,J) entry equal to the overlap ratio between row I in bboxA and row J % in bboxB. By default, the overlap ratio between two boxes A and B is % defined as area(A intersect B) / area(A union B). The range of % overlapRatio is between 0 and 1, where 1 implies a perfect overlap. % % overlapRatio = bboxOverlapRatio(bboxA, bboxB, ratioType) additionally % lets you specify the method to compute the ratio. ratioType can be % 'Union', as described above, or 'Min'. When ratioType is 'Min', the % overlap ratio is defined as area(A intersect B) / min(area(A),area(B)). % % Class Support % ------------- % bboxA and bboxB are real, finite, and nonsparse. They can be uint8, % int8, uint16, int16, uint32, int32, single and double. The output % overlapRatio is double if bboxA or bboxB is double, otherwise it is % single. % % Example 1 - compute the overlap ratio between two bounding boxes % ---------- % % define two bounding boxes % bboxA = [1, 1, 100, 200]; % bboxB = bboxA + 20; % % % compute the overlap ratio between the two bounding boxes % overlapRatio = bboxOverlapRatio(bboxA, bboxB) % % Example 2 - compute the overlap ratio between every pair of bounding boxes % ---------- % % randomly generate two sets of bounding boxes % bboxA = 10*rand(5, 4); % bboxB = 10*rand(10, 4); % % % make sure the width and height are strictly positive % bboxA(:,3:4) = bboxA(:,3:4) + 10; % bboxB(:,3:4) = bboxB(:,3:4) + 10; % % % compute the overlap ratio between every pair % overlapRatio = bboxOverlapRatio(bboxA, bboxB) % % See also selectStrongestBbox % Copyright 2013-2014 The MathWorks, Inc. %#codegen %#ok<*EMCLS> %#ok<*EMCA> isUsingCodeGeneration = ~isempty(coder.target); % Parse and check inputs if isUsingCodeGeneration, [bboxA, bboxB, ratioType] = validateAndParseInputsCodegen(varargin{:}); else [bboxA, bboxB, ratioType] = validateAndParseInputs(varargin{:}); end if (isa(bboxA,'double') || isa(bboxB,'double')) bboxA = double(bboxA); bboxB = double(bboxB); else bboxA = single(bboxA); bboxB = single(bboxB); end if (isempty(bboxA) || isempty(bboxB)) overlapRatio = zeros(size(bboxA, 1), size(bboxB, 1), 'like', bboxA); return; end if isUsingCodeGeneration, overlapRatio = bboxOverlapRatioCodegen(bboxA, bboxB, ratioType); else if strncmpi(ratioType, 'Union', 1) overlapRatio = visionBboxIntersectByUnion(bboxA, bboxB); else overlapRatio = visionBboxIntersectByMin(bboxA, bboxB); end end end %========================================================================== function checkInputBoxes(bbox) % Validate the input boxes validateattributes(bbox,{'uint8', 'int8', 'uint16', 'int16', 'uint32', ... 'int32', 'single', 'double'}, {'real','nonsparse','finite','size',[NaN, 4]}, ... mfilename); if (any(bbox(:,3)<=0) || any(bbox(:,4)<=0)) error(message('vision:visionlib:invalidBboxHeightWidth')); end end %========================================================================== function checkRatioType(value) % Validate the input ratioType string list = {'Union', 'Min'}; validateattributes(value, {'char'}, {'nonempty'}, mfilename, 'RatioType'); validatestring(value, list, mfilename, 'RatioType'); end %========================================================================== function [bboxA, bboxB, ratioType] = validateAndParseInputs(varargin) % Validate and parse optional inputs % Setup parser parser = inputParser; parser.CaseSensitive = false; parser.FunctionName = mfilename; parser.addRequired('bboxA', @checkInputBoxes); parser.addRequired('bboxB', @checkInputBoxes); parser.addOptional('RatioType', 'Union', @checkRatioType); % Parse input parser.parse(varargin{:}); bboxA = parser.Results.bboxA; bboxB = parser.Results.bboxB; ratioType = parser.Results.RatioType; end %========================================================================== function checkInputBoxesCodegen(bbox) % Validate the input boxes validateattributes(bbox,{'uint8', 'int8', 'uint16', 'int16', 'uint32', ... 'int32', 'single', 'double'}, {'real','nonsparse','finite','size',[NaN, 4]}, ... mfilename); coder.internal.errorIf((any(bbox(:,3)<=0) || any(bbox(:,4)<=0)), ... 'vision:visionlib:invalidBboxHeightWidth'); end %========================================================================== function [bboxA, bboxB, ratioType] = validateAndParseInputsCodegen(varargin) % Validate and parse optional inputs eml_lib_assert(nargin >= 2, 'vision:visionlib:NotEnoughArgs', 'Not enough input arguments'); eml_lib_assert(nargin <= 3, 'vision:visionlib:TooManyArgs', 'Too many input arguments.'); bboxA = varargin{1}; checkInputBoxesCodegen(bboxA); bboxB = varargin{2}; checkInputBoxesCodegen(bboxB); if nargin == 3, ratioType = varargin{3}; validateattributes(ratioType, {'char'}, {'nonempty'}, mfilename, 'ratioType'); validatestring(ratioType, {'Union', 'Min'}, mfilename, 'ratioType'); else ratioType = 'Union'; end end %========================================================================== function overlapRatio = bboxOverlapRatioCodegen(bboxA, bboxB, ratioType) % Compute the overlap ratio between every row in bboxA and bboxB % left top corner x1BboxA = bboxA(:, 1); y1BboxA = bboxA(:, 2); % right bottom corner x2BboxA = x1BboxA + bboxA(:, 3); y2BboxA = y1BboxA + bboxA(:, 4); x1BboxB = bboxB(:, 1); y1BboxB = bboxB(:, 2); x2BboxB = x1BboxB + bboxB(:, 3); y2BboxB = y1BboxB + bboxB(:, 4); % area of the bounding box areaA = bboxA(:, 3) .* bboxA(:, 4); areaB = bboxB(:, 3) .* bboxB(:, 4); overlapRatio = zeros(size(bboxA,1),size(bboxB,1), 'like', bboxA); for m = 1:size(bboxA,1) for n = 1:size(bboxB,1) % compute the corners of the intersect x1 = max(x1BboxA(m), x1BboxB(n)); y1 = max(y1BboxA(m), y1BboxB(n)); x2 = min(x2BboxA(m), x2BboxB(n)); y2 = min(y2BboxA(m), y2BboxB(n)); % skip if there is no intersection w = x2 - x1; if w <= 0 continue; end h = y2 - y1; if h <= 0 continue; end intersectAB = w * h; if strncmpi(ratioType, 'Union', 1) % divide by union of bboxA and bboxB overlapRatio(m,n) = intersectAB/(areaA(m)+areaB(n)-intersectAB); else % divide by minimum of bboxA and bboxB overlapRatio(m,n) = intersectAB/min(areaA(m), areaB(n)); end end end end