fitting a circle to a binary image

Here is a solution that tries to make an optimal circle fit via minimization. It soon becomes apparent that the bubble isn't a circle :) Note the use of "regionprops" for easily determining area, centroid, etc. of regions.

Circle fit to bubble

from skimage import io, color, measure, draw, img_as_bool
import numpy as np
from scipy import optimize
import matplotlib.pyplot as plt


image = img_as_bool(color.rgb2gray(io.imread('bubble.jpg')))
regions = measure.regionprops(image)
bubble = regions[0]

y0, x0 = bubble.centroid
r = bubble.major_axis_length / 2.

def cost(params):
    x0, y0, r = params
    coords = draw.circle(y0, x0, r, shape=image.shape)
    template = np.zeros_like(image)
    template[coords] = 1
    return -np.sum(template == image)

x0, y0, r = optimize.fmin(cost, (x0, y0, r))

import matplotlib.pyplot as plt

f, ax = plt.subplots()
circle = plt.Circle((x0, y0), r)
ax.imshow(image, cmap='gray', interpolation='nearest')
ax.add_artist(circle)
plt.show()

This should in general give very good and robust results:

import numpy as np
from skimage import measure, feature, io, color, draw

img = color.rgb2gray(io.imread("circle.jpg"))
img = feature.canny(img).astype(np.uint8)
img[img > 0] = 255

coords = np.column_stack(np.nonzero(img))

model, inliers = measure.ransac(coords, measure.CircleModel,
                                min_samples=3, residual_threshold=1,
                                max_trials=500)

print model.params

rr, cc = draw.circle(model.params[0], model.params[1], model.params[2],
                     shape=img.shape)

img[rr, cc] = 128

This is actually a mostly solved problem in image processing. Looks like what you want is a Hough Transform, specifically the circular or elliptical kind. I believe the circular one is a bit less computationally intensive in general.

Here are some code examples for scikit-image that show pretty much exactly what you're trying to do. And here is a link to the documentation.