Derive a smooth circle with cusp from an image

question 1 get the center

(sample data)

sample is the black circle with cusp.

 (*Input 1 ==< *)
sample = Binarize[Import["http://i.stack.imgur.com/z7isS.png"]]

(*Output CellExpression, You can copy to Notebook or just Skip*)
\!$$\*GraphicsBox[TagBox[RasterBox[CompressedData["1:eJztnc1u1DAUhR3Egh079jwKPEJ5glaCLVJBQn17mpnpNImPnTj+ude+51OpVI1jn/v5ZzLTqfj69Pvh1wfn3J9Pr98eHv99e35+fPnx8fWH7y9/fz7ND32enPvy+m9qhpuJPz65W7MFq8fHw+1ouT0cszKmmGm9YtbVX782Le+tt44Gw6/0bsUZtLLdGP7PsfaDSilhRSZ4VfatrMse3AraCrsFwotG8kMrK4pXM4QbWtlSN32vbirnXvbdh5ZG89jZZmqUtWMrFdP2Y6V5zi7UtM+o3YrgtCk2I7mYlVoRny2VB4x4JFrZC6DCiqI0iszoSbJ8eSSYRdHcvLF871MqgkIr0om0CXlHMhmtaBs7jlAyhQfKGpGAtKJiyFO0TUkrsmPl0i4qrYSH6UDJG7SCqJ3XdWuldv9dCblSOXWnVnY/65vdd4dOZuolp5VAv30qmerN6BhWSlcwhpXCvTa4Q6zK+41W0Sp6t1L8NVHPTz4LaAVSUkuHr3wClKyEVmr3JUuxSuo8n4lBK4gytQyl5Ep+RWMtlCvFrBRLpIH8mR7RSm5VI+6fmby6aKX81XrJqGuwG5U1p2ujlciFNTKp4JwYI1aSPq088vZ5I73C8Z3kWBnZS7IVA/sn/ZSwcKqctlI1kwbSvNBKpHXlTPLQCiLFihEl0+J3zwfuQOxYSXkNbNHKzmKxcaty5+BacWaO2gtHrVhycoFWEEdOFmtOjp2ktBJs0yyRBvatGBNygVYQe1bMbZ4btIKgFUR8D9FK6NHGgVSwb8WmmNiLRFrxirerZKIVDK0gaAVBKwGwF1qhFR9oJXp7ZwFkJXJvZ4SIFbFM8tAKglYQtIKgFUTQytCfrt3Dt8KVQisYWoGErJj24n+ciU5iVix74VrB0AqCVhDb5xxamUFWRAOpgFYQKyvcPjdoBUErCFpB0Apidc9PK3doBUErPjxXELSCoBUErSCcW3ihlRu0gqAVBM8VBK0gaAVDKwha8eEOQqysTHyP/wqtIGgFQSsIWkEgKxRDKwhaQdAKglYQWwu0MkMrCFpB0AoCWRGMowRaQXAHIWgFQSsIWvHxHdAKrWBoBQEc0Aq8Z6OVoBXTXmgFQSsIWvHB5Zu3El0rRr0EiqcVvFVM7yBaQcStWNWyY8WkFheunVZia8Wgl8iCiAgbnZiV2PYamWjVzupiiVdt7H86vLNXtc3VslewRSeHrVjycqhcWgk2ohXUyJKWg9Wa0nK4WFrJajgCqVZseKEVREqpVqykLQBayW/dK87Rio/jWgGkrhUbXtJrpJXoNdUyCXNy2mml4GW9cLI4WolcRivosjF/73x+ytNvcvoho7JhrWTVRSuVrtdIfk0Dni1FKhrTSpFOaAV1Qiuok3HEFKuEViIdjWClYB20Eu+tby/FZ5dWoh0W6k+ECidB916qFEArTbttQ7XsI1ip8mZrr2Iq5na0ItF7JarP5vszfkdeqkemlZ0hevHSJCytRIfpQEzbpLSyN2CT0U6wMtIqZVdWmqXsy4rIsO0GPUrqx4vLDaxZi5gVoa17ANlctHIkgMD4HioCqQixREUgFSGWiO8ebUGc05LET6Mlh7QVkEh4eAVCZqRTSY8fpkCyU9dux9XkhFYwtBIkJ2H6db4QfUZyU45q5crZrCnXgDH0CrlAK2FQ7kjylNZ9CrlAKyGwGa+GQLODSBSWxVkrSZ4kCsvirJU0JCrL5WSNAxuZqWml+7+zPjXzKW27hFZihJ5fpHPJkmFlXHXBexHpYIqgDIRuK/8B+/IYOQ=="], {{0, 271}, {278, 0}}, {0, 1},ColorFunction->GrayLevel],BoxFormImageTag["Bit", ColorSpace -> Automatic, Interleaving -> None],Selectable->False],BaseStyle->"ImageGraphics",ImageSizeRaw->{278, 271},PlotRange->{{0, 278}, {0, 271}}]$$

 (*Input 2 ==< *)
pts0 = PrincipalComponents@N@Position[ImageData[sample], 0];
{length = pts0 // Length,
radius = EuclideanDistance[#, {0, 0}] & /@ pts0 // Mean,
center = Mean@pts0 // N // Chop,
g1 = Graphics[{Point[pts0], {Red, Thick, circleNew = Circle[center, radius]}}]
}

Output result see picture ==> :)@@


I do not like this, I' d like the red circle overlap the black circle.

question 2 get the cusp.

Thought 1:

Put one locator in the cusp and drag it to along the diameter (from cusp point to center), and the circleNew will go to the center.

Maybe need interpolation, ie something BezierCurve or BSplineCurve..

Thought 2:

Go on ImageProcessing, directly make circleNew (smooth except the place of cusp) overlap the balck circle.

Maybe here we can directly Fit one curve with one function?

 (*Input 3 ==< *)
Pruning[Thinning[ColorNegate[Erosion[sample, 1]]]]

(*Output CellExpression, You can copy to Notebook or just Skip*)
\!$$\*GraphicsBox[TagBox[RasterBox[CompressedData["1:eJztnMtu00AYhWcQC3bs2PMo8AjlCVoJtkgFCfXtSVtTcjm2ZzyX/3Y+qRfXdnLOZ8/ISZp8fvh59+NdSunXh9O3u/s/Xx4f75++vT8tfH36/f3hedXHnNKn0xcxQH5DOokezl3Qy0LeXIxCvuJmvUQoAd76l00dZ7IczzT55peivRY1PrU0H22HWnqMAFejqOP1h5uLmREdjHsZdlztehl7qhsdSONDm9My50gam3unJrWhZfrhs3C6SERUr0UmoGYtgnOf3mlXOpb0/QM0HCsFES5RkkdJjAU1aRTNL2qCvKIijTInSYUWBRFuEM8kHgAifP7qlJJEveibUs4QyqbaSRLSotxJEkmoX8r8jNpHz8LUS10jTl6ZlNWUk1lWbDlJcwKbk8KXplYYHdqklNGpbUoZnNuqlKHJ7UoZmN2ylGHpbUuhFcyQ/NalDGlgX8qADh6kdG/hQ0rnHl6k9G1CK2NvSpp+VRxJ6VfGlZRedZxJ6VPInZQelRxKae/kUUp7K59WWms5tdLWy6uUpmZ+pTR08yzlcDvfUg728y7lWENa6bWPMeorBpBS3zGClPqWtNK+uVnqekaxUvmxQaNSaKOmaBgpNU3jSKnoGklKeVtaOb6ZF2gFUtQ3mpSyxvGsFFQOKGW/c0Qpu6VDStlrHVPKTu2gUrZ7R5VCK5it5nGtbFWnlep1vqEVCIcQZLV7ZCmr5UNLoRUIrUBW6ge3stI/uhUoILwUWoHQCgIYoBRagdAKglYQtIK4VUAptIK5cUApiVYwHEEIWkHQCoLzCoJWINcWaOWFvLEUF1pB5NWFyOSV32NDKwhaQdAKglYQtIKgFQStIGgFQSsIWkHQCoJWELSCoBUErSBoBUErCFpB0AqCVhB8jh9BKwhaQdAKgq+oImgFkTcXo0IrCFpB0AqA/wGGoBUErSBoBUErCFpB0AqCVhC0AuC7GwB8exCCVhC0AuA73xH89BUAFhBdC60gaAVBK4CV+rRS9fcY0AqCVhCr7UNroRXAendaqVvjn43ucbVsNQ9rZbN4VCvbvWnlyGqn7LYOqWW/dEAtBZXjWSlpHM5KWeFoWgr7xtJS2pZW2jb0AK0gystG0kIrgJqqcbRUNY2ipa4nrfTY3Cq0AqhuGUJLfckAWg5U9G/lUEPvWg72863laDta6bmfCY6X86yloZtfLS3NvFrJbcV8amlu5VFLh07+tHRp5E1Lpz7OtNAKoFsbV1r6lXGkpWMVP1a6NvGipXMPJ1p613ChpXsJD1YGdLCvZUgD61oG5betZVh6y1oGZrerZWhyo1oan5Dcv/2xNz+G8aENapkRefTZ2J1JeW1pmZbWkpaJWQ1pmRnVipbJk6ANLdNTWtAikFG9FplLCOVapOKp1iIXTq8W0QtwrVqEc2WNj4o0ZFIQ4RIdgXSdL4rCMAlESxgtORZUxFE0ehYUBFIQ4YYsOuvK3vs2YsHUGnlB4pBpPk3+w+e/MDOfQTYjZWJWQ06eOeQl58o5wpiUdOThUb74UXIPlXegg7pP8Xjbumw3o07SMiQKN73YreB2j2ZSQlH+q402S5s38kLem0XRyrXN7Z8ll6y2wSvyOanArVFWGpUU9ajjH+hYO65bwfWYkM6jCwohhATjL3IdCrM="], {{0, 271}, {278, 0}}, {0, 1},ColorFunction->GrayLevel],BoxFormImageTag["Bit", ColorSpace -> Automatic, Interleaving -> None],Selectable->False],BaseStyle->"ImageGraphics",ImageSizeRaw->{278, 271},PlotRange->{{0, 278}, {0, 271}}]$$


• Looks like this could help: mathematica.stackexchange.com/questions/27007/… Jun 14, 2013 at 13:44
• You have over 1000 reputation points. I think it's time that you take some time and learn how to properly format your code with markdown. Jun 14, 2013 at 13:53
• @m_goldberg ok, I'll read that. Jun 14, 2013 at 14:10
• I formatted your code once again. I hope you will study what I did and learn from it. The most important reworking was adding spaces and making line breaks in the proper places to improve the code's readability. Jun 14, 2013 at 14:18
• What's the {0,0}? Jun 14, 2013 at 16:00

i1 = ColorNegate@ Opening[Binarize@Import@"http://i.stack.imgur.com/3VEuj.jpg", 1];
ct = 1 /. ComponentMeasurements[FillingTransform@i1, "Centroid"];
r = Mean[EuclideanDistance[ct, #] & /@ PixelValuePositions[i1, 1]];
Show[i1, Graphics[{Thick, Red, Circle[ct, r]}]]


• Late to respond for struggling with so many questions. I like it. @@ any suggestion for question2 Jun 15, 2013 at 14:33
• @HyperGroups Re:your second question. The problem is that you're not imposing any constraints, so the "cusp" could be anything. You could propose a cusp "model", some constraints, anything to thin down the infinite possibilities Jun 15, 2013 at 14:39
• Ok, I'll edit after I've done some continued work. Jun 15, 2013 at 14:42

Since the binary image a little noisy, the easiest thing is to Dilate it a bit to make it one connected component.

img = Dilation[ColorNegate[Import["http://i.stack.imgur.com/z7isS.png"]], 1]


Now we can use ComponentMeasurements to find the desired properties:

ComponentMeasurements[img, {"Centroid", "EquivalentDiskRadius"}]

{1 -> {{139.859, 131.044}, 68.0123}}


So the center is about {139.859, 131.044} and the radius is 68.0123. Approaching it this way gives this circle:

Show[Import["http://i.stack.imgur.com/z7isS.png"],
Graphics[{Thick, Red, Circle[{139.859, 131.044}, 2 68.0123]}]]


• ha, nicie. I think put one slider in the cusp and drag to fit the whole circle is one way. And you can think my question 2 @@ Jun 14, 2013 at 14:09
• I might approach it this way: define an ideal version of the cusped circle. First, locate the best real circle like above to find the approximate center and radius. Then correlate your cusped circle with the image, once for each possible rotation. When you get the highest correlation, you will have the proper orientation of the cusped circle. Jun 14, 2013 at 14:57

Cusp detection using information from this post, and following the code from @belisarius' answer:

Transformation of the image to polar coordinates:

maxRadius = r + 10;
polar = ImageTransformation[i1,
ct + {Cos[#[[1]]], Sin[#[[1]]]}*#[[2]] &, {360, maxRadius},
DataRange -> Full,
PlotRange -> {{0, 360 \[Degree]}, {1, maxRadius}}]


result:

Then we find the position of the peak:

diff = Mean[Flatten[Position[#, 1]]] & /@
Transpose[ImageData[polar]];
cusp = Mean[Flatten[Position[diff, Max[diff]]]]


272

Display the detected cusp:

Show[i1, Graphics[{Thick, Red, Circle[ct, r], Green,