gusucode.com > vision工具箱matlab源码程序 > vision/disparity.m
function disparityMap = disparity(I1,I2,varargin) % DISPARITY Compute disparity map. % disparityMap = DISPARITY(I1,I2) returns the disparity map for a pair of % stereo images, I1 and I2. I1 and I2 must have the same size and must be % rectified such that the corresponding points are located on the same % rows. This rectification can be performed using the rectifyStereoImages % function. The returned disparity map has the same size as I1 and % I2. % % The disparity function implements two different algorithms: Block % Matching and Semi-Global Block Matching. These algorithms consist of % the following steps: % % (1) Compute a measure of contrast of the image by using the Sobel filter. % % (2) Compute the disparity for each pixel in I1. % % (3) Mark the elements of d for which disparity was not computed % reliably with -REALMAX('single'). % % disparityMap = DISPARITY(...,Name,Value) specifies additional name-value pairs % described below: % % 'Method' 'BlockMatching' for basic Block Matching or 'SemiGlobal' for % Semi-Global Block Matching. In the Block Matching method the % function computes disparity by comparing the sum of absolute % differences (SAD) of each block of pixels in the image. In % the Semi-Global Block Matching method the function % additionally forces similar disparity on neighboring blocks. % This additional constraint results in a more complete % disparity estimate than in Block Matching. % % Default: 'SemiGlobal' % % 'DisparityRange' A two-element vector, [MinDisparity % MaxDisparity], defining the range of disparity. % MinDisparity and MaxDisparity must be integers % and their difference must be divisible by 16. % % Default: [0 64] % % 'BlockSize' An odd integer, 5 <= BlockSize <= 255. The width % of each square block of pixels used for % comparison between I1 and I2. % % Default: 15 % % 'ContrastThreshold' A scalar value, 0 < ContrastThreshold <= 1, % defining the acceptable range of contrast % values. Increasing this parameter results in % fewer pixels being marked as unreliable. % % Default: 0.5 % % 'UniquenessThreshold' A non-negative integer defining the minimum % value of uniqueness. If a pixel is less unique, % the disparity computed for it is less reliable. % Increasing this parameter will result in marking % more pixels unreliable. You can set this % parameter to 0 to disable it. % % Default: 15 % % 'DistanceThreshold' A non-negative integer defining the maximum % distance for left-right checking.Increasing this % parameter results in fewer pixels being marked % as unreliable. You can also set this parameter % to an empty matrix [] to disable it. % % Default: [] (disabled) % % 'TextureThreshold' A scalar value, 0 <= TextureThreshold <= 1, % defining the minimum texture. If a block of % pixels is less textured, the computed disparity % is less reliable. Increasing this parameter % results in more pixels being marked as % unreliable. Set this parameter to 0 to disable it. % % This parameter is used only with the % 'BlockMatching' method. % % Default: 0.0002 % % Class Support % ------------- % All inputs must be real, finite, and nonsparse. I1 and I2 must have the % same class and must be uint8, uint16, int16, single, or double. % % Example % ------- % % Load the images. % I1 = imread('scene_left.png'); % I2 = imread('scene_right.png'); % % % Show the stereo anaglyph. You can view the image in 3-D using % % red-cyan stereo glasses. % figure % imshow(stereoAnaglyph(I1,I2)); % title('Red-cyan composite view of the stereo images'); % % % Compute the disparity map. % disparityRange = [-6 10]; % disparityMap = disparity(rgb2gray(I1), rgb2gray(I2), 'BlockSize', 15, ... % 'DisparityRange', disparityRange); % % % Show the disparity map. For better visualization use the disparity % % range as the display range for imshow. % figure % imshow(disparityMap, disparityRange); % title('Disparity Map'); % colormap jet % colorbar % % See also rectifyStereoImages, reconstructScene, % estimateCameraParameters, estimateUncalibratedRectification % References: % ----------- % [1] K. Konolige, "Small Vision Systems: Hardware and Implementation," % Proceedings of the 8th International Symposium in Robotic Research, % pages 203-212, 1997. % % [2] G. Bradski and A. Kaehler, "Learning OpenCV : Computer Vision with % the OpenCV Library," O'Reilly, Sebastopol, CA, 2008. % % [3] Hirschmuller, Heiko. "Accurate and Efficient Stereo Processing by % Semi-Global Matching and Mutual Information." International Conference % on Computer Vision and Pattern Recognition, 2005. % % Copyright 2011-2012 The MathWorks, Inc. %#codegen %#ok<*EMCA> %-------------------------------------------------------------------------- % Parse the inputs %-------------------------------------------------------------------------- r = parseInputs(I1, I2, varargin{:}); % Two structures with overlapping fields are required for code generation % BlockMatching method parameters % ------------------------------- optBM.preFilterCap = int32(floor(63 * r.ContrastThreshold)); optBM.preFilterCap = int32(floor(63 * r.ContrastThreshold)); optBM.SADWindowSize = int32(r.BlockSize); optBM.minDisparity = int32(r.DisparityRange(1)); optBM.numberOfDisparities = int32(r.DisparityRange(2) - r.DisparityRange(1)); optBM.uniquenessRatio = int32(r.UniquenessThreshold); % parameters unique to block matching optBM.roi1 = int32(r.ROI1) - int32([1 1 0 0]); optBM.roi2 = int32(r.ROI2) - int32([1 1 0 0]); optBM.textureThreshold = int32(255 * r.TextureThreshold * r.BlockSize^2); % OpenCV parameters that are not exposed as optional parameters optBM.preFilterType = int32(1); % Fixed to CV_STEREO_BM_XSOBEL optBM.preFilterSize = int32(15); optBM.trySmallerWindows = int32(0); % SemiGlobal method parameters % ---------------------------- optSGBM.preFilterCap = int32(floor(63 * r.ContrastThreshold)); optSGBM.preFilterCap = int32(floor(63 * r.ContrastThreshold)); optSGBM.SADWindowSize = int32(r.BlockSize); optSGBM.minDisparity = int32(r.DisparityRange(1)); optSGBM.numberOfDisparities = int32(r.DisparityRange(2) - r.DisparityRange(1)); optSGBM.uniquenessRatio = int32(r.UniquenessThreshold); % OpenCV parameters that are not exposed as optional parameters optSGBM.P1 = int32(8 * r.BlockSize^2); optSGBM.P2 = int32(32 * r.BlockSize^2); optSGBM.fullDP = 0; % false if isempty(r.DistanceThreshold) optBM.disp12MaxDiff = int32(-1); optSGBM.disp12MaxDiff = int32(-1); else % in codegen, r.DistanceThreshold is never empty optBM.disp12MaxDiff = int32(r.DistanceThreshold); optSGBM.disp12MaxDiff = int32(r.DistanceThreshold); end %-------------------------------------------------------------------------- % Other OpenCV parameters which are not exposed in the main interface %-------------------------------------------------------------------------- optBM.speckleWindowSize = int32(0); optBM.speckleRange = int32(0); optSGBM.speckleWindowSize = int32(0); optSGBM.speckleRange = int32(0); %-------------------------------------------------------------------------- % Compute disparity %-------------------------------------------------------------------------- I1_u8 = im2uint8(I1); I2_u8 = im2uint8(I2); if isSimMode() if strcmpi(r.Method,'SemiGlobal') disparityMap = ocvDisparitySGBM(I1_u8, I2_u8, optSGBM); else disparityMap = ocvDisparityBM(I1_u8, I2_u8, optBM); end else if strcmpi(r.Method,'SemiGlobal') disparityMap = vision.internal.buildable.disparitySGBMBuildable.disparitySGBM_compute(... I1_u8, I2_u8, optSGBM); else disparityMap = vision.internal.buildable.disparityBMBuildable.disparityBM_compute(... I1_u8, I2_u8, optBM); end end %========================================================================== % Parse and check inputs %========================================================================== function r = parseInputs(I1, I2, varargin) vision.internal.inputValidation.validateImagePair(I1, I2, 'I1', 'I2', 'grayscale'); imageSize = size(I1); r = parseOptionalInputs(imageSize, varargin{:}); %-------------------------------------------------------------------------- % Check if ROI1 and ROI2 have the same size %-------------------------------------------------------------------------- errIf(any(r.ROI1(3:4) ~= r.ROI2(3:4)), 'vision:disparity:ROISizeMismatch'); errIf(~isa(r.ROI1, class(r.ROI2)), 'vision:disparity:ROIClassMismatch'); %-------------------------------------------------------------------------- % Check if BlockSize is smaller than both image size and the ROI size. %-------------------------------------------------------------------------- if all(r.ROI1(3:4) > 0) checkBlockSize(r.BlockSize, r.ROI1([4,3])); end checkBlockSize(r.BlockSize, imageSize); %========================================================================== function r = parseOptionalInputs(imageSize, varargin) if isSimMode() % inline the following function r = vision.internal.disparityParser(imageSize, getDefaultParameters(),... varargin{:}); else r = parseOptionalInputs_cg(imageSize, varargin{:}); end %========================================================================== function r = parseOptionalInputs_cg(imageSize, varargin) % Optional value: ROI1, ROI2 % Optional Name-Value pair: 6 pairs (see help section) defaults = getDefaultParameters(); defaultsNoVal = getDefaultParametersNoVal(); properties = getEmlParserProperties(); if nargin==1 % only imageSize r = defaults; return; end firstArg = varargin{1}; numargs = length(varargin); if isnumeric(firstArg) errIf((numargs<2) || (~isnumeric(varargin{2})), ... 'vision:disparity:ROIClassMismatch'); pvPairStartIdx = 3; else ROI1 = defaults.ROI1; ROI2 = defaults.ROI2; pvPairStartIdx = 1; end %varargin{pvPairStartIdx:end} = varargin{pvPairStartIdx:end}; optarg = eml_parse_parameter_inputs(defaultsNoVal, properties, varargin{pvPairStartIdx:end}); Method = eml_get_parameter_value(optarg.Method, ... defaults.Method, varargin{pvPairStartIdx:end}); ContrastThreshold = (eml_get_parameter_value( ... optarg.ContrastThreshold, defaults.ContrastThreshold, varargin{pvPairStartIdx:end})); BlockSize = (eml_get_parameter_value( ... optarg.BlockSize, defaults.BlockSize, varargin{pvPairStartIdx:end})); DisparityRange = (eml_get_parameter_value( ... optarg.DisparityRange, defaults.DisparityRange, varargin{pvPairStartIdx:end})); TextureThreshold = (eml_get_parameter_value( ... optarg.TextureThreshold, defaults.TextureThreshold, varargin{pvPairStartIdx:end})); UniquenessThreshold = (eml_get_parameter_value( ... optarg.UniquenessThreshold, defaults.UniquenessThreshold, varargin{pvPairStartIdx:end})); DistanceThreshold = (eml_get_parameter_value( ... optarg.DistanceThreshold, defaults.DistanceThreshold, varargin{pvPairStartIdx:end})); checkMethod(Method); isROIUsed = pvPairStartIdx == 3; if isROIUsed errIf(strcmpi(Method,'SemiGlobal'),... 'vision:disparity:ROINotAvailableForSGBM'); checkROI('ROI1', firstArg, imageSize, 1); secondArg = varargin{2}; checkROI('ROI1', secondArg, imageSize, 2); ROI1 = firstArg; ROI2 = secondArg; end checkContrastThreshold(ContrastThreshold); checkBlockSize(BlockSize, imageSize); checkDisparityRange(DisparityRange, imageSize); checkTextureThreshold(TextureThreshold); checkUniquenessThreshold(UniquenessThreshold); skipCheck = isscalar(DistanceThreshold) && ... (DistanceThreshold == defaults.DistanceThreshold); if ~skipCheck checkDistanceThreshold(DistanceThreshold, imageSize); end r.Method = Method; r.ContrastThreshold = ContrastThreshold; r.BlockSize = BlockSize; r.DisparityRange = DisparityRange; r.TextureThreshold = TextureThreshold; r.UniquenessThreshold = UniquenessThreshold; r.DistanceThreshold = DistanceThreshold; r.ROI1 = ROI1; r.ROI2 = ROI2; %========================================================================== function defaults = getDefaultParameters() defaults = struct(... 'Method', 'SemiGlobal',... 'ROI1', int32([1 1 0 0]), ... 'ROI2', int32([1 1 0 0]), ... 'ContrastThreshold', 0.5, ... 'BlockSize', 15, ... 'DisparityRange', [0 64], ... 'TextureThreshold', 0.0002, ... 'UniquenessThreshold', 15, ... 'DistanceThreshold', -107); % unusual value %========================================================================== function defaultsNoVal = getDefaultParametersNoVal() defaultsNoVal = struct(... 'Method',uint32(0),... 'ROI1', uint32(0), ... 'ROI2', uint32(0), ... 'ContrastThreshold', uint32(0), ... 'BlockSize', uint32(0), ... 'DisparityRange', uint32(0), ... 'TextureThreshold', uint32(0), ... 'UniquenessThreshold', uint32(0), ... 'DistanceThreshold', uint32(0)); %========================================================================== function properties = getEmlParserProperties() properties = struct( ... 'CaseSensitivity', false, ... 'StructExpand', true, ... 'PartialMatching', false); %========================================================================== function r = checkMethod(value) list = {'BlockMatching', 'SemiGlobal'}; validateattributes(value, {'char'}, {'nonempty'}, 'disparity', ... 'Method'); matchedValue = validatestring(value, list, mfilename, 'Method'); coder.internal.errorIf(~strcmpi(value, matchedValue), ... 'vision:validateString:unrecognizedStringChoice', value); r = 1; %========================================================================== function r = checkROI(name, value, imageSize, position) validateattributes(value, {'numeric'}, ... {'real', 'nonsparse', 'integer', 'positive', 'finite', 'size', [1, 4]},... mfilename, name, position); errIf(value(1)+value(3) > imageSize(2)+1 || value(2)+value(4) > imageSize(1)+1, ... 'vision:disparity:invalidROIValue'); r = 1; %========================================================================== function r = checkContrastThreshold(value) validateattributes(value, {'numeric'}, ... {'real', 'scalar', '>', 0, '<=', 1},... mfilename, 'ContrastThreshold'); r = 1; %========================================================================== function r = checkBlockSize(value, imageSize) maxBlockSize = min([imageSize, 255]); validateattributes(value, {'numeric'}, ... {'real', 'scalar', 'integer', 'odd', '>=', 5, '<=', maxBlockSize},... mfilename, 'BlockSize'); r = 1; %========================================================================== function r = checkDisparityRange(value,imageSize) maxValue = min(imageSize); validateattributes(value, {'numeric'}, ... {'real', 'nonsparse', 'integer', 'finite', 'size', [1,2], ... '>', -maxValue, '<', maxValue},... mfilename, 'DisparityRange'); errIf(value(2) <= value(1) || mod(value(2) - value(1), 16) ~= 0, ... 'vision:disparity:invalidDisparityRange'); r = 1; %========================================================================== function r = checkTextureThreshold(value) validateattributes(value, {'numeric'}, ... {'real', 'scalar', 'finite', 'nonnegative', '<', 1},... mfilename, 'TextureThreshold'); r = 1; %========================================================================== function r = checkUniquenessThreshold(value) validateattributes(value, {'numeric'}, ... {'real', 'scalar', 'integer', 'finite', 'nonnegative'},... mfilename, 'UniquenessThreshold'); r = 1; %========================================================================== function r = checkDistanceThreshold(value, imageSize) maxValue = min(imageSize); if ~isempty(value) validateattributes(value, {'numeric'}, ... {'real', 'scalar', 'integer', 'finite', 'nonnegative','<',maxValue},... mfilename, 'DistanceThreshold'); end r = 1; %========================================================================== function flag = isSimMode() flag = isempty(coder.target); %========================================================================== function errIf(condition, msgID) coder.internal.errorIf(condition, msgID);