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; 
    } 
 
}