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

boofcv.alg.disparity.block.SparseScoreRectifiedCensus 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) 2022, 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.alg.disparity.block;

import boofcv.abst.transform.census.FilterCensusTransform;
import boofcv.alg.descriptor.DescriptorDistance;
import boofcv.alg.disparity.block.score.DisparitySparseRectifiedScoreBM_S32;
import boofcv.struct.image.*;

/**
 * Disparity score functions for sparse Census.
 *
 * WARNING: This will not produce identical results to the dense implementation at the image border. In the
 * dense implementation it computes the Census transform for the entire image. Then when it computes the block
 * score it ventures outside the image again and by default will reflect while in the sparse case it uses
 * a padded sub image and will not trigger a border situation. To fix this problem would require a lot of
 * complex specialized code and would most likely not produce significantly better results.
 *
 * @author Peter Abeles
 */
public interface SparseScoreRectifiedCensus {

	/**
	 * Applies a census transform to the input image and creates a new transformed image patch for later processing
	 */
	abstract class Census, Out extends ImageGray>
			extends DisparitySparseRectifiedScoreBM_S32 {
		// Applies census transform to input iamges
		FilterCensusTransform censusTran;

		// census transform applied to left and right image patches
		Out censusLeft, censusRight;

		protected Census( int radiusX, int radiusY, FilterCensusTransform censusTran, Class imageType ) {
			super(radiusX, radiusY, imageType);
			this.censusTran = censusTran;
			setSampleRegion(censusTran.getRadiusX(), censusTran.getRadiusY());

			censusLeft = censusTran.getOutputType().createImage(1, 1);
			censusRight = censusTran.getOutputType().createImage(1, 1);
		}

		@Override
		public void configure( int disparityMin, int disparityRange ) {
			super.configure(disparityMin, disparityRange);
			censusLeft.reshape(patchTemplate);
		}

		@Override
		protected void scoreDisparity( int disparityRange, final boolean leftToRight ) {
			censusRight.reshape(patchCompare);

			// NOTE: the borders do not need to be processed
			censusTran.process(patchTemplate, censusLeft);
			censusTran.process(patchCompare, censusRight);

			scoreCensus(disparityRange, leftToRight);
		}

		protected abstract void scoreCensus( int disparityRange, final boolean leftToRight );
	}

	/**
	 * Computes census score for transformed images of type U8
	 */
	class U8> extends Census {
		public U8( int radiusX, int radiusY,
				   FilterCensusTransform censusTran,
				   Class imageType ) {
			super(radiusX, radiusY, censusTran, imageType);
		}

		@Override
		protected void scoreCensus( int disparityRange, final boolean leftToRight ) {
			final int[] scores = leftToRight ? scoreLtoR : scoreRtoL;
			final byte[] dataLeft = censusLeft.data;
			final byte[] dataRight = censusRight.data;
			for (int d = 0; d < disparityRange; d++) {
				int total = 0;
				for (int y = 0; y < blockHeight; y++) {
					int idxLeft = (y + sampleRadiusY)*censusLeft.stride + sampleRadiusX;
					int idxRight = (y + sampleRadiusY)*censusRight.stride + sampleRadiusX + d;
					for (int x = 0; x < blockWidth; x++) {
						final int a = dataLeft[idxLeft++] & 0xFF;
						final int b = dataRight[idxRight++] & 0xFF;
						total += DescriptorDistance.hamming(a ^ b);
					}
				}
				int index = leftToRight ? disparityRange - d - 1 : d;
				scores[index] = total;
			}
		}
	}

	/**
	 * Computes census score for transformed images of type S32
	 */
	class S32> extends Census {
		public S32( int radiusX, int radiusY,
					FilterCensusTransform censusTran,
					Class imageType ) {
			super(radiusX, radiusY, censusTran, imageType);
		}

		@Override
		protected void scoreCensus( int disparityRange, final boolean leftToRight ) {
			final int[] scores = leftToRight ? scoreLtoR : scoreRtoL;
			final int[] dataLeft = censusLeft.data;
			final int[] dataRight = censusRight.data;
			for (int d = 0; d < disparityRange; d++) {
				int total = 0;
				for (int y = 0; y < blockHeight; y++) {
					int idxLeft = (y + sampleRadiusY)*censusLeft.stride + sampleRadiusX;
					int idxRight = (y + sampleRadiusY)*censusRight.stride + sampleRadiusX + d;
					for (int x = 0; x < blockWidth; x++) {
						final int a = dataLeft[idxLeft++];
						final int b = dataRight[idxRight++];
						total += DescriptorDistance.hamming(a ^ b);
					}
				}
				int index = leftToRight ? disparityRange - d - 1 : d;
				scores[index] = total;
			}
		}
	}

	/**
	 * Computes census score for transformed images of type S64
	 */
	class S64> extends Census {
		public S64( int radiusX, int radiusY,
					FilterCensusTransform censusTran,
					Class imageType ) {
			super(radiusX, radiusY, censusTran, imageType);
		}

		@Override
		protected void scoreCensus( int disparityRange, final boolean leftToRight ) {
			final int[] scores = leftToRight ? scoreLtoR : scoreRtoL;
			final long[] dataLeft = censusLeft.data;
			final long[] dataRight = censusRight.data;
			for (int d = 0; d < disparityRange; d++) {
				int total = 0;
				for (int y = 0; y < blockHeight; y++) {
					int idxLeft = (y + sampleRadiusY)*censusLeft.stride + sampleRadiusX;
					int idxRight = (y + sampleRadiusY)*censusRight.stride + sampleRadiusX + d;
					for (int x = 0; x < blockWidth; x++) {
						final long a = dataLeft[idxLeft++];
						final long b = dataRight[idxRight++];
						total += DescriptorDistance.hamming(a ^ b);
					}
				}
				int index = leftToRight ? disparityRange - d - 1 : d;
				scores[index] = total;
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy