Advice on vertical edge detection on grayscale image with very weak contrast

2 views (last 30 days)
I’ve taken a large quantity of X-ray images of wooden samples and in order perform the analysis I’m trying to do I need to extract the individual yearly growth cycles from the wood by finding the column index of each latewood line (dark lines that can be seen in the attached image WoodXray.jpg) of each row.
So far I’ve tried applying a strong Gaussian blur to the image to remove noise and looping through the rows of the image one by one and identifying the points with the lowest values, which corresponds to a darker color in the image (see rowbyrowminima.jpg for an example of what I get from that). By viewing all the resulting rows from that as a vector I then get a pretty good estimation of where the boundary between early-wood/late-wood should be (see attached EdgeDetected.jpg to see what I get). I then get exactly what I want, the problem is that the outcome is rarely as good as on the image, very often the whole boundary detection collapses and the lines are fragmented all over the image. The method I am using is in other words very unrobust. I’ve also tried a bit with Sobel edge detection for vertical lines but I didn’t seem to have much more luck there.
Does anyone who work a lot with edge detection have any suggestions for how I could do this in a more robust or easier way? I suspect that it would be much more robust to have a detection method that already knows its looking for something that more or less is shaped like a line, right now I’m only detecting row by row and the next coming row does not consider at all the previous one.
Any advice?
I’ve also attached one of the images in matlab format if you would like to look at it yourself (XrayWoodenSample.mat).
Thanks

Accepted Answer

Image Analyst
Image Analyst on 20 Mar 2016
The results you showed looked pretty good so I don't see what's wrong. Please attach an image where the results are not so ideal.
I'm not sure what "the outcome is rarely as good as on the image" means. Please explain.
If you just don't like the image being so blurred, then display the lines over the original image, not the blurred image.
If you don't want huge blurring, make sure you're just blurring vertically and not horizontally. You could also take a look at some other denoising routines that are better, like medfilt2(), non-local means, k-SVD, UINTA, K-LLD, and BM3D (which is often regarded as the best).
To accentuate and find the ridge/valley lines, you could try anisotropic diffusion (my demo attached), or a Frangi or Hessian filter (see the File Exchange for submissions).
  2 Comments
Petter Stefansson
Petter Stefansson on 20 Mar 2016
Ok, I have now attached an example image showing how it can look when the detection goes wrong. It almost entirely misses one edge and also mixes up which column should be where. Sometimes it also detects a line twice as in the right part of the image.
The way I’m detecting this is that I for each row fit a linear regression line to the intensity curve and I then subtract the values of the regression line from my intensity data, which makes the curve more horizontal and centered around 0. I then draw a horizontal line at 0 and find each index of my data that intersects with the line. Between each pair of found intersections I then search for the lowest part which becomes my detection. See attached image for illustration. The problem is when the curve is too noisy and has many maximas crossing the horizontal line, for example in the image I attached if the curve around index 70 would be slightly higher it would change the detection. That is the reason why I think a method that from the start knows that it will be searching for a line instead of individual points would be better, it would be more immune towards local variations occurring on a few rows.
And to make matters worse I am measuring wood that has been exposed to weathering and some of the samples are quite degraded and have holes in them which really makes the detection difficult. But if those are too impossible I can discard them or manually set the edges.
Thank you for the filtering suggestions I will have a look at them now!
Image Analyst
Image Analyst on 20 Mar 2016
How many do you have? What's wrong with manually specifying all the lines with improfile()?
Do you know if all the lines are vertical? If so, just get the mean horizontal profile and use that to scan for minima
horizontalProfile = mean(grayImage, 1);
If that's the best line collection you can get (which I don't think it is), then you can do "edge linking". Get the coordinates of the lines and identify which lines are in the same "column" by using kmeans() (In the Statistics and Machine Learning Toolbox) to identify groupings of the "x" values. Then for all lines in a certain vertical band (identified from your x cluster means), use an edge linking routine to join the lines into a single big long line.
Attach the original image for not so good.jpg in case I ever get time to try anything.

Sign in to comment.

More Answers (0)

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!