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

boofcv.alg.feature.dense.BaseDenseHog 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.alg.feature.dense;

import boofcv.abst.filter.derivative.ImageGradient;
import boofcv.alg.filter.derivative.DerivativeReduceType;
import boofcv.alg.filter.derivative.DerivativeType;
import boofcv.factory.filter.derivative.FactoryDerivative;
import boofcv.struct.feature.TupleDesc_F64;
import boofcv.struct.image.*;
import georegression.struct.point.Point2D_I32;
import org.ddogleg.struct.FastQueue;

/**
 * Base calss for dense HOG implementations.
 *
 * @author Peter Abeles
 */
public abstract class BaseDenseHog> {

	ImageGradient gradient;

	// gradient of each pixel
	protected GrayF32 derivX = new GrayF32(1,1);
	protected GrayF32 derivY = new GrayF32(1,1);

	// Storage for descriptors
	FastQueue descriptions;

	// Location of each descriptor in the image, top-left corner (lower extents)
	FastQueue locations = new FastQueue<>(Point2D_I32::new);

	int orientationBins; // number of orientation bins computed in a block
	int pixelsPerCell; // number of pixels wide a cell is
	int cellsPerBlockX;  // number of cells wide a block is
	int cellsPerBlockY;  // number of cells wide a block is
	int stepBlock; // how many cells are skipped between a block

	// type of input image
	ImageType imageType;

	/**
	 * Configures HOG descriptor computation
	 *
	 * @param orientationBins Number of bins in a cell's histogram.  9 recommended
	 * @param pixelsPerCell Number of pixel's wide a cell is.  8 recommended
	 * @param cellsPerBlockX Number of cells's wide a block is. x-axis 3 recommended
	 * @param cellsPerBlockY Number of cells's wide a block is. x-axis 3 recommended
	 * @param stepBlock Number of cells which are skipped between each block
	 */
	public BaseDenseHog(int orientationBins , int pixelsPerCell ,
						int cellsPerBlockX , int cellsPerBlockY,
						int stepBlock ,
						ImageType imageType )
	{
		if( stepBlock <= 0 )
			throw new IllegalArgumentException("stepBlock must be >= 1");

		this.imageType = imageType;

		gradient = createGradient(imageType);

		this.orientationBins = orientationBins;
		this.pixelsPerCell = pixelsPerCell;
		this.cellsPerBlockX = cellsPerBlockX;
		this.cellsPerBlockY = cellsPerBlockY;
		this.stepBlock = stepBlock;

		final int descriptorLength = orientationBins*cellsPerBlockX*cellsPerBlockY;

		descriptions = new FastQueue<>(()-> new TupleDesc_F64(descriptorLength));
	}

	/**
	 * Given different types input images it creates the correct algorithm for computing the image gradient.  The
	 * actualy calulcation is always done using {@link DerivativeType#THREE}
	 */
	static >
	ImageGradient createGradient( ImageType imageType ) {
		ImageGradient gradient;
		ImageType typeF32 = ImageType.SB_F32;

		if( imageType.getDataType() != ImageDataType.F32 )
			throw new IllegalArgumentException("Input image type must be F32");

		if( imageType.getFamily() == ImageType.Family.GRAY) {
			gradient = FactoryDerivative.gradient(DerivativeType.THREE,imageType, typeF32);
		} else if( imageType.getFamily() == ImageType.Family.PLANAR ) {
			ImageType> typePF32 = ImageType.pl(imageType.getNumBands(),GrayF32.class);
			ImageGradient,Planar> gradientMB =
					FactoryDerivative.gradient(DerivativeType.THREE,typePF32, typePF32);
			gradient = (ImageGradient)FactoryDerivative.gradientReduce(gradientMB, DerivativeReduceType.MAX_F, GrayF32.class);
		} else {
			throw new IllegalArgumentException("Unsupported image type "+imageType);
		}

		return gradient;
	}

	/**
	 * Specifies input image.  Gradient is computed immediately
	 * @param input input image
	 */
	public void setInput( I input ) {
		derivX.reshape(input.width,input.height);
		derivY.reshape(input.width,input.height);

		// pixel gradient
		gradient.process(input,derivX,derivY);
	}

	public abstract void process();

	/**
	 * List of locations for each descriptor.
	 */
	public FastQueue getLocations() {
		return locations;
	}

	/**
	 * List of descriptors
	 */
	public FastQueue getDescriptions() {
		return descriptions;
	}

	public GrayF32 _getDerivX() {
		return derivX;
	}

	public GrayF32 _getDerivY() {
		return derivY;
	}

	/**
	 * Returns the number of pixel's wide the square region is that a descriptor was computed from
	 * @return number of pixels wide
	 */
	public int getRegionWidthPixelX() {
		return pixelsPerCell * cellsPerBlockX;
	}

	public int getRegionWidthPixelY() {
		return pixelsPerCell * cellsPerBlockY;
	}

	public int getPixelsPerCell() {
		return pixelsPerCell;
	}

	public int getCellsPerBlockX() {
		return cellsPerBlockX;
	}

	public int getCellsPerBlockY() {
		return cellsPerBlockY;
	}

	public int getStepBlock() {
		return stepBlock;
	}

	public int getOrientationBins() {
		return orientationBins;
	}

	public ImageType getImageType() {
		return imageType;
	}

	public TupleDesc_F64 createDescription() {
		return new TupleDesc_F64(orientationBins* cellsPerBlockX * cellsPerBlockY);
	}
}