Well, that picked my interest so I just spent a lunch break on it. Running the following using the process function attached (which uses FEX circfit):
process( 'WHL_20mm.PNG' ) ;
process( 'WHR_10mm_1.PNG' ) ;
I wrote the code too quickly but you should still see what I am doing based on the few comments.
Just a few explanations as I have 5 minutes free:
- For the inner rings (upper and lower), we use a convolution of the derivative along the y axis based on a square kernel. You can see this as a moving average in 2D that smooths things up.
- We split the image in two blocks based on the position of the largest positive derivative (going from dark (low values) to bright (high values) means positive derivative), analyzing the sum per row of the smoothed out derivative (which is more stable than the central vertical line that I used in the previous version). This assumes that the sleeve(?) is always brighter than the rest. We could find another approach if it's not the case.
- We then limit the analysis to the lower block that contains the inner rings.
- We find the red points by taking locations with the largest positive derivative derivatives given a factor for thresholding (e.g. 0.9 * max). We optimize this factor to have a large enough number of points and a minimal variance of their y coordinates.
- We find the blue points by taking locations with the largest negative derivative derivatives given a factor for thresholding (e.g. 0.9 * min). We optimize this factor to have a large enough number of points and a minimal variance of their y coordinates.
- We fit circles to these sets of points and compute the mean of their centers coordinates.
- For the outer ring we process the upper block now.
- Given the low contrast, we try to spot regions where there is the most important variation (positive or negative) in the derivative along the y axis.
- For this we perform a convolution of the absolute value of the derivative using a column vector kernel and we compute the max per column.
- Then we look for a "good" frame (delineated by vertical boundaries) and for points in each column whose values are above a given threshold (e.g. 0.9 * max per column).
- We find green points by optimizing three parameters which are the factor for thresholding and the frame boundaries, using an objective function that targets minimal variance of y coordinates while keeping enough points.
- Finally, as this set of points is not well suited for fitting a circle (x0,y0,r), we use the mean x0 and y0 defined by the red and blue circles, and we find an r that minimizes some objective function.
Note that it looks cool, but I know nothing about image processing, so if the purpose is to learn correct image processing you should really investigate the other solutions.