Let me give you my general solution for the scientific image processing. The most important is to try to use less subjective parameters, like a threshold value. First, let's assume that the image is taken from charge-coupled device (CCD) or CMOS matrix. These detectors are widely used in most of the modern digital electronics: photo camera, scanner etc.
Second, plot the image histogram.
im = Import["image.png"]
imdata = ImageData[im];
data = Flatten[ImageData[im]];
SmoothHistogram[data, PlotRange -> All]
You can see that the histogram looks like combination of two Gaussian PDF. It has Gaussian shape due to the photon-shot noise. Because the number of photon counts is finite. In general, the noise has Poisson distribution, but for the large number of photon counts Poisson PDF can be approached by Gaussian. Also from the image histogram, you can see that Gaussian curves are very close to each others, and the image has low contrast. To increase the contrast, you have to separate distributions.
Let's find distributions property. It can be done by various ways, but I use Expectation-Maximization algorithm for Gaussian Mixture Models. I gave the example of the algorithm for other question. The results of the algorithm you can find at the image below. Please note, it is important to choose the the starting point as better as you can, otherwise it may converge to single Gaussian only.
The result of the algorithm, where the red curve shows the recovered distribution, where two Gaussian functions where used.
And the left Gaussian has mean value
μ1 = 0.588906
and the right
μ2 = 0.623881
Let's define linear mapping to increase the contrast.
df[gl_] := If[gl < μ2, (gl - μ2)/(μ1 - μ2), 0];
For the left maximum it gives 1 and for the right 0. Now let's map the initial image to the high-contrast image.
{nRow, nCol} = Dimensions[imdata]
imdf = Table[df[imdata[[i]][[j]]], {i, 1, nRow}, {j, 1, nCol}];
And plot.
Image[imdf]
As you can see, the spot and other features have higher contrast now.
Now, you perform the simple threshold-based segmentation, where the threshold value is between pikes 0.5.
segment =
Table[If[imdf[[i]][[j]] > 0.5, 1, 0], {i, 1, nRow}, {j, 1, nCol}];
binary = Image[segment]
Delete small and border components
binnew = DeleteSmallComponents[DeleteBorderComponents[binary], 100]
And find your centroid
ComponentMeasurements[binnew, "IntensityCentroid"]
{1 -> {77.2571, 397.8}}
UPDATE:
Actually, Otsu's algorithm gives similar result directly for the low-contrast image. As far as I see, the idea behind the Otsu's algorithm is similar to what I write here. But now it is clear how to extend the segmentation to arbitrary number of Gaussian.
Segmentation with Otsu's algorithm of the low-contrast image.
ColorNegate[Binarize[im]]
MedianFilter[i, 10]
, and thenImageSubtract
it from the original image. $\endgroup$LocalAdaptiveBinarize[ColorNegate@img, 20, {.6, 0, .2}]
gives me a good result. $\endgroup$