How can I count the number of threads in a Nut with image processing?

I know that I need to find the place of threads and count them. Ok, But how can I find the place of threads?

This is a sample image:

An image from a Nut

Update As I know I need to do these steps:

  1. Making image ready. For example az @A_A sayed, with Thresholding
  2. Remove noise and just keep threads in the image
  3. Count threads. maybe using signal processing

Level 1 is solved. What should I do for 2 and 3?

For example this is what I did for a bolt. I got a sample of a vertical line in the middle of the nut then plotted the data. But I don't know how to remove additional parts and count up and downs.

enter image description here enter image description here


  • 1
    $\begingroup$ I am afraid that the way this question is posed, makes it too broad. The incredibly short answer is: The short answer is use thresholding. But I suspect that there are other parameters in the problem that would render this answer trivial. Therefore, would it be possible for you to write a bit more about the problem you are faced with? $\endgroup$ – A_A Dec 4 '18 at 9:45
  • $\begingroup$ Thanks. Thresholding is one of steps. I want to know how can I count these white areas by code? $\endgroup$ – rostamiani Dec 4 '18 at 10:11
  • $\begingroup$ well, you just actually write a loop that counts the plateaus that represent threads. $\endgroup$ – Marcus Müller Dec 4 '18 at 10:41

The most important thing in this problem is to be able to control the scene and more importantly:

  1. The lighting
  2. The camera position & angle

The Lighting: Simply put, the lighting is what creates the essential contrast to delineate the thread. If you light the thread "head on" (light from the viewpoint of the camera), there will be no contrast or "ups and downs" to count. The better position for the light is at the top and slightly forward of the face of the thread so that a) All thread peaks are lit (both those that are on the top, but also those that are below them) and b) The top thread casts a bit of shadow to the one below it. Try to think of the thread as a difraction grating, only here, you need the shadows.

The Camera: The camera distance from the thread and angle to the thread are very important, especially if you wish at some point to derive the pitch of the thread. To derive the pitch of the thread, you would have to count lines per unit of distance.

  1. The Camera Distance: The only way to relate the pixel size to a physical unit of length in a monocular image, is to fix the distance between the subject and the lens, similarly to how they do it in archaeology photography. There, we assume that the ruler's plain coincides with the focus plane of the lens, or is too near to be creating a negligible error.

  2. The Camera Angle: The camera angle is incredibly important in this problem because it is responsible for an optical distortion that would affect your measurement. In the nut example, it is impossible to image the thread vertically ("head on"), because you are trying to image the inside of a very small and thick cylinder. Therefore, you have to look at it from an angle. In the bolt example, it is impossible to image the thread vertically ("head on"), because there will be no shadows to create contrast. A pen, imaged at an angle will appear shorter than it really is. Similarly, the thread imaged at an angle, will not give you equidistant peaks. Specifically, as the thread "screws away" from the camera, its pitch will be increasing because the lines that denote the threads would appear to get closer and closer and closer. Therefore, the angle that the camera is set against the screw determines a) The error of measurement and b) the limits of measurement (how fine / coarse a thread you can measure).

AFTER determining / fixing these parameters which are very important to the problem you are dealing with, you can start thinking about extracting the thread. If you get the imaging conditions right, the thread extraction via image processing will be much more easier and straightforward than trying to do it over any random image.

Trivial way of extracting the thread:

Assuming that the thread is aligned and centred within the camera's Field Of View (FOV), you are using something like Octave and the image has been loaded in I with something like I = imread('someNutImage.jpg');:

  1. Threshold the image

enter image description here

  1. Because the thread is (supposedly) aligned with the FOV, take the middle column of values. That would look something like:

enter image description here

Notice here how the pitch changes visibly because of the camera angle.

  1. Now, "count" the gaps. This is a trivial "pulse counting" excercise which I have outlined previously. Prior to counting the pulse widths, you need an absolutely saturated signal. Therefore Q = double(I(:,320)>128).*255; (Where 320 is some column image, I am taking the middle here as explained above). Now, differentiate the signal to get the "pulse fronts" and then differentiate that again, to get the "inter-pulse-front" distances. That is:

    pulse_fronts = find(abs(diff(Q))); pulse_lengths = diff(pulse_fronts);

For the signal I am using here, I get:

1, 24, 64, 11, 8, 13, 6, 14, 6, 13, 6, 13, 6, 13, 5, 12, 6, 11, 5, 12, 5, 10, 6

That is, the signal starts with a spike pulse of length 1, followed by 24 zeroes followed by 11 ones, followed by 8 zeros, followed by 13 ones and so on.

Of course, you are not going to "count the gaps" manually. At this point, you can do a histogram and obtain the two most frequent values. For example, with a hist(pulseLength,max(pulseLength)), you get something like:

enter image description here

The "low" most frequent value (6) are the zeroes and the "high" most frequent value (13) are the ones. Once you have these two values (from the histogram), you know the full length of your thread in pixels. To convert it to mm, you need to determine the pixel size.

Less trivial way of extracting the thread:

The above method allows you to filter (if required) the pulse lengths to get rid of various artifacts. Another way to extract the thread would be to use the Discrete Fourier Transform of Q to assess the frequency of the pulse train.

For example: semilogy(abs(fft(Q))), gives you something like:

enter image description here

This image is 480 pixels tall. This means that the highest frequency (in terms of alternating black/white lines per unit of length) is 240. The first peak of the DFT occurs at 26 lines. From the method above we had ~13+~6=~19. The DFT will give you an average pitch over the whole acquired signal. Again, to give these numbers a physical meaning, you would need to know the pixel size which is only known by fixing the distance from the camera.

Even less trivial way of extracting the thread:

Once you threshold the image, either apply thining or a simple high-pass convolution mask to preserve the edges and then a Hough Transform. This will generate one "dot" for every slanted "line" that is created by the thread. What you would be looking for then would be a series of dots, one next to the other signifying the thread. By measuring the distance between these dots, you can extract your thread information. This is probably the most accurate method because the Hough Transform is very sensitive and accurate at recovering lines from very noisy images like the thresholded one we are talking about here. It is also the most computationally expensive option.

Each one of these methods has pros and cons for estimating the thread of a nut or bolt.

Finally, the most important part in such applications is to fix the imaging geometry so that you know what you measure and what sort of limits this measurement has.

Hope this helps.

  • $\begingroup$ Thanks a lot... I will test the method and will accept your answer soon $\endgroup$ – rostamiani Dec 5 '18 at 2:55
  • $\begingroup$ I really shocked. I didn't expect this much help. Thanks a lot. I read the link about pulse counting but could not find anything helpful there. whitch part is about counting? $\endgroup$ – rostamiani Dec 6 '18 at 4:38
  • $\begingroup$ @rostamiani I am glad that you are finding this helpful. I do not understand what you mean by '...not helpful'. The reason I linked the other answer is because it explains in more detail how the "pulse counting" works. The solution(s) above will give you estimates of the pitch with varying accuracy. They take you from image to a quantification of the thread width. What is the point that presents the highest difficulty? $\endgroup$ – A_A Dec 6 '18 at 12:14
  • $\begingroup$ That 'not helfull' was just a mistake. execuse me. I wanted to write:'I didn't find something'. (English is not my main language). The main problem is not the width, it's is the count of threads. because faulty bolts and nuts does not have enough threads. $\endgroup$ – rostamiani Dec 6 '18 at 12:57
  • 1
    $\begingroup$ @rostamiani No worries, I understand, I was more trying to understand what was the problem rather than calling you at for saying it was unhelpful. In this case, the first method (the most trivial) might involve a bit more work in detecting the total number of "threads". I would use the second method that calculates the DFT and then use the DFT spectrum as a "feature" in a very simple classifier that would classify "good" from "bad" bolts. Happy to elaborate further if you could post some examples of "good" and "bad" bolts you might be dealing with. $\endgroup$ – A_A Dec 6 '18 at 13:02

The images attached here has the necessary functions of opencv to solve the problem you have posed here. The logic is that, keeping a reference line(like the red line you have drawn in the image present in the question), count how many times the intensity of the image changes either from 255 to 0 or vice versa. Dividing this count value by 2 will yield you the exact number of threads.

(I know, pretty late. But hope it helps somebody)




Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.