Difference between revisions of "Example Fit Ellipse"

From BoofCV
Jump to navigationJump to search
m
m
 
(5 intermediate revisions by the same user not shown)
Line 8: Line 8:


Example Code:
Example Code:
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.23/examples/src/boofcv/examples/features/ExampleFitEllipse.java ExampleFitEllipse.java]
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.40/examples/src/main/java/boofcv/examples/features/ExampleFitEllipse.java ExampleFitEllipse.java]


Concepts:
Concepts:
Line 14: Line 14:
* Best fit shape
* Best fit shape


Relevant Applets:
Relevant Examples:
* [[Applet Contour| Contour Detector]]
* [[Example_Binary_Image| Binary Image Processing]]
* [[Applet Shape Fitting| Shape Fitting]]
* [[Example_Fit_Polygon| Polygon Fitting]]


= Example Code =
= Example Code =
Line 27: Line 27:
  */
  */
public class ExampleFitEllipse {
public class ExampleFitEllipse {
 
public static void main( String[] args ) {
public static void main( String args[] ) {
// load and convert the image into a usable format
// load and convert the image into a usable format
BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("particles01.jpg"));
BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("particles01.jpg"));
GrayF32 input = ConvertBufferedImage.convertFromSingle(image, null, GrayF32.class);
GrayF32 input = ConvertBufferedImage.convertFromSingle(image, null, GrayF32.class);


GrayU8 binary = new GrayU8(input.width,input.height);
GrayU8 binary = new GrayU8(input.width, input.height);


// the mean pixel value is often a reasonable threshold when creating a binary image
// the mean pixel value is often a reasonable threshold when creating a binary image
Line 39: Line 38:


// create a binary image by thresholding
// create a binary image by thresholding
ThresholdImageOps.threshold(input, binary, (float) mean, true);
ThresholdImageOps.threshold(input, binary, (float)mean, true);


// reduce noise with some filtering
// reduce noise with some filtering
Line 45: Line 44:
filtered = BinaryImageOps.dilate8(filtered, 1, null);
filtered = BinaryImageOps.dilate8(filtered, 1, null);


// Find the contour around the shapes
// Find only external contours around each shape. Much faster than if internal + labeled images are considered.
List<Contour> contours = BinaryImageOps.contour(filtered, ConnectRule.EIGHT,null);
List<Contour> contours = BinaryImageOps.contourExternal(filtered, ConnectRule.EIGHT);


// Fit an ellipse to each external contour and draw the results
// Fit an ellipse to each external contour and draw the results
Line 53: Line 52:
g2.setColor(Color.RED);
g2.setColor(Color.RED);


for( Contour c : contours ) {
for (Contour c : contours) {
FitData<EllipseRotated_F64> ellipse = ShapeFittingOps.fitEllipse_I32(c.external,0,false,null);
FitData<EllipseRotated_F64> ellipse = ShapeFittingOps.fitEllipse_I32(c.external, 0, false, null);
VisualizeShapes.drawEllipse(ellipse.shape, g2);
VisualizeShapes.drawEllipse(ellipse.shape, g2);
}
}


// ShowImages.showWindow(VisualizeBinaryData.renderBinary(filtered, false, null),"Binary",true);
// ShowImages.showWindow(VisualizeBinaryData.renderBinary(filtered, false, null),"Binary",true);
ShowImages.showWindow(image,"Ellipses",true);
ShowImages.showWindow(image, "Ellipses", true);
}
}
}
}
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 13:02, 17 January 2022

Fitting ellipses to 2D objects found in images is a common task in industrial and scientific settings. In this example, binary blobs are found inside an image of particles and the best fit ellipses found. In a real application the next step could be to analyze the size distribution of the found ellipses to characterize the particles.

Example Code:

Concepts:

  • Object contours/edges
  • Best fit shape

Relevant Examples:

Example Code

/**
 * Demonstration which fits ellipses to object contours in a binary image.
 *
 * @author Peter Abeles
 */
public class ExampleFitEllipse {
	public static void main( String[] args ) {
		// load and convert the image into a usable format
		BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("particles01.jpg"));
		GrayF32 input = ConvertBufferedImage.convertFromSingle(image, null, GrayF32.class);

		GrayU8 binary = new GrayU8(input.width, input.height);

		// the mean pixel value is often a reasonable threshold when creating a binary image
		double mean = ImageStatistics.mean(input);

		// create a binary image by thresholding
		ThresholdImageOps.threshold(input, binary, (float)mean, true);

		// reduce noise with some filtering
		GrayU8 filtered = BinaryImageOps.erode8(binary, 1, null);
		filtered = BinaryImageOps.dilate8(filtered, 1, null);

		// Find only external contours around each shape. Much faster than if internal + labeled images are considered.
		List<Contour> contours = BinaryImageOps.contourExternal(filtered, ConnectRule.EIGHT);

		// Fit an ellipse to each external contour and draw the results
		Graphics2D g2 = image.createGraphics();
		g2.setStroke(new BasicStroke(3));
		g2.setColor(Color.RED);

		for (Contour c : contours) {
			FitData<EllipseRotated_F64> ellipse = ShapeFittingOps.fitEllipse_I32(c.external, 0, false, null);
			VisualizeShapes.drawEllipse(ellipse.shape, g2);
		}

//		ShowImages.showWindow(VisualizeBinaryData.renderBinary(filtered, false, null),"Binary",true);
		ShowImages.showWindow(image, "Ellipses", true);
	}
}