9
$\begingroup$

so I found a program in the answers to this question that I thought was brilliant, so here it is applied to my situation: I have the image enter image description here and here's the code:

img=https://i.stack.imgur.com/MRlBH.png;
img = GaussianFilter[i, 2]

squaredError = 1/2 ({cx - x, cy - y}.{-gy, gx})^2;

errDerivative = Expand[D[squaredError, {{cx, cy}}]];
linearSystem = {{D[errDerivative, cx],


D[errDerivative, cy]}, -errDerivative /. {cx -> 0, cy -> 0}}

gradientX = ImageData@GaussianFilter[img, 1, {0, 1}];
gradientY = ImageData@GaussianFilter[img, 1, {1, 0}];
xArr = Array[N[#2] &, Dimensions[gradientX]];
yArr = Array[N[#1] &, Dimensions[gradientX]];
ls = Total[
linearSystem /. {gx -> gradientX, gy -> gradientY, x -> xArr, y -> `yArr},{-2, -1}];`
center = LinearSolve @@ ls;


center[[1]] -= 1;
center[[2]] = Length[gradientX] - center[[2]];

maxRadius = 400;
polar = ImageTransformation[img, 
  center + {Cos[#[[1]]], Sin[#[[1]]]}*#[[2]] &, {360, maxRadius}, 
  DataRange -> Full, 
  PlotRange -> {{0 \[Degree], 360 \[Degree]}, {1, maxRadius}}]

enter image description here

radiusStrength = Mean /@ ImageData[polar, DataReversed -> True];
peakX = Position[
    MapThread[#1 > #2 && #1 > #3 &, {radiusStrength, 
      RotateLeft[radiusStrength], RotateRight[radiusStrength]}], 
    True][[All, 1]];
peaks = SortBy[Transpose[{peakX, radiusStrength[[peakX]]}], Last];
ListLinePlot[radiusStrength, PlotRange -> .8, 
 Epilog -> {Red, Point[peaks[[-6 ;;]]]}]

enter image description here

Show[img, 
 Graphics[{Red, Dashed, Circle[center, #] & /@ peaks[[-8 ;;, 1]]}]]

enter image description here


Fantastic, exactly what I want this code to do for this image. If I crop the image so I only have the top half of the circles it still works great. However, when I try out this image, it shits the bed: enter image description here This is the final output enter image description here

Do you guys have any suggestions for a more robust algorithm to find the centre?

$\endgroup$
  • $\begingroup$ @nikie as the creator for the code I'm using, do you have any ideas for this? $\endgroup$ – Mason Nov 9 '16 at 21:27
  • 2
    $\begingroup$ I suggest increasing the kernel size in the calculation of gradientX and gradientY (e.g. from 1 to 10) and also increase maxRadius to ~650 $\endgroup$ – Simon Woods Nov 9 '16 at 22:10
  • $\begingroup$ Worked like a charm! Thanks. $\endgroup$ – Mason Nov 9 '16 at 22:49