Measuring distance between two lines




I am new to ImageJ and am currently trying to use the macro functionnality to automaticaly detect the thickness of a plate measured under a microscope (=the thickness of the dark part).

I currently am following this to get the length:
-detect edges using canny Edge (using the function FeatureJ Edges). Filtering, Thresholding and Thinning of edges applied in this function
-Use hough transform to find the lines (function “Find Straight Lines” from Burger&Burge).
I end up with an ok solution as you can see here under (purple lines are detected edges) but I still have issues:

  • the edge on the left is seldom correctly detected: rather than finding the edge of the black part, it detects the edge of the gray part.
    -I am applying quite a high gauss filter and thresholding to remove all the unwanted edges that are found on the image usind Canny. I am unsure if this is not detrimental to the robustness of the method

My question would be if there is a better flow to measure the thickness of such a part? Thresholding before running edge detection for instance? Or is this the correct way to proceed and I need to find correct values for the smoothing filter and threshold values?

Any suggestion would be highly appreciated


Hi @jsq

And welcome to the forum!

I am not sure which edges you want to detect. I can distinguish the following different regions:

Are you looking for the left and right edge of the red, green, or blue region?

You could try a median filter, which is edge preserving.


Hello tibuch,

thanks for the answer. I will try the median filter right away. What I am looking for is the thickness of the black layer, it would be about the width of your blue square…


Good day Josquin,


is an estimate of the left boundary of the dark layer.

See the recent threads:




Hello Herbie,

thanks for the reply. It looks like this is the boundary I’m loking for. I guess that I could use the points you found to fit a line through it using hough transform or just get the pixel coordinates of these points. What I don’t understand is how you found the boundary? I couldn’t find your method in any of the posts. Can you help me out?


median filtering doesn’t solve the problem. It seems better than the gaussian filter I used, but it won’t help me detect the real boundary Im looking for. What I can find with Canny is the red edge in the image here under (median filtering was applied on the lower part). What i want is the blue edge. The problem is that the difference in contrast around the red edge will alway be higher than around the blue edge.
What I want in the end is the thickness of the blue part (=the length of the blue arrow). But currently my only difficulty is to find the blue edge.


Well Josquin,

in his thread Mark describes the approach in his first post and for a binary image/border gives a solution in this post: Accessible surface

My approach however works with the original image data, i.e. without thresholding. The code is experimental and not for distribution, but I’m sure you will find someone who is able to write the necessary code, or even better: Do it yourself.




Hi @jsq,

if you only need the thickness, why don’t you just plot a profile and determine the thickness as the distance between the two minima? A profile plot can be obtained by Edit/Selection/Select All and Analyze/Plot Profile. Estimating the thickness as the distance between the two minima would account, partially, for the edges not being perfectly vertical, but not for the edges not being parallel with respect to each other. The image show the position of the two minima detected. Writing a macro should be pretty straightforward.



here is an ImageJ macro that does what you want, provided that the borders are about vertical:

// ImageJ-macro start
selH = 8;
selH_h = round( 0.5 * selH );
run( "Median...", "radius=10" );
run( "Select All" );
p = getProfile();
p_min = Array.findMinima( p, 0 );
mi = p_min[0];
diffArray( p );
p = Array.findMaxima( p, 0 );
mx = p[0];
h = getHeight();
n = h - selH;
layW = newArray( n );
y = newArray( n );
for ( i = 0; i < n; i++ ) {
	makeRectangle( mi-5, i, mx+15-mi, selH );
	layW[i] = layerWidth();
	y[i] = i + selH_h;
run( "Select None" );
Plot.create( "Result", "y", "Thickness", y, layW );
Fit.doFit( "Straight Line", y, layW );
thickn = newArray( n );
for ( i = 0; i < n; i++ ) {
	thickn[i] = Fit.f(i);
Plot.setColor( "blue" );
Plot.add( "line", thickn );
Plot.setColor( "black" );
function diffArray( a ) {
    for ( i = 1; i < a.length; i++ ) {
        a[i-1] = a[i] - a[i-1];
    a[a.length-1] = 0;
function layerWidth() {
        p = getProfile();
        p_min = Array.findMinima( p, 0 );
        Array.sort( p_min );
        diffArray( p );
        p = Array.findMaxima( p, 0 );
        return ( p[0] - p_min[0] );
// macro end

(Paste the above macro code to an empty macro window (Plugins >> New >> Macro) and run it.)

The result shows the layer thickness as a function of the vertical coordinate (y = 4 to y = 1126) and a straight line fit in blue.




Hi Josquin,

Maybe you do not have to worry about the second line so much, since after Hough transform you get a function of the line (y = mx + c1, y = mx + c2) for each of the three parallel lines, using the found functions you can use the shortest distance between two parallel lines formula d = Math.abs(c1 - c2) / Math.sqrt(1 + m^2 ). The you need a macro to compute all the distances between all possible lines that you find and you make a list of distances, sort it and pick the second highest value which in a sorted list will the value at the second last index of the list. Would that solve your problem?




Thank you @gcardone for the method and thank you @Herbie for the implemented macro.
The macro works just fine and with some slight modifications I was able to automate on the whole bunch of pictures I have. I works better than going via Edge Detection and Hough Transform.