Difference between revisions of "Example Detect Black Ellipses"

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


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


Concepts:
Concepts:
Line 11: Line 11:
* Fiducials
* Fiducials


Related Examples
Related Examples:
* [[Example_Detect_Black_Polygons|Black Polygons]]
* [[Example_Detect_Black_Polygons|Black Polygons]]
* [[Example_Detect_Calibration_Target| Calibration Target]]
* [[Example_Detect_Calibration_Target| Calibration Target]]
Videos:
* [https://youtu.be/qMTtdiujAtQ?t=513 Ellipse Detector]


= Example Code =
= Example Code =
Line 19: Line 22:
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
/**
/**
  * Example of how to detect black ellipses with a white background inside of images. These ellipses will have a
  * Example of how to detect black ellipses with a white background inside of images. These ellipses will have a
  * high level of accuracy and are used in camera calibration else where.
  * high level of accuracy and are used in camera calibration else where.
  *
  *
Line 25: Line 28:
  */
  */
public class ExampleDetectBlackEllipse {
public class ExampleDetectBlackEllipse {
public static void main(String[] args) {
public static void main( String[] args ) {
String images[] = new String[]{
String[] images = new String[]{
"shapes/polygons01.jpg",
"shapes/polygons01.jpg",
"shapes/shapes02.png",
"shapes/shapes02.png",
"fiducial/circle_asymmetric/image00.jpg",
"fiducial/circle_hexagonal/image00.jpg",
"fiducial/circle_asymmetric/image01.jpg"};
"fiducial/circle_hexagonal/image01.jpg"};


ListDisplayPanel panel = new ListDisplayPanel();
ListDisplayPanel panel = new ListDisplayPanel();
Line 36: Line 39:
BinaryEllipseDetector<GrayU8> detector = FactoryShapeDetector.ellipse(null, GrayU8.class);
BinaryEllipseDetector<GrayU8> detector = FactoryShapeDetector.ellipse(null, GrayU8.class);


for( String fileName : images ) {
for (String fileName : images) {
BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample(fileName));
BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample(fileName));


GrayU8 input = ConvertBufferedImage.convertFromSingle(image, null, GrayU8.class);
GrayU8 input = ConvertBufferedImage.convertFromSingle(image, null, GrayU8.class);
GrayU8 binary = new GrayU8(input.width,input.height);
GrayU8 binary = new GrayU8(input.width, input.height);


// Binarization is done outside to allows creative tricks. For example, when applied to a chessboard
// Binarization is done outside to allows creative tricks. For example, when applied to a chessboard
// pattern where square touch each other, the binary image is eroded first so that they don't touch.
// pattern where square touch each other, the binary image is eroded first so that they don't touch.
// The squares are expanded automatically during the subpixel optimization step.
// The squares are expanded automatically during the subpixel optimization step.
int threshold = GThresholdImageOps.computeOtsu(input, 0, 255);
int threshold = (int)GThresholdImageOps.computeOtsu(input, 0, 255);
ThresholdImageOps.threshold(input, binary, threshold, true);
ThresholdImageOps.threshold(input, binary, threshold, true);


Line 54: Line 57:


// visualize results by drawing red polygons
// visualize results by drawing red polygons
FastQueue<EllipseRotated_F64> found = detector.getFoundEllipses();
DogArray<BinaryEllipseDetector.EllipseInfo> found = detector.getFound();
Graphics2D g2 = image.createGraphics();
Graphics2D g2 = image.createGraphics();
g2.setStroke(new BasicStroke(3));
g2.setStroke(new BasicStroke(5));
g2.setColor(Color.RED);
g2.setColor(Color.RED);
for (int i = 0; i < found.size; i++) {
for (int i = 0; i < found.size; i++) {
VisualizeShapes.drawEllipse(found.get(i), g2);
VisualizeShapes.drawEllipse(found.get(i).ellipse, g2);
}
}


panel.addImage(image,new File(fileName).getName());
panel.addImage(image, new File(fileName).getName());
}
}


ShowImages.showWindow(panel,"Detected Ellipses",true);
ShowImages.showWindow(panel, "Detected Ellipses", true);
}
}
}
}
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 12:55, 17 January 2022

Red lines outline detected ellipses

BinaryEllipseDetector will detect ellipses inside an image which are black to a high level of precision quickly. Detection is done inside a binary image with subpixel refinement inside a gray scale image. These ellipses are used by ellipses based calibration targets

Example Code:

Concepts:

  • Ellipses
  • Fiducials

Related Examples:

Videos:

Example Code

/**
 * Example of how to detect black ellipses with a white background inside of images. These ellipses will have a
 * high level of accuracy and are used in camera calibration else where.
 *
 * @author Peter Abeles
 */
public class ExampleDetectBlackEllipse {
	public static void main( String[] args ) {
		String[] images = new String[]{
				"shapes/polygons01.jpg",
				"shapes/shapes02.png",
				"fiducial/circle_hexagonal/image00.jpg",
				"fiducial/circle_hexagonal/image01.jpg"};

		ListDisplayPanel panel = new ListDisplayPanel();

		BinaryEllipseDetector<GrayU8> detector = FactoryShapeDetector.ellipse(null, GrayU8.class);

		for (String fileName : images) {
			BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample(fileName));

			GrayU8 input = ConvertBufferedImage.convertFromSingle(image, null, GrayU8.class);
			GrayU8 binary = new GrayU8(input.width, input.height);

			// Binarization is done outside to allows creative tricks. For example, when applied to a chessboard
			// pattern where square touch each other, the binary image is eroded first so that they don't touch.
			// The squares are expanded automatically during the subpixel optimization step.
			int threshold = (int)GThresholdImageOps.computeOtsu(input, 0, 255);
			ThresholdImageOps.threshold(input, binary, threshold, true);

			// it takes in a grey scale image and binary image
			// the binary image is used to do a crude polygon fit, then the grey image is used to refine the lines
			// using a sub-pixel algorithm
			detector.process(input, binary);

			// visualize results by drawing red polygons
			DogArray<BinaryEllipseDetector.EllipseInfo> found = detector.getFound();
			Graphics2D g2 = image.createGraphics();
			g2.setStroke(new BasicStroke(5));
			g2.setColor(Color.RED);
			for (int i = 0; i < found.size; i++) {
				VisualizeShapes.drawEllipse(found.get(i).ellipse, g2);
			}

			panel.addImage(image, new File(fileName).getName());
		}

		ShowImages.showWindow(panel, "Detected Ellipses", true);
	}
}