(ImagePlus imp)
| 145 | Authors: Nikolai Chernov, Michael Doube, Ved Sharma |
| 146 | */ |
| 147 | void fitCircle(ImagePlus imp) { |
| 148 | if (!imp.okToDeleteRoi()) return; |
| 149 | Roi roi = imp.getRoi(); |
| 150 | if (roi==null) { |
| 151 | noRoi("Fit Circle"); |
| 152 | return; |
| 153 | } |
| 154 | |
| 155 | if (roi.isArea()) { //create circle with the same area and centroid |
| 156 | Undo.setup(Undo.ROI, imp); |
| 157 | ImageProcessor ip = imp.getProcessor(); |
| 158 | ip.setRoi(roi); |
| 159 | ImageStatistics stats = ImageStatistics.getStatistics(ip, Measurements.AREA+Measurements.CENTROID, null); |
| 160 | double r = Math.sqrt(stats.pixelCount/Math.PI); |
| 161 | imp.deleteRoi(); |
| 162 | int d = (int)Math.round(2.0*r); |
| 163 | Roi roi2 = new OvalRoi((int)Math.round(stats.xCentroid-r), (int)Math.round(stats.yCentroid-r), d, d); |
| 164 | transferProperties(roi, roi2); |
| 165 | imp.setRoi(roi2); |
| 166 | return; |
| 167 | } |
| 168 | |
| 169 | Polygon poly = roi.getPolygon(); |
| 170 | int n=poly.npoints; |
| 171 | int[] x = poly.xpoints; |
| 172 | int[] y = poly.ypoints; |
| 173 | if (n<3) { |
| 174 | IJ.error("Fit Circle", "At least 3 points are required to fit a circle."); |
| 175 | return; |
| 176 | } |
| 177 | |
| 178 | // calculate point centroid |
| 179 | double sumx = 0, sumy = 0; |
| 180 | for (int i=0; i<n; i++) { |
| 181 | sumx = sumx + poly.xpoints[i]; |
| 182 | sumy = sumy + poly.ypoints[i]; |
| 183 | } |
| 184 | double meanx = sumx/n; |
| 185 | double meany = sumy/n; |
| 186 | |
| 187 | // calculate moments |
| 188 | double[] X = new double[n], Y = new double[n]; |
| 189 | double Mxx=0, Myy=0, Mxy=0, Mxz=0, Myz=0, Mzz=0; |
| 190 | for (int i=0; i<n; i++) { |
| 191 | X[i] = x[i] - meanx; |
| 192 | Y[i] = y[i] - meany; |
| 193 | double Zi = X[i]*X[i] + Y[i]*Y[i]; |
| 194 | Mxy = Mxy + X[i]*Y[i]; |
| 195 | Mxx = Mxx + X[i]*X[i]; |
| 196 | Myy = Myy + Y[i]*Y[i]; |
| 197 | Mxz = Mxz + X[i]*Zi; |
| 198 | Myz = Myz + Y[i]*Zi; |
| 199 | Mzz = Mzz + Zi*Zi; |
| 200 | } |
| 201 | Mxx = Mxx/n; |
| 202 | Myy = Myy/n; |
| 203 | Mxy = Mxy/n; |
| 204 | Mxz = Mxz/n; |
no test coverage detected