Ask Your Question

How to detect scratches in wood

asked 2014-01-27 13:58:23 -0600

selvaline gravatar image

updated 2020-10-23 08:40:41 -0600

Hi there! I try to explain my problem.. I've an image of wood beam where I've to identify the scratches and flaws contained in. I've attached a picture to describe my problem. I've to identify the scratches surrounded by squares. The rectangles in picture were added by hand, just to illustrate my purposes. Can you suggest me some algorithms, procedures or tricks that I can adopt for my goal? I'm new to the computer vision subject and I just know the basis of opencv, so I dunno what kind of algorithms are better for me.. Thank you for the patience and the suggestions! Nikolaj

image (1920x5000 - 923 KB)

EDIT by @sturkmen :

Note : please don't upload such a big file or give a link to image. i think there is some users have a limited internet access like me :)

edit retag flag offensive close merge delete

6 answers

Sort by » oldest newest most voted

answered 2014-01-28 02:17:49 -0600

Goosebumps gravatar image

updated 2014-01-28 02:18:44 -0600

You could use what I call an oriented high-pass filter (don't know the official name). I pasted the code below. It is in Emgu though (.Net wrapper for OpenCV). The basic idea is that you take a high pass filter kernel like:

k = [-1 -1 4 -1 -1
     -1 -1 4 -1 -1
     -1 -1 4 -1 -1
     -1 -1 4 -1 -1
     -1 -1 4 -1 -1
     -1 -1 4 -1 -1
     -1 -1 4 -1 -1
     -1 -1 4 -1 -1]

and convolve it with the image. Then rotate the kernel by N degrees (e.g. 15) and convolve it again. You do this up to 180 degrees and take the max of all the convoluted images. Scratches will have a high response to this kernel when aligned with the rotated filter. Your grains will too though. But you could experiment with leaving out the direction of the grains... BTW, smoothing the image beforehand gave me better results.

private Image<Gray, float> OrientedHighPass(Image<Gray, byte> image)
Image<Gray, float> filtered = new Image<Gray, float>(image.Size);
Image<Gray, float> final = new Image<Gray, float>(image.Size);

// import parameters
int smoothOpSize = 5;
int filterLength = 16;
int angleStep = 15;

// construct the kernel
float[,,] k3 = new float[1, 5, 1]
    { { -1 }, { -1 }, { 4 }, { -1 }, { -1 } },
Image<Gray, float> kRow = new Image<Gray, float>(k3);
Image<Gray, float> kImageOriginal = kRow;
for (int l = 0; l < filterLength - 1; ++l)
    kImageOriginal = kImageOriginal.ConcateVertical(kRow);

// first step, smooth image

for (int angle = 0; angle < 180; angle += angleStep)
    // Create convolution kernel
    Image<Gray, float> kImage = kImageOriginal.Rotate(angle, new Gray(0), false);
            // make sure the average of the kernel stays zero
    kImage = kImage - (kImage.GetSum().Intensity / (kImage.Width * kImage.Height));

    float[,] k = new float[kImage.Height, kImage.Width];
    Buffer.BlockCopy(kImage.Data, 0, k, 0, k.Length * sizeof(float));
    ConvolutionKernelF kernel = new ConvolutionKernelF(k);

    filtered = image.Convolution(kernel);

    final = filtered.Max(final);

return final;
edit flag offensive delete link more


It could be interesting! I can't use Emgu but I understand what you mean! By the way I am not sure this filter can work for me. It empathize white that has a walk like the filter's line of 4s.. But if the analyzed white pixel has another white near it, with the subtraction it will disappear.. I believe it can work by using different set of values but it's difficult to find a filter that works on every picture

selvaline gravatar imageselvaline ( 2014-01-29 11:17:40 -0600 )edit

answered 2014-01-28 03:46:38 -0600

Ben gravatar image

Seems like the scratches are a lot lighter than the wood. Maybe you could use a simple gray level threshold() or adaptiveThreshold() to detect candidate regions. Then you could try HoughLinesP() to detect lines in the resulting binary image.

edit flag offensive delete link more


Yes with a simple threshold I can preprocess the image removing the major part of grains, however I have to use another method then, because there are some grains too bright..For what concerns Hough Transform I dunno how the result will be: grains have a line walk too.. But I'll try it to see! Thank you Ben!

selvaline gravatar imageselvaline ( 2014-01-29 11:08:16 -0600 )edit

answered 2014-01-30 12:31:07 -0600

keghn gravatar image

updated 2014-01-30 12:32:46 -0600

selvaline said:

Thank you for the reply Keghn. Has this solution got a name or it's a filtering technique invented by you? It's a kind of mean-filtering without the division by the number of box's pixels, or am I wrong? selvaline (Jan 28 '14)

I do allot of research in this area and developed this process in the year of 2013 and have not coined a name for it yet.

edit flag offensive delete link more


Please don't create an answer to the thread topic when it is just an a response to a question in a comment.

Ben gravatar imageBen ( 2014-01-31 03:35:34 -0600 )edit

answered 2020-09-15 23:41:18 -0600

RobBW gravatar image

Check out these notes I made recently about the "Phase Only Transform"

To test the algorithm presented in the article "The Phase Only Transform for unsupervised surface defect detection", Aiger & Talbot 2010. use this code:

Aiger & Talbots work is extended in 2014 by: ’Saliency-Based Defect Detection in Industrial Images by Using Phase Spectrum’

edit flag offensive delete link more

answered 2014-01-28 18:32:47 -0600

keghn gravatar image

Hello selvaline.

I am using support vector machines classes:

I am classifying data by the texture in the box as a class and when the texture changes it will be seen as another class.

If you want to, the distance between each of the class you but a dot on another empty image. it should build up an out line of all the shades and objects, and then get the length of the line for matching to other captured out lines.

The add up in the box was to lower the resolution of the texture for pattern capture.

I am new to OpenCV and do not know all the trick they have to offer yet.

But I am glad their are other help you.



edit flag offensive delete link more

answered 2014-01-27 15:23:21 -0600

keghn gravatar image


Assuming that this image is 1000x1000 pixels and is

using gray scale or black and white, and is one channel.

Have a box scan the image. Say 10 pixel by 10 pixels. All of the pixel values, inside the box are added up into a box value and saved with location x, y.

Comparing the box value with one another for the one that has the lowest box value, assuming that the scratches will be lighter and will cause a lower box value.

The box size may be too big or small and my need to adjusted, too small it will pick up the grains, too big it will pick up the glare. You might have to do the the scan up and down and left to right.

You can move the box one pixel at time for accuracy or 10 pixels for fast scan.

Lots of luck,


edit flag offensive delete link more


Thank you for the reply Keghn. Has this solution got a name or it's a filtering technique invented by you? It's a kind of mean-filtering without the division by the number of box's pixels, or am I wrong?

selvaline gravatar imageselvaline ( 2014-01-28 02:12:26 -0600 )edit

Looks like convolution with a square kernel or 2D moving average filtering if you want some google keywords. This is a low pass filtering technique. Since the kernel is square it will act differently depending on the orientation of your scratch. You might also consider a circular or gaussian kernel if this is your way to go (personally, I do not think so).

Goosebumps gravatar imageGoosebumps ( 2014-01-31 01:32:27 -0600 )edit

Thank you Goosebumps Sure any info wold be great.

keghn gravatar imagekeghn ( 2014-02-02 16:23:39 -0600 )edit

Any luck so far?

Goosebumps gravatar imageGoosebumps ( 2014-02-13 06:07:48 -0600 )edit

Question Tools

1 follower


Asked: 2014-01-27 13:58:23 -0600

Seen: 4,126 times

Last updated: Sep 15 '20