boofcv.factory.disparity.FactoryStereoDisparityAlgs Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of boofcv-ip-multiview Show documentation
Show all versions of boofcv-ip-multiview Show documentation
BoofCV is an open source Java library for real-time computer vision and robotics applications.
/*
* Copyright (c) 2023, Peter Abeles. All Rights Reserved.
*
* This file is part of BoofCV (http://boofcv.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package boofcv.factory.disparity;
import boofcv.abst.filter.FilterImageInterface;
import boofcv.alg.disparity.DisparityBlockMatchRowFormat;
import boofcv.alg.disparity.block.BlockRowScore;
import boofcv.alg.disparity.block.BlockRowScoreMutualInformation;
import boofcv.alg.disparity.block.DisparitySelect;
import boofcv.alg.disparity.block.DisparitySparseSelect;
import boofcv.alg.disparity.block.select.*;
import boofcv.alg.disparity.sgm.*;
import boofcv.alg.disparity.sgm.cost.SgmCostAbsoluteDifference;
import boofcv.alg.disparity.sgm.cost.SgmCostFromBlocks;
import boofcv.alg.disparity.sgm.cost.SgmCostHamming;
import boofcv.alg.disparity.sgm.cost.StereoMutualInformation;
import boofcv.concurrency.BoofConcurrency;
import boofcv.core.image.border.FactoryImageBorder;
import boofcv.factory.transform.census.FactoryCensusTransform;
import boofcv.struct.image.*;
import org.jetbrains.annotations.Nullable;
import static boofcv.factory.disparity.FactoryStereoDisparity.*;
/**
* Algorithms related to computing the disparity between two rectified stereo images.
*
* @author Peter Abeles
*/
@SuppressWarnings({"rawtypes", "unchecked"})
public class FactoryStereoDisparityAlgs {
/**
* Creates SGM stereo using HMI.
*/
public static SgmStereoDisparity createSgm( @Nullable ConfigDisparitySGM config ) {
if (config == null)
config = new ConfigDisparitySGM();
int maxError = config.maxError < 0 ? Integer.MAX_VALUE : config.maxError;
SgmDisparitySelector selector = BoofConcurrency.USE_CONCURRENT ?
new SgmDisparitySelector_MT() : new SgmDisparitySelector();
selector.setRightToLeftTolerance(config.validateRtoL);
selector.setMaxError(maxError);
selector.setTextureThreshold(config.texture);
SgmStereoDisparity sgm;
// There's currently no block variant of MI
if (!config.useBlocks)
sgm = createSgmNativeCost(config, selector);
else
sgm = createSgmBlockCost(config, selector, GrayU8.class);
sgm.setDisparityMin(config.disparityMin);
sgm.setDisparityRange(config.disparityRange);
sgm.getAggregation().setPathsConsidered(config.paths.getCount());
sgm.getAggregation().setPenalty1(config.penaltySmallChange);
sgm.getAggregation().setPenalty2(config.penaltyLargeChange);
return sgm;
}
private static SgmStereoDisparity createSgmNativeCost( ConfigDisparitySGM config, SgmDisparitySelector selector ) {
SgmStereoDisparity sgm;
switch (config.errorType) {
case MUTUAL_INFORMATION: {
StereoMutualInformation stereoMI = createStereoMutualInformation(config);
sgm = new SgmStereoDisparityHmi(config.configHMI.pyramidLayers, stereoMI, selector);
((SgmStereoDisparityHmi)sgm).setExtraIterations(config.configHMI.extraIterations);
}
break;
case ABSOLUTE_DIFFERENCE: {
sgm = new SgmStereoDisparityError(new SgmCostAbsoluteDifference.U8(), selector);
}
break;
case CENSUS: {
FilterImageInterface censusTran = FactoryCensusTransform.variant(config.configCensus.variant, true, GrayU8.class);
Class censusType = censusTran.getOutputType().getImageClass();
SgmCostHamming cost;
if (censusType == GrayU8.class) {
cost = new SgmCostHamming.U8();
} else if (censusType == GrayS32.class) {
cost = new SgmCostHamming.S32();
} else if (censusType == GrayS64.class) {
cost = new SgmCostHamming.S64();
} else {
throw new IllegalArgumentException("Unsupported image type");
}
sgm = new SgmStereoDisparityCensus(censusTran, cost, selector);
}
break;
default:
throw new IllegalArgumentException("Unknown error type " + config.errorType);
}
return sgm;
}
private static >
SgmStereoDisparity createSgmBlockCost( ConfigDisparitySGM config, SgmDisparitySelector selector, Class imageType ) {
SgmStereoDisparity sgm;
ConfigDisparityBM configBM = new ConfigDisparityBM();
configBM.regionRadiusX = config.configBlockMatch.radiusX;
configBM.regionRadiusY = config.configBlockMatch.radiusY;
configBM.disparityMin = config.disparityMin;
configBM.disparityRange = config.disparityRange;
configBM.border = config.border;
SgmCostFromBlocks blockCost = new SgmCostFromBlocks();
DisparityBlockMatchRowFormat blockScore;
switch (config.errorType) {
case MUTUAL_INFORMATION: {
if (imageType != GrayU8.class) {
throw new IllegalArgumentException("Only GrayU8 supported at this time for Mutual Information");
}
StereoMutualInformation stereoMI = createStereoMutualInformation(config);
BlockRowScore rowScore = new BlockRowScoreMutualInformation.U8(stereoMI);
rowScore.setBorder(FactoryImageBorder.generic(config.border, rowScore.getImageType()));
blockScore = createSgmBlockMatch(config, imageType, configBM, blockCost, rowScore);
blockScore.setBorder(FactoryImageBorder.generic(config.border, rowScore.getImageType()));
sgm = new SgmStereoDisparityHmi(config.configHMI.pyramidLayers, stereoMI, selector, (SgmCostFromBlocks)blockCost);
((SgmStereoDisparityHmi)sgm).setExtraIterations(config.configHMI.extraIterations);
}
break;
case ABSOLUTE_DIFFERENCE: {
BlockRowScore rowScore = createScoreRowSad(configBM, imageType);
blockScore = createSgmBlockMatch(config, (Class)imageType, configBM, (SgmCostFromBlocks)blockCost, rowScore);
blockScore.setBorder(FactoryImageBorder.generic(config.border, rowScore.getImageType()));
sgm = new SgmStereoDisparityError(blockCost, selector);
}
break;
case CENSUS: {
FilterImageInterface censusTran = FactoryCensusTransform.variant(config.configCensus.variant, true, imageType);
BlockRowScore rowScore = createCensusRowScore(configBM, censusTran);
blockScore = createSgmBlockMatch(config, censusTran.getOutputType().getImageClass(),
configBM, blockCost, rowScore);
blockScore.setBorder(FactoryImageBorder.generic(config.border, censusTran.getOutputType()));
sgm = new SgmStereoDisparityCensus(censusTran, blockCost, selector);
}
break;
default:
throw new IllegalArgumentException("Unknown error type " + config.errorType);
}
blockCost.setBlockScore(blockScore);
return sgm;
}
private static StereoMutualInformation createStereoMutualInformation( ConfigDisparitySGM config ) {
StereoMutualInformation stereoMI = new StereoMutualInformation();
stereoMI.configureSmoothing(config.configHMI.smoothingRadius);
stereoMI.configureHistogram(config.configHMI.totalGrayLevels);
return stereoMI;
}
private static > DisparityBlockMatchRowFormat
createSgmBlockMatch( ConfigDisparitySGM config, Class imageType, ConfigDisparityBM configBM,
SgmCostFromBlocks blockCost, BlockRowScore rowScore ) {
DisparityBlockMatchRowFormat blockScore = switch (config.configBlockMatch.approach) {
case BASIC -> createBlockMatching(configBM, imageType, blockCost, rowScore);
case BEST5 -> createBestFive(configBM, imageType, blockCost, rowScore);
default -> throw new IllegalArgumentException("Unknown type " + config.configBlockMatch.approach);
};
return blockScore;
}
public static DisparitySelect selectDisparity_S32( int maxError, int tolR2L, double texture ) {
if (maxError < 0 && tolR2L < 0 && texture <= 0)
return new SelectErrorBasicWta_S32_U8();
else
return new SelectErrorWithChecks_S32.DispU8(maxError, tolR2L, texture);
}
public static DisparitySelect selectDisparity_F32( int maxError, int tolR2L, double texture ) {
if (maxError < 0 && tolR2L < 0 && texture <= 0)
return new SelectErrorBasicWta_F32_U8();
else
return new SelectErrorWithChecks_F32.DispU8(maxError, tolR2L, texture);
}
public static > DisparitySelect selectCorrelation_F32( int tolR2L, double texture, boolean subpixel ) {
if (!subpixel && tolR2L < 0 && texture <= 0)
return (DisparitySelect)new SelectCorrelationWta_F32_U8();
else if (!subpixel)
return (DisparitySelect)new SelectCorrelationWithChecks_F32.DispU8(tolR2L, texture);
else
return (DisparitySelect)new SelectCorrelationSubpixel.F32_F32(tolR2L, texture);
}
public static DisparitySelect
selectDisparitySubpixel_S32( int maxError, int tolR2L, double texture, boolean squaredError ) {
return new SelectErrorSubpixel.S32_F32(maxError, tolR2L, texture, squaredError);
}
public static DisparitySelect
selectDisparitySubpixel_F32( int maxError, int tolR2L, double texture, boolean squaredError ) {
return new SelectErrorSubpixel.F32_F32(maxError, tolR2L, texture, squaredError);
}
public static DisparitySparseSelect
selectDisparitySparse_S32( int maxError, double texture, int tolRightToLeft ) {
if (maxError < 0 && texture <= 0)
return new SelectSparseErrorBasicWta_S32();
else
return new SelectSparseErrorWithChecksWta_S32(maxError, texture, tolRightToLeft);
}
public static DisparitySparseSelect
selectDisparitySparse_F32( int maxError, double texture, int tolRightToLeft ) {
if (maxError < 0 && texture <= 0)
return new SelectSparseErrorBasicWta_F32();
else
return new SelectSparseErrorWithChecksWta_F32(maxError, texture, tolRightToLeft);
}
public static DisparitySparseSelect
selectDisparitySparseSubpixel_S32( int maxError, double texture, int tolRightToLeft, boolean squaredError ) {
return new SelectSparseErrorSubpixel.S32(maxError, texture, tolRightToLeft, squaredError);
}
public static DisparitySparseSelect
selectDisparitySparseSubpixel_F32( int maxError, double texture, int tolRightToLeft, boolean squaredError ) {
return new SelectSparseErrorSubpixel.F32(maxError, texture, tolRightToLeft, squaredError);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy