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

com.github.ojil.algorithm.LinefitHoughVert Maven / Gradle / Ivy

There is a newer version: 0.0.11
Show newest version
/*
 * LinefitHoughVert.java
 *
 * Created on September 9, 2006, 1:15 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 *
 * Copyright 2007 by Jon A. Webb
 *     This program is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU Lesser General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU Lesser General Public License for more details.
 *
 *    You should have received a copy of the Lesser GNU General Public License
 *    along with this program.  If not, see .
 *
 */

package com.github.ojil.algorithm;
import java.util.Enumeration;
import java.util.Vector;

import com.github.ojil.core.Error;
import com.github.ojil.core.Point;

/**
 * Finds a line in an array of points using Hough transform. Not a pipeline
 * stage. Returns the most likely line as y-slope and x-intercept through
 * member access functions. The line search for should be oriented more or less
 * vertically (within the slope range specified).

* Lines are traditionally represented in terms of slope m and x-intercept b, i.e., * y = m * x + b. In this code we are concerned with vertical or nearly vertical * lines so we change the representation to x = m * y + b. b is then the x-intercept * (y = 0 gives x = b) and m is the "y-slope". m = 0 gives a vertical line at x = b. * @author webb */ public class LinefitHoughVert { /** @var cHoughAccum the Hough accumulator array */ Integer[][] cHoughAccum; /** @var cCount the number of points on the line that was found */ int cCount = 0; /** @var cMaxSlope the maximum allowable slope, times 256 */ final int cMaxSlope; /** @var cMaxX the maximum allowable x-intercept */ final int cMaxX; /** @var cMinSlope the minimum allowable slope, times 256 */ final int cMinSlope; /** @var cMinX the minimum allowable x-intercept */ final int cMinX; /** @var cSlope the slope of the line that was found, times 256 */ int cSlope; /** @var cSteps the number of steps to take from cMinSlope to cMaxSlope */ final int cSteps; /** @var cXInt the x-intercept of the line that was found */ int cXInt; /** Creates a new instance of LinefitHoughVert * * @param cMinX minimum X value * @param cMaxX maximum X value * @param cMinSlope minimum slope (multiplied by 256) * @param cMaxSlope maximum slope (multiplied by 256) * @param cSteps steps taken in Hough accumulator between minimum and * maximum slope. * @throws com.github.ojil.core.Error if X or slope range is empty, or * cSteps is not positive. */ public LinefitHoughVert( int cMinX, int cMaxX, int cMinSlope, int cMaxSlope, int cSteps) throws com.github.ojil.core.Error { if (cMaxX < cMinX) { throw new Error( Error.PACKAGE.ALGORITHM, ErrorCodes.PARAMETER_RANGE_NULL_OR_NEGATIVE, new Integer(cMinX).toString(), new Integer(cMaxX).toString(), null); } this.cMinX = cMinX; this.cMaxX = cMaxX; if (cMaxSlope < cMinSlope) { throw new Error( Error.PACKAGE.ALGORITHM, ErrorCodes.PARAMETER_RANGE_NULL_OR_NEGATIVE, new Integer(cMinSlope).toString(), new Integer(cMaxSlope).toString(), null); } if (cSteps <= 0) { throw new Error( Error.PACKAGE.ALGORITHM, ErrorCodes.PARAMETER_OUT_OF_RANGE, new Integer(cSteps).toString(), new Integer(1).toString(), new Integer(Integer.MAX_VALUE).toString()); } this.cMinSlope = cMinSlope; this.cMaxSlope = cMaxSlope; this.cSteps = cSteps; } /** Add a new point to the Hough accumulator array. We increment along the * line in the array * from (cMinSlope>>8, xIntStart) to (cMaxSlope>>8, xIntEnd), where * xIntStart is the x-intercept assuming the slope is at the minimum, * and xIntEnd is the x-intercept assuming the slope is maximal. * * @param p the point to add to the accumulator array */ private void addPoint(Point p) { // Remember the line we are fitting is // x = slope * x + intercept // compute initial intercept. cMinSlope is the real slope minimum // * 256. int xIntStart = (p.getX() * 256 - p.getY() * this.cMinSlope) / 256; // compute final intercept. cMaxSlope is the real slope maximum // * 256. int xIntEnd = (p.getX() * 256 - p.getY() * this.cMaxSlope) / 256; /** work along the line from (0,xIntStart) to (cSteps,xIntEnd), * incrementing the Hough accumulator. */ for (int slope = 0; slope < this.cSteps; slope++) { int xInt = (xIntEnd - xIntStart) * slope / this.cSteps + xIntStart; /** check if the current position falls inside the Hough * accumulator. */ if (xInt >= this.cMinX && xInt < this.cMaxX) { this.cHoughAccum[slope][xInt-this.cMinX]++; } }; } /** Find the peak in the Hough array. Updates cCount, cSlope, and cXInt. */ private void findPeak() { this.cCount = Integer.MIN_VALUE; for (int slope=0; slope this.cCount) { this.cCount = this.cHoughAccum[slope][x]; this.cSlope = slope * (this.cMaxSlope - this.cMinSlope) / this.cSteps + this.cMinSlope; this.cXInt = x + this.cMinX; } } } } /** Returns the count of points on the line that was found. * * @return the point count. */ public int getCount() { return this.cCount; } /** Returns the y-slope of the line that was found. * * @return the line slope (*256) */ public int getSlope() { return this.cSlope; } /** Returns the x-intercept of the line that was found. * * @return the x-intercept. */ public int getX() { return this.cXInt; } /** Finds the most likely line passing through the points in the Vector. * * @param points the input Vector of point positions * @throws com.github.ojil.core.Error if points is not a Vector of * point objects. */ public void push(Vector points) throws com.github.ojil.core.Error { /* create Hough accumulator */ this.cHoughAccum = new Integer[this.cSteps][this.cMaxX-this.cMinX]; /* fill the Hough accumulator */ for (Enumeration e = points.elements(); e.hasMoreElements();) { Object o = e.nextElement(); if (!(o instanceof Point)) { throw new Error( Error.PACKAGE.ALGORITHM, ErrorCodes.OBJECT_NOT_EXPECTED_TYPE, o.toString(), "Point", null); } Point p = (Point) o; addPoint(p); } findPeak(); // sets cXInt, cSlope, cCount for access by caller this.cHoughAccum = null; // free memory } /** Return a string describing the current instance, giving the values * of the constructor parameters. * * @return the string describing the current instance. */ public String toString() { return super.toString() + "(" + this.cMinX + "," + this.cMaxX + "," + //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ this.cMinSlope + "," + this.cMaxSlope + "," + this.cSteps + ")"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy