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

boofcv.deepboof.ClipAndReduce Maven / Gradle / Ivy

/*
 * Copyright (c) 2021, 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.deepboof;

import boofcv.alg.distort.ImageDistort;
import boofcv.alg.distort.PixelTransformAffine_F32;
import boofcv.alg.interpolate.InterpolatePixel;
import boofcv.alg.interpolate.InterpolationType;
import boofcv.factory.distort.FactoryDistort;
import boofcv.factory.interpolate.FactoryInterpolation;
import boofcv.struct.border.BorderType;
import boofcv.struct.image.ImageBase;
import boofcv.struct.image.ImageType;

/**
 * Transforms an image in an attempt to not change the information contained inside of it for processing by
 * a classification algorithm that requires an image of fixed size. This is done by clipping the image to
 * ensure that it has the same aspect ratio then scales it using bilinear interpolation.
 *
 * @author Peter Abeles
 */
@SuppressWarnings({"NullAway.Init"})
public class ClipAndReduce> {

	// storage for clipped sub-region
	T clipped;

	// affine transform that specifies how to scale the image
	PixelTransformAffine_F32 transform = new PixelTransformAffine_F32();
	// class used to distort the image/shrink it
	ImageDistort distort;

	boolean clip;

	/**
	 * Configuration constructor
	 *
	 * @param clip If true it will first clip the image to make it square before reducing it's size. Otherwise both
	 * sides are scaled independently to make it square
	 * @param imageType Type of image it iwll be processing
	 */
	public ClipAndReduce( boolean clip, ImageType imageType ) {
		this.clip = clip;
		InterpolatePixel interp =
				FactoryInterpolation.createPixel(0, 255, InterpolationType.BILINEAR, BorderType.EXTENDED, imageType);
		distort = FactoryDistort.distort(false, interp, imageType);
		distort.setModel(transform);
	}

	/**
	 * Clipps and scales the input image as necessary
	 *
	 * @param input Input image. Typically larger than output
	 * @param output Output image
	 */
	public void massage( T input, T output ) {
		if (clip) {
			T inputAdjusted = clipInput(input, output);

			// configure a simple change in scale for both axises
			transform.getModel().a11 = input.width/(float)output.width;
			transform.getModel().a22 = input.height/(float)output.height;
			// this change is automatically reflected in the distortion class. It is configured to cache nothing

			distort.apply(inputAdjusted, output);
		} else {
			// scale each axis independently. It will have the whole image but it will be distorted
			transform.getModel().a11 = input.width/(float)output.width;
			transform.getModel().a22 = input.height/(float)output.height;

			distort.apply(input, output);
		}
	}

	/**
	 * Clip the input image to ensure a constant aspect ratio
	 */
	T clipInput( T input, T output ) {
		double ratioInput = input.width/(double)input.height;
		double ratioOutput = output.width/(double)output.height;

		T a = input;

		if (ratioInput > ratioOutput) { // clip the width
			int width = input.height*output.width/output.height;
			int x0 = (input.width - width)/2;
			int x1 = x0 + width;

			clipped = input.subimage(x0, 0, x1, input.height, clipped);
			a = clipped;
		} else if (ratioInput < ratioOutput) { // clip the height
			int height = input.width*output.height/output.width;
			int y0 = (input.height - height)/2;
			int y1 = y0 + height;

			clipped = input.subimage(0, y0, input.width, y1, clipped);
			a = clipped;
		}

		return a;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy