All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boofcv.factory.feature.disparity.FactoryStereoDisparityAlgs Maven / Gradle / Ivy

Go to download

BoofCV is an open source Java library for real-time computer vision and robotics applications.

There is a newer version: 1.1.7
Show newest version
/*
 * Copyright (c) 2011-2020, 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.feature.disparity;

import boofcv.abst.filter.FilterImageInterface;
import boofcv.alg.feature.disparity.DisparityBlockMatchRowFormat;
import boofcv.alg.feature.disparity.block.BlockRowScore;
import boofcv.alg.feature.disparity.block.BlockRowScoreMutualInformation;
import boofcv.alg.feature.disparity.block.DisparitySelect;
import boofcv.alg.feature.disparity.block.DisparitySparseSelect;
import boofcv.alg.feature.disparity.block.select.*;
import boofcv.alg.feature.disparity.sgm.*;
import boofcv.alg.feature.disparity.sgm.cost.SgmCostAbsoluteDifference;
import boofcv.alg.feature.disparity.sgm.cost.SgmCostFromBlocks;
import boofcv.alg.feature.disparity.sgm.cost.SgmCostHamming;
import boofcv.alg.feature.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 javax.annotation.Nullable;

import static boofcv.factory.feature.disparity.FactoryStereoDisparity.*;

/**
 * Algorithms related to computing the disparity between two rectified stereo images.
 *
 * @author Peter Abeles
 */
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:
				blockScore = createBlockMatching(configBM, imageType, blockCost, rowScore);
				break;

			case BEST5:
				blockScore = createBestFive(configBM, imageType, blockCost, rowScore);
				break;

			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) {
		return new SelectErrorSubpixel.S32_F32(maxError,tolR2L,texture);
	}

	public static DisparitySelect
	selectDisparitySubpixel_F32( int maxError , int tolR2L , double texture) {
		return new SelectErrorSubpixel.F32_F32(maxError,tolR2L,texture);
	}

	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) {
		return new SelectSparseErrorSubpixel.S32(maxError,texture,tolRightToLeft);
	}

	public static DisparitySparseSelect
	selectDisparitySparseSubpixel_F32( int maxError , double texture, int tolRightToLeft) {
		return new SelectSparseErrorSubpixel.F32(maxError,texture,tolRightToLeft);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy