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

boofcv.alg.fiducial.qrcode.SquareLocatorPatternDetectorBase Maven / Gradle / Ivy

/*
 * 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.fiducial.qrcode;

import boofcv.abst.filter.binary.BinaryContourFinder;
import boofcv.alg.distort.LensDistortionNarrowFOV;
import boofcv.alg.interpolate.InterpolatePixelDistortS;
import boofcv.alg.interpolate.InterpolatePixelS;
import boofcv.alg.shapes.polygon.DetectPolygonBinaryGrayRefine;
import boofcv.factory.interpolate.FactoryInterpolation;
import boofcv.misc.BoofMiscOps;
import boofcv.misc.MovingAverage;
import boofcv.struct.ConfigLength;
import boofcv.struct.border.BorderType;
import boofcv.struct.distort.PixelTransform;
import boofcv.struct.distort.Point2Transform2_F32;
import boofcv.struct.distort.PointToPixelTransform_F32;
import boofcv.struct.image.GrayU8;
import boofcv.struct.image.ImageGray;
import georegression.struct.point.Point2D_F32;
import lombok.Getter;
import lombok.Setter;
import org.ddogleg.struct.VerbosePrint;
import org.jetbrains.annotations.Nullable;

import java.io.PrintStream;
import java.util.Set;

/**
 * Several fiducials use square objects as locator patterns for the markers. This contains common code.
 *
 * @author Peter Abeles
 */
public abstract class SquareLocatorPatternDetectorBase> implements VerbosePrint {
	/** used to subsample the input image */
	@Getter protected InterpolatePixelS interpolate;

	/** Used to prune very large contours. This is tuned for QR codes which have two position patterns side by side */
	@Getter @Setter protected double maxContourFraction = 4.0/3.0;

	/** Used to detect black squares */
	@Getter protected DetectPolygonBinaryGrayRefine squareDetector;

	/** runtime profiling */
	@Getter protected MovingAverage profilingMS = new MovingAverage(0.8);

	@Nullable protected PrintStream verbose = null;

	/**
	 * Configures the detector
	 *
	 * @param squareDetector Square detector
	 */
	protected SquareLocatorPatternDetectorBase( DetectPolygonBinaryGrayRefine squareDetector ) {
		this.squareDetector = squareDetector;

		squareDetector.getDetector().setConvex(true);
		squareDetector.getDetector().setOutputClockwiseUpY(false);
		squareDetector.getDetector().setNumberOfSides(4, 4);

		interpolate = FactoryInterpolation.bilinearPixelS(squareDetector.getInputType(), BorderType.EXTENDED);
	}

	/**
	 * Detects position patterns inside the image and forms a graph.
	 *
	 * @param gray Gray scale input image
	 * @param binary Binary version of gray image.
	 */
	public void process( T gray, GrayU8 binary ) {
		// don't sanity check binary shape here since it may or may not be padded. See square detector
		configureContourDetector(gray);
		interpolate.setImage(gray);

		// detect squares
		squareDetector.process(gray, binary);

		long time0 = System.nanoTime();
		findLocatorPatternsFromSquares();
		long time1 = System.nanoTime();

		profilingMS.update((time1 - time0)*1e-6);
	}

	/** Called after squares have been detected and you are using detected squares to identify locator patterns */
	protected abstract void findLocatorPatternsFromSquares();

	/**
	 * 

Specifies transforms which can be used to change coordinates from distorted to undistorted and the opposite * coordinates. The undistorted image is never explicitly created.

* * @param width Input image width. Used in sanity check only. * @param height Input image height. Used in sanity check only. * @param model distortion model. Null to remove a distortion model. */ public void setLensDistortion( int width, int height, @Nullable LensDistortionNarrowFOV model ) { interpolate = FactoryInterpolation.bilinearPixelS( squareDetector.getInputType(), BorderType.EXTENDED); if (model != null) { PixelTransform distToUndist = new PointToPixelTransform_F32(model.undistort_F32(true, true)); PixelTransform undistToDist = new PointToPixelTransform_F32(model.distort_F32(true, true)); squareDetector.setLensDistortion(width, height, distToUndist, undistToDist); // needs to sample the original image when the Point2Transform2_F32 u2d = model.distort_F32(true, true); this.interpolate = new InterpolatePixelDistortS<>(this.interpolate, u2d); } else { squareDetector.setLensDistortion(width, height, null, null); } } /** * Configures the contour detector based on the image size. Setting a maximum contour and turning off recording * of inner contours and improve speed and reduce the memory footprint significantly. */ protected void configureContourDetector( T gray ) { // determine the maximum possible size of a position pattern // contour size is maximum when viewed head one. Assume the smallest qrcode is 3x this width // 4 side in a square int maxContourSize = (int)(Math.min(gray.width, gray.height)*maxContourFraction); BinaryContourFinder contourFinder = squareDetector.getDetector().getContourFinder(); contourFinder.setMaxContour(ConfigLength.fixed(maxContourSize)); contourFinder.setSaveInnerContour(false); } @Override public void setVerbose( @Nullable PrintStream out, @Nullable Set configuration ) { this.verbose = BoofMiscOps.addPrefix(this, out); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy