Chapter 01-4: Edge Detection with multiple straight lines selections


Chapter 01-4 descripes a way to detect a edge with multiple lines. This is a more accurate method to detect the corner of a given object. The method is to spread a certain amount of searchlines along the edge of an object and to compute several cornerpoints. Once you have detected a certain amount of edge points you will make a best fit of a straight line inbetween the given points. In this chapter you will use the roiManager to store the lines. At this point you should know the basic handling with the roiManager in imagej.  RoiManager OnlineHelp
This method is limited also to horizontal straight line selections.

Step 01: The start-up image

Chapter01-4_step01.jpg


The first step is to open an image and select the straight line tool.  Draw a horizontal line (press the shift key while dragging the mouse). It is necessary to start from the left side drawing to the right side with the search direction from the bright side to the dark side, otherwise the macro will not work correctly. After the line is created press the t-key on your keypad and the roiManager window pops up.  Now the straight line roi is stored in the roiManager and can be used later on.

Step 02: Adding additional search lines to the roiManager

chapter01-4_step02.png


Adding additional lines to the manager. Basically you could draw every line new and add it to the roiManager like in step 01. But a faster way is to grab the line, move it to the next spot and press the t-key. The only thing you have to look for is not to get mixed up with the number of the line and the position in the row. The first line has to be the first line in the row, the second has to be the second and so on...If you mix up the position of the line the fitting of the detected edge line will not work correctly. You can add as many lines as you wish. The only limit is the array buffer in imagej. To detect a corner very precisely usually you don' t need more than 10-20 search lines. There are a lot  of things you can do with the rois in the roiManager. It is worth to have a look in the official imagej dokumentation. Now everything is set to run the macro.

Step 03: Compute the corner points and fit a straight line

Some simple code sample for the imagej macro language. Just copy the code into a new imagej text window and run the macro.


/***********************************************************************************************************************/
/*   This macro detects the corner of a bright to dark edge and draws a straight line selection at the          */
/*    detected edge.                                                                                                                                                 */
/***********************************************************************************************************************/
/* Step 01: check for minimum 2 straight line selections in the roiManager                                                     */

count = roiManager("count")
if (count<2) exit("Error: minimum 2 straight line selections are required");
for(i=0; i<count; i++)
    {
    roiManager("select", i);
    getSelectionCoordinates(x,y);
    //print(selectionType(),"    ",y[0],y[1], count);
    if((y[0]!=y[1])&&(x[0]!=x[1])) exit("Error: horizontal or vertical straight line selections required");
    if(selectionType()!=5) exit("Error: horizontal straight line selections required");
    }

/***********************************************************************************************************************/
/* Step 02: Declarations                                                                                                                                         */

function cornerdetect(Pixel_I);

x1 = 0;
y1 = 0;
number_lines = roiManager("count");                           // saves the number of the straight line selections in the roiManager
array_cornerpointsX = newArray(number_lines);        // variable for the x-values of the detected cornerpoints
array_cornerpointsY = newArray(number_lines);        // varialble for the y-values of the detected cornerpoints
bild = getImageID();

/***********************************************************************************************************************/
/**************************************** M A I N **********************************************************************/
/***********************************************************************************************************************/

for(i=0; i<number_lines;i++)
    {  
    selectImage(bild);                      
    roiManager("select",i);                          
    getLine(x1,y1,x2,y2, width);
    profile_line = getProfile();

// horizontal selections
if (y1 == y2)    {
        corner_Pt_x = cornerdetect(profile_line);
        corner_Pt_x += x1;
        array_cornerpointsX[i] = corner_Pt_x;
        array_cornerpointsY[i] = y1;
        print( "roiManager Line Number",i);
        print( "x-Coordinate edgepoint:   ",    corner_Pt_x);
        print( "y-Coordinate edgepoint:   ", y1);
        }

// vertical selections

    if (x1 == x2)    {
            corner_Pt_y = cornerdetect(profile_line);
            corner_Pt_y += y1;
            array_cornerpointsX[i] = x1;
            array_cornerpointsY[i] = corner_Pt_y;
    print("roiManager Line Number:   ", i);
            print( "x-Coordinate edgepoint:   ", x1);
            print( "y-Coordinate edgepoint:   ", corner_Pt_y);
            }

}
doLineFit("Straight Line", array_cornerpointsX, array_cornerpointsY, number_lines); // function for the line fitting


/***********************************************************************************************************************/
/************************************** S U B R O U T I N E S ******************************************************/
/***********************************************************************************************************************/
/***************************** 01 Subfunction: Detect Cornerpoint ************************************************/

function cornerdetect(Pixels_I)                // argument is the values of the profile_line array
{
    maxvalue = 0;
    pos_maxvalue = 0;
    array_getcornerpoint = newArray(Pixels_I.length);

    for(i=0; i<Pixels_I.length-1; i++)
            {
            array_getcornerpoint[i] = Pixels_I[i] - Pixels_I[i+1];
            if(array_getcornerpoint[i]>maxvalue)
                    {
                    maxvalue = array_getcornerpoint[i];
                    pos_maxvalue = i;
                    }
          
            }
    print("Value of maxvalue  =  ",maxvalue);
    return pos_maxvalue;
}
/***********************************************************************************************************************/

/******************************** 02 Subfunction: Do Line Fit ******************************************************/

function doLineFit(equation, array_ptx, array_pty, nLines)

    {
    Fit.doFit(equation, array_ptx, array_pty);
    ArrayNr = nLines -1;
    Fit.logResults
    y_Wert1 = Fit.f(array_ptx[0]);
    y_Wert2 = Fit.f(array_ptx[ArrayNr]);
    print("y_Wert2:   ",y_Wert2);
    print("x_Wert2:   ", array_ptx[ArrayNr]);
    print("y_Wert1:   ", y_Wert1);
    makeLine(array_ptx[0], y_Wert1, array_ptx[ArrayNr], y_Wert2);
    updateDisplay();
    }
/***********************************************************************************************************************/


/***********************************************************************************************************************/
/********************************************* E N D  M A C R O  ***************************************************/
/***********************************************************************************************************************/




Step 04: Enjoy the results


So this is the result line. You have to play around to get an idea what sort of edges can be detected. This is a very simple routine which could be enhanced whith filter techniques or better search algorithms. If you want to detect dark to bright edges as well, you  just have to invert the image, process the cornerdetect funktion and invert the image again. Later on I'm gonna spend time to on this subject as well. But for now I'll try to keep the programms short, clear and comprehendible.