edge detection

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
4 messages Options
Reply | Threaded
Open this post in threaded view
|

edge detection

Ru Wang
Hello All,

I am using Image J to detect my grain image.
http://picasaweb.google.com/wangru.ustc/Image_ProcessAlbum
The first one is the origin image and the last one is the final image.
But you can see the result is not that satisfactory. I am wondering
if you can come up with a better procedure to detect the boundaries.
Mine is the following:

1. find edges
2. sharpen
3. threshold
4. make binary
5. invert
6. skeltenize
7. dilate
8  skelen
9  remove the unconnected lines

Thanks.

Ru
Reply | Threaded
Open this post in threaded view
|

Re: edge detection

Jarek Grodek
Hello,

I was wondering how to remove the unconnected lines? pls, be so kind and
send me an answer.
Greetings,
Jarek



> Hello All,
>
> I am using Image J to detect my grain image.
> http://picasaweb.google.com/wangru.ustc/Image_ProcessAlbum
> The first one is the origin image and the last one is the final image.
> But you can see the result is not that satisfactory. I am wondering
> if you can come up with a better procedure to detect the boundaries.
> Mine is the following:
>
> 1. find edges
> 2. sharpen
> 3. threshold
> 4. make binary
> 5. invert
> 6. skeltenize
> 7. dilate
> 8  skelen
> 9  remove the unconnected lines
>
> Thanks.
>
> Ru
>
>
Reply | Threaded
Open this post in threaded view
|

Re: edge detection

Ru Wang
In reply to this post by Ru Wang
Hello,

I got the plug in to remove the unconnected lines from Michael Schmid.
Thank Michael again!

I can't see your email address. So I am going to post the code here.


Ru
Reply | Threaded
Open this post in threaded view
|

Re: edge detection

Ru Wang
In reply to this post by Ru Wang
here is a Plugin derived from the code in "MaximumFinder" that
eliminates unconnected lines.
Lines touching the edge are preserved.
Lines must be nonzero pixel values, background zero
(white background with inverted Lut, black background otherwise).

Michael
________________________________________________________________



import ij.*;
import ij.gui.*;
import ij.measure.*;
import ij.process.*;
//import java.awt.*;
//import java.util.*;
import ij.plugin.filter.*;

/** This ImageJ plug-in filter removes unconnected lines from
a binary image with background value 0 and lines having
pixel values > 0 */

public class Remove_Unconnected_Lines implements PlugInFilter {
     /** a point on a line (as a return type of isLineOrDot)*/
     final static int IS_LINE=1;
     /** an isolated point (as a return type of isLineOrDot)*/
     final static int IS_DOT=2;
     /**offsets of neighbor pixels for addressing*/
     int [] dirOffset, dirXoffset, dirYoffset;

     public int setup(String arg, ImagePlus imp) {
        return IJ.setupDialog(imp, DOES_8G);
     }
     public void run(ImageProcessor ip) {
     if (dirOffset==null) makeDirectionOffsets(ip);
         int width = ip.getWidth();
         int height = ip.getHeight();
         byte[] pixels =  (byte[])ip.getPixels();
         for (int y=0, i=0; y<height; y++) {
             for (int x=0; x<width; x++,i++) {
                 int v = pixels[i]&255;
                 if (v>0) {
                     int type = isLineOrDot(ip, x, y);
                     if (type==IS_DOT) {
                         pixels[i] = (byte)0;                  //
delete the point;
                     } else if (type==IS_LINE) {
                         int xEnd = x;
                         int yEnd = y;
                         boolean endFound = true;
                         while (endFound) {
                             pixels[xEnd + width*yEnd] = (byte)0;  //
delete the point
                             //if(movie.getSize()<100)movie.addSlice
("part-cleaned", ip.duplicate());
                             endFound = false;
                             for (int d=0; d<8; d++)  
{               //analyze neighbors of the point
                                 if (isWithin(ip, xEnd, yEnd, d)) {
                                     v = pixels[xEnd + width*yEnd +  
dirOffset[d]]&255;
                                     //if(x>210&&x<215&&y==13)IJ.write
("x,y start="+x+","+y+": look at="+xEnd+","+yEnd+"+dir "+d+": v="+v);
                                     if (v>0 && isLineOrDot(ip, xEnd
+dirXoffset[d], yEnd+dirYoffset[d])==IS_LINE) {
                                         xEnd += dirXoffset[d];
                                         yEnd += dirYoffset[d];
                                         endFound = true;
                                         break;
                                     }
                                 }
                             } // for directions d
                         } // while (endFound)
                     } // if IS_LINE
                 } // if v<255 && v>0
             } // for x
         } // for y

     }

     /** analyze the neighbors of a pixel (x, y) in a byte image;  
pixels >0 are
      * considered part of lines.
      * @param ip
      * @param x
      * @param y
      * @return  IS_LINE if pixel is part of a line, IS_DOT if a  
single dot
      */
     int isLineOrDot(ImageProcessor ip, int x, int y) {
         int result = 0;
         int width = ip.getWidth();
         int height = ip.getHeight();
         byte[] pixels = (byte[])ip.getPixels();
         int offset = x + y*width;
         int whiteNeighbors = 0;             //counts neighbors that  
are not part of a line
         int countTransitions = 0;
         boolean pixelSet;
         boolean prevPixelSet = true;
         boolean firstPixelSet = true;       //initialize to make the  
compiler happy
         for (int d=0; d<8; d++) {           //walk around the point  
and note every no-line->line transition
             if (isWithin(ip, x, y, d)) {
                 pixelSet = (pixels[offset+dirOffset[d]]!=0);
                 if (!pixelSet) whiteNeighbors++;
             } else {
                 pixelSet = true;
             }
             if (pixelSet && !prevPixelSet)
                 countTransitions ++;
             prevPixelSet = pixelSet;
             if (d==0)
                 firstPixelSet = pixelSet;
         }
         if (firstPixelSet && !prevPixelSet)
             countTransitions ++;
             //if (x>=210&&x<=215 && y>=10 && y<=17)IJ.write("x,y="+x
+","+y+": transitions="+countTransitions);
         if (countTransitions==1 && whiteNeighbors>=5)
             result = IS_LINE;
         else if (whiteNeighbors==8)
             result = IS_DOT;
         return result;
     } //isLineEnd

     /** create an array of offsets within a pixel array for  
directions in clockwise order: 0=(x,y-1), 1=(x+1,y-1), ... 7=(x-1,y)
      * uses class variable width: width of the image where the  
pixels should be addressed
      * returns as class variables: the arrays of the offsets to the  
8 neighboring pixels
      */
     private void makeDirectionOffsets(ImageProcessor ip) {
         int width = ip.getWidth();
         int height = ip.getHeight();
         dirOffset = new int[] { -width, -width+1, +1, +width+1,  
+width, +width-1,   -1, -width-1 };
         dirXoffset = new int[] {    0,       1,     1,     1,        
0,      -1,      -1,    -1    };
         dirYoffset = new int[] {   -1,      -1,     0,     1,        
1,       1,       0,    -1,   };
     }

     /** returns whether the neighbor in a given direction is within  
the image
      * NOTE: it is assumed that the pixel x,y itself is within the  
image!
      * Uses class variables width, height: dimensions of the image
      * @param x         x-coordinate of the pixel that has a  
neighbor in the given direction
      * @param y         y-coordinate of the pixel that has a  
neighbor in the given direction
      * @param direction the direction from the pixel towards the  
neighbor (see makeDirectionOffsets)
      * @return          true if the neighbor is within the image  
(provided that x, y is within)
      */
     boolean isWithin(ImageProcessor ip, int x, int y, int direction) {
         int width = ip.getWidth();
         int height = ip.getHeight();
         int xmax = width - 1;
         int ymax = height -1;
         switch(direction) {
             case 0:
                 return (y>0);
             case 1:
                 return (x<xmax && y>0);
             case 2:
                 return (x<xmax);
             case 3:
                 return (x<xmax && y<ymax);
             case 4:
                 return (y<ymax);
             case 5:
                 return (x>0 && y<ymax);
             case 6:
                 return (x>0);
             case 7:
                 return (x>0 && y>0);
         }
         return false;   //to make the compiler happy :-)
     } // isWithin

}