import java.applet.*; import java.awt.*; import java.awt.image.*; import java.net.*; import java.util.*; import java.io.*; import java.awt.Color.*; import java.lang.Math.*; /** *LineDetector is an algorithm to find the lines in an image *@author:Timothy Sharman *@see code.iface.linedet */ public class LineDetector extends Thread{ //The Convolution operator used as part of the process. Convolution convolution; //the width and height of the output image private int d_w; private int d_h; private int [] dest_1d; //Create a new version of twoimages to put the output images in TwoImages twoimages = new TwoImages(); //The kernels to be used in the detection function private double [][] ker4 = {{-0.1667,-0.1667,-0.1667},{0.3333,0.3333,0.3333},{-0.1667,-0.1667,-0.1667}}; private double [][] ker2 = {{-0.1667,-0.1667,0.3333},{-0.1667,0.3333,-0.1667},{0.3333,-0.1667,-0.1667}}; private double [][] ker3 = {{0.3333,-0.1667,-0.1667},{-0.1667,0.3333,-0.1667},{-0.1667,-0.1667,0.3333}}; private double [][] ker1 = {{-0.1667,0.3333,-0.1667},{-0.1667,0.3333,-0.1667},{-0.1667,0.3333,-0.1667}}; /** *Applies the line detector to the input image *@param src_1d The source image as a pixel array *@param width width of the destination image in pixels *@param height height of the destination image in pixels *@param kernels Integer which determines which kernels are applied : * 1 = Kernel 1, 2 = Kernel 2, 4 = Kernel 3, 8 = Kernel 4. * These values are summed and the result is in kernels *@param thresh The threshold limit for kernel detection *@param choice Boolean which specifies whether to apply thresholding *@param scale The scale value to apply to the output *@param offset The offset to add to the output *@return The output array with the line edges and the colored edge image */ //Tim's Line Detection Algorithm /*a) assume the image is grey level (hence RR=GG=BB) b) use value &0x000000ff to get the BB value c) apply the selected kernels to the image d) return the output image */ public TwoImages apply_lineDetect(int [] src_1d, int width, int height, int kernels, int thresh, boolean choice, float scale, float offset){ d_w = width; d_h = height; dest_1d = new int[d_w*d_h]; int [] label_1d = new int[d_w*d_h]; double [] tmp_1d = new double[d_w*d_h]; double [] tmp2_1d = new double[d_w*d_h]; double [][] src_2d = new double[d_w][d_h]; //Initialise the destination and label array for(int i = 0; i < dest_1d.length; i++){ tmp2_1d[i] = -1000.0; label_1d[i] = 0xff000000; } //Change the source array into 2d double array for use with //convolution operator. for(int i = 0; i < d_w; i++){ for(int j = 0; j < d_h; j++){ //if (i==32 && j==100) System.out.println("Convolve bug: "+i+"+"+(j*d_w)); /// 26432 264 w 268 h src_2d[i][j] = (double)(src_1d[i+(j*d_w)] & 0x000000ff); //if (i==32 && j==100) System.out.println("Convolve data 2d: "+src_2d[i][j]+" "+src_1d[i+(j*d_w)]); } } //Find if the first kernel needs to be applied if((kernels & 1) == 1){ tmp_1d = convolution. convolutionDoublePadded(src_2d, d_w, d_h, ker1, 3, 3); for(int i = 0; i < tmp_1d.length; i++){ if(tmp_1d[i] > tmp2_1d[i]){ tmp2_1d[i] = tmp_1d[i]; label_1d[i] = 0xffffff00; } } } if((kernels & 2) == 2){ tmp_1d = convolution. convolutionDoublePadded(src_2d, d_w, d_h, ker2, 3, 3); for(int i = 0; i < tmp_1d.length; i++){ if(tmp_1d[i] > tmp2_1d[i]){ tmp2_1d[i] = tmp_1d[i]; label_1d[i] = 0xffff0000; } } } if((kernels & 4) == 4){ tmp_1d = convolution. convolutionDoublePadded(src_2d, d_w, d_h, ker3, 3, 3); for(int i = 0; i < tmp_1d.length; i++){ if(tmp_1d[i] > tmp2_1d[i]){ tmp2_1d[i] = tmp_1d[i]; label_1d[i] = 0xff00ff00; } } } if((kernels & 8) == 8){ tmp_1d = convolution. convolutionDoublePadded(src_2d, d_w, d_h, ker4, 3, 3); for(int i = 0; i < tmp_1d.length; i++){ //if (i==26432) System.out.println("Convolve bug tmp: "+tmp_1d[i]+" tmp2: "+tmp2_1d[i]); if(tmp_1d[i] > tmp2_1d[i]){ tmp2_1d[i] = tmp_1d[i]; label_1d[i] = 0xff0000ff; } } } // convert to integer double tmp_rgb; int dest_rgb; for(int i = 0; i < tmp2_1d.length; i++){ //Find the absolute edge strength tmp_rgb = tmp2_1d[i]; //Apply the threshold if necessary if(choice){ if(tmp_rgb > thresh){ //No change in value } else{ tmp_rgb = 0; label_1d[i] = 0xff000000; } } //Apply scaling and offset dest_rgb = (int)((scale*tmp_rgb)+offset); //Clip values if(dest_rgb < 0){dest_rgb = 0;} if(dest_rgb > 255){dest_rgb = 255;} //Output them dest_1d[i] = 0xff000000 | (dest_rgb + (dest_rgb << 16) + (dest_rgb << 8)); } //Set the output images of the return class twoimages. image1 = dest_1d; twoimages. image2 = label_1d; return twoimages; } }