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 and convert them to grayscale.
% I1 = rgb2gray(imread('scene_left.png'));
% I2 = rgb2gray(imread('scene_right.png'));
%
% figure; imshowpair(I1,I2,'ColorChannels','red-cyan');
% title(' Red-cyan composite view of the stereo images');
%
% % Compute the disparity map.
% disparityMap = disparity(I1, I2, 'BlockSize', 15, ...
% 'DisparityRange', [-6 10]);
%
% % For the purpose of visualizing the disparity, replace
% % the -realmax('single') marker with the minimum disparity value.
% marker_idx = (disparityMap == -realmax('single'));
% disparityMap(marker_idx) = min(disparityMap(~marker_idx));
%
% % Show the disparity map. Brighter pixels indicate意味着 objects which are
% % closer to the camera.
% figure; imshow(mat2gray(disparityMap));
% 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);
% 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 and convert them to grayscale.
% I1 = rgb2gray(imread('scene_left.png'));
% I2 = rgb2gray(imread('scene_right.png'));
%
% figure; imshowpair(I1,I2,'ColorChannels','red-cyan');
% title(' Red-cyan composite view of the stereo images');
%
% % Compute the disparity map.
% disparityMap = disparity(I1, I2, 'BlockSize', 15, ...
% 'DisparityRange', [-6 10]);
%
% % For the purpose of visualizing the disparity, replace
% % the -realmax('single') marker with the minimum disparity value.
% marker_idx = (disparityMap == -realmax('single'));
% disparityMap(marker_idx) = min(disparityMap(~marker_idx));
%
% % Show the disparity map. Brighter pixels indicate意味着 objects which are
% % closer to the camera.
% figure; imshow(mat2gray(disparityMap));
% 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);