HoughLine2.java
package ac.essex.ooechs.imaging.commons.edge.hough;
import ac.essex.ooechs.imaging.commons.Pixel;
import java.awt.image.BufferedImage;
import java.awt.*;
import java.util.Vector;
/**
* Represents a linear line as detected by the hough transform.
* This line is represented by an angle theta and a radius from the centre.
*
* @author Olly Oechsle, University of Essex, Date: 13-Mar-2008
* @version 1.0
*/
public class HoughLine2 {
protected double theta;
protected double r;
boolean valid = true;
public HoughLine2(HoughLine line) {
this.theta = line.theta;
this.r = line.r;
}
/**
* Initialises the hough line
*/
public HoughLine2(double theta, double r) {
this.theta = theta;
this.r = r;
}
/**
* Draws the line on the image of your choice with the RGB colour of your choice.
*/
public void draw(BufferedImage image, BufferedImage newImage, int color) {
int height = image.getHeight();
int width = image.getWidth();
// During processing h_h is doubled so that -ve r values
int houghHeight = (int) (Math.sqrt(2) * Math.max(height, width)) / 2;
// Find edge points and vote in array
float centerX = width / 2;
float centerY = height / 2;
// Draw edges in output array
double tsin = Math.sin(theta);
double tcos = Math.cos(theta);
final int GREEN = Color.GREEN.getRGB();
final int RED = Color.RED.getRGB();
Vector<Pixel> line = new Vector<Pixel>(200);
int total = 0;
if (theta < Math.PI * 0.25 || theta > Math.PI * 0.75) {
// Draw vertical-ish lines
for (int y = 1; y < height - 1; y++) {
int x = (int) ((((r - houghHeight) - ((y - centerY) * tsin)) / tcos) + centerX);
if (x < width - 1 && x > 0) {
boolean edgeNearby = edgeNearTo(image, x, y);
if (edgeNearby) total++;
line.add(new Pixel(x, y, edgeNearby ? 1 : 0));
}
}
} else {
// Draw horizontal-sh lines
for (int x = 1; x < width - 1; x++) {
int y = (int) ((((r - houghHeight) - ((x - centerX) * tcos)) / tsin) + centerY);
if (y < height - 1 && y > 0) {
boolean edgeNearby = edgeNearTo(image, x, y);
if (edgeNearby) total++;
line.add(new Pixel(x, y, edgeNearby ? 1 : 0));
}
}
}
int startIndex;
for (startIndex = 0; startIndex < line.size(); startIndex++) {
Pixel p = line.elementAt(startIndex);
if (p.value == 1) {
start = p;
break;
}
}
int endIndex;
for (endIndex = line.size() - 1; endIndex > 0; endIndex--) {
Pixel p = line.elementAt(endIndex);
if (p.value == 1) {
end = p;
break;
}
}
double length = endIndex - startIndex;
double density = total / length;
if (density > 0.5) {
for (int i = startIndex; i < endIndex; i++) {
Pixel p = line.elementAt(i);
color = p.value == 1 ? GREEN : RED;
newImage.setRGB(p.x, p.y, color);
}
} else {
valid = false;
}
}
protected Pixel start, end;
public Pixel getStart() {
return start;
}
public Pixel getEnd() {
return end;
}
public boolean isValid() {
return valid;
}
public boolean edgeNearTo(BufferedImage image, int x, int y) {
int neighbourhoodSize = 1;
for (int dx = -neighbourhoodSize; dx <= neighbourhoodSize; dx++) {
for (int dy = -neighbourhoodSize; dy <= neighbourhoodSize; dy++) {
int X = x + dx;
int Y = y + dy;
if ((image.getRGB(X, Y) & 0x000000ff) != 0) {
return true;
}
}
}
return false;
}
}