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

boofcv.alg.feature.detect.line.HoughTransformLineFootOfNorm 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-2017, 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.detect.line;


import boofcv.abst.feature.detect.extract.NonMaxSuppression;
import boofcv.alg.InputSanityCheck;
import boofcv.alg.misc.ImageMiscOps;
import boofcv.struct.QueueCorner;
import boofcv.struct.image.*;
import georegression.struct.line.LineParametric2D_F32;
import georegression.struct.point.Point2D_I16;
import org.ddogleg.struct.FastQueue;
import org.ddogleg.struct.GrowQueue_F32;

/**
 * 

* Hough transform based line detector. Lines are parameterized based upon the (x,y) coordinate * of the closest point to the origin. This parametrization is more convenient since it corresponds * directly with the image space. See [1] for more details. *

* *

* The line's direction is estimated using the gradient at each point flagged as belonging to a line. * To minimize error the image center is used as the coordinate system's center. However lines which * lie too close to the center can't have their orientation accurately estimated. *

* *

* [1] Section 9.3 of E.R. Davies, "Machine Vision Theory Algorithms Practicalities," 3rd Ed. 2005 *

* * @author Peter Abeles */ public class HoughTransformLineFootOfNorm { // extracts line from the transform NonMaxSuppression extractor; // stores returned lines FastQueue lines = new FastQueue<>(10, LineParametric2D_F32.class, true); // lines are ignored if they are less than this distance from the origin // because the orientation can't be accurately estimated int minDistanceFromOrigin; // origin of the transform coordinate system int originX; int originY; // contains a set of counts for detected lines in each pixel // floating point image used because that's what FeatureExtractor's take as input GrayF32 transform = new GrayF32(1,1); // found lines in transform space QueueCorner foundLines = new QueueCorner(10); // list of points in the transform with non-zero values QueueCorner candidates = new QueueCorner(10); // line intensities for later pruning GrowQueue_F32 foundIntensity = new GrowQueue_F32(10); /** * Specifies parameters of transform. * * @param extractor Extracts local maxima from transform space. A set of candidates is provided, but can be ignored. * @param minDistanceFromOrigin Distance from the origin in which lines will not be estimated. In transform space. Try 5. */ public HoughTransformLineFootOfNorm(NonMaxSuppression extractor, int minDistanceFromOrigin) { this.extractor = extractor; this.minDistanceFromOrigin = minDistanceFromOrigin; } /** * Computes the Hough transform using the image gradient and a binary image which flags pixels as being edges or not. * * @param derivX Image derivative along x-axis. * @param derivY Image derivative along y-axis. * @param binary Non-zero pixels are considered to be line pixels. */ public > void transform(D derivX , D derivY , GrayU8 binary ) { InputSanityCheck.checkSameShape(derivX,derivY,binary); transform.reshape(derivX.width,derivY.height); ImageMiscOps.fill(transform,0); originX = derivX.width/2; originY = derivX.height/2; candidates.reset(); if( derivX instanceof GrayF32) _transform((GrayF32)derivX,(GrayF32)derivY,binary); else if( derivX instanceof GrayS16) _transform((GrayS16)derivX,(GrayS16)derivY,binary); else if( derivX instanceof GrayS32) _transform((GrayS32)derivX,(GrayS32)derivY,binary); else throw new IllegalArgumentException("Unsupported derivative image type: "+derivX.getClass().getSimpleName()); } /** * Searches for local maximas and converts into lines. * * @return Found lines in the image. */ public FastQueue extractLines() { lines.reset(); foundLines.reset(); foundIntensity.reset(); extractor.process(transform,null, candidates,null, foundLines); for( int i = 0; i < foundLines.size(); i++ ) { Point2D_I16 p = foundLines.get(i); int x0 = p.x - originX; int y0 = p.y - originY; if( Math.abs(x0) >= minDistanceFromOrigin || Math.abs(y0) >= minDistanceFromOrigin ) { LineParametric2D_F32 l = lines.grow(); l.p.set(p.x,p.y); l.slope.set(-y0,x0); foundIntensity.push(transform.get(p.x,p.y)); } } return lines; } /** * Takes the detected point along the line and its gradient and converts it into transform space. * @param x point in image. * @param y point in image. * @param derivX gradient of point. * @param derivY gradient of point. */ public void parameterize( int x , int y , float derivX , float derivY ) { // put the point in a new coordinate system centered at the image's origin // this minimizes error, which is a function of distance from origin x -= originX; y -= originY; float v = (x*derivX + y*derivY)/(derivX*derivX + derivY*derivY); // finds the foot a line normal equation and put the point into image coordinates int x0 = (int)(v*derivX) + originX; int y0 = (int)(v*derivY) + originY; if( transform.isInBounds(x0,y0)) { int index = transform.startIndex+y0*transform.stride+x0; // keep track of candidate pixels so that a sparse search can be done // to detect lines if( transform.data[index]++ == 1 ) candidates.add(x0,y0); } } /** * Returns the Hough transform image. * * @return Transform image. */ public GrayF32 getTransform() { return transform; } /** * Returns the intensity/edge count for each returned line. Useful when doing * post processing pruning. * * @return Array containing line intensities. */ public float[] getFoundIntensity() { return foundIntensity.data; } private void _transform(GrayF32 derivX , GrayF32 derivY , GrayU8 binary ) { // apply the transform to the entire image for( int y = 0; y < binary.height; y++ ) { int start = binary.startIndex + y*binary.stride; int end = start + binary.width; for( int index = start; index < end; index++ ) { if( binary.data[index] != 0 ) { int x = index-start; parameterize(x,y,derivX.unsafe_get(x,y),derivY.unsafe_get(x,y)); } } } } private void _transform(GrayS16 derivX , GrayS16 derivY , GrayU8 binary ) { // apply the transform to the entire image for( int y = 0; y < binary.height; y++ ) { int start = binary.startIndex + y*binary.stride; int end = start + binary.width; for( int index = start; index < end; index++ ) { if( binary.data[index] != 0 ) { int x = index-start; parameterize(x,y,derivX.unsafe_get(x,y),derivY.unsafe_get(x,y)); } } } } private void _transform(GrayS32 derivX , GrayS32 derivY , GrayU8 binary ) { // apply the transform to the entire image for( int y = 0; y < binary.height; y++ ) { int start = binary.startIndex + y*binary.stride; int end = start + binary.width; for( int index = start; index < end; index++ ) { if( binary.data[index] != 0 ) { int x = index-start; parameterize(x,y,derivX.unsafe_get(x,y),derivY.unsafe_get(x,y)); } } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy