public class Circle_Fitter extends Object implements ij.plugin.filter.PlugInFilter
The implementation largely follows http://www.dtcenter.org/met/users/docs/write_ups/circle_fit.pdf (It is summarized below.)
The major contributions of this plugin is that it does not take a list of points, but uses all pixel locations, weighted by intensity. The circle fitting works like this: given a set of points (x_i, y_i), i = 1, .., N try to fit a circle with radius r and center (x_c, y_c) using the least squares method. The function to minimize is
The derivative of S with regard to r^2 must be 0:
d/dr^2 \sum g_i^2 = \sum 2 * g_i * -1
and therefore
\sum g_i = 0
Expanded, with uu = \sum x_i * x_i, uv = \sum x_i * y_i and u, v, uu, uuu, uuv, uvv, vvv defined analogously, this yields
uu - 2 * u * x_c + N * x_c^2 + vv - 2 * v * y_c + N * y_c^2 - N * r^2 = 0
With u = v = 0, as per the earlier assumption, it follows that
uu + vv + N * (x_c^2 + y_c^2 - r^2) = 0 (eq. 1)
The derivative of S with regard to x_c must be 0:
d/dx_c \sum g_i^2 = \sum 2 * g_i * (2 * (x_i - x_c) * (-1)) = -4 * \sum g_i * x_i + 4 * x_c * \sum g_i
and therefore
\sum g_i * x_i = 0 (as \sum g_i must be 0 already)
Expanded, with uu and friends defined as before, this yields
uuu - 2 * uu * x_c + u * x_c^2 + uvv - 2 * uv * y_c + v * y_c^2 + u * r^2 = 0
Like before, u = v = 0, therefore
2 * uu * x_c + 2 * uv * y_c = uuu + uvv (eq. 2)
For y_c, it is
2 * uv * x_c + 2 * vv * y_c = uuv + vvv (eq. 3)
Equations 2 and 3 determine x_c and y_c, and equation 1 gives us the radius.
CONVERT_TO_FLOAT, DOES_16, DOES_32, DOES_8C, DOES_8G, DOES_ALL, DOES_RGB, DOES_STACKS, DONE, FINAL_PROCESSING, KEEP_THRESHOLD, NO_CHANGES, NO_IMAGE_REQUIRED, NO_UNDO, NO_UNDO_RESET, PARALLELIZE_IMAGES, PARALLELIZE_STACKS, ROI_REQUIRED, SNAPSHOT, STACK_REQUIRED, SUPPORTS_MASKING
Constructor and Description |
---|
Circle_Fitter() |
Modifier and Type | Method and Description |
---|---|
OvalRoi |
calculateRoi()
Computes and return the circle Roi that fits.
|
float |
getDefaultThreshold()
The default threshold is determined like this: as a circle is a linear
structure, we want the _square root_ of the total number of pixels to
contribute.
|
float |
getThreshold()
Returns threshold used by this plugin.
|
void |
run(ij.process.ImageProcessor ip) |
void |
setAutoThreshold()
Sets the threshold used by this plugin to be the default one.
|
void |
setImageProcessor(ij.process.ImageProcessor ip)
Set the ImageProcessor that will be fitted.
|
void |
setThreshold(float threshold)
Sets the threshold for the fit.
|
int |
setup(String arg,
ij.ImagePlus image) |
public int setup(String arg, ij.ImagePlus image)
setup
in interface ij.plugin.filter.PlugInFilter
public void run(ij.process.ImageProcessor ip)
run
in interface ij.plugin.filter.PlugInFilter
public OvalRoi calculateRoi()
public float getDefaultThreshold()
Therefore, we split the histogram into background and foreground where the number of pixels in the foreground part is \sqrt(w * h) and the split point is the desired threshold.
public float getThreshold()
public void setThreshold(float threshold)
threshold
- the threshold.public void setAutoThreshold()
getDefaultThreshold()
public void setImageProcessor(ij.process.ImageProcessor ip)
ip
- the ImageProcessorCopyright © 2015–2021 Fiji. All rights reserved.