Difference between revisions of "Example Morphological Thinning"

From BoofCV
Jump to navigationJump to search
(Created page with "<center> <gallery widths=240px heights=220px> File:Fingerprint.jpg | Input image of a finger print File:Thinned_binary.png | Binary image File:Thinned_thinned.png | Thinned im...")
 
m
 
(5 intermediate revisions by the same user not shown)
Line 1: Line 1:
<center>
<center>
<gallery widths=240px heights=220px>
<gallery widths=240px heights=220px>
File:Fingerprint.jpg | Input image of a finger print
File:Thinning_cartoon_face.png | Input image of a finger print
File:Thinned_binary.png | Binary image
File:Thinning_cartoon_face_binary.png | Binary image
File:Thinned_thinned.png | Thinned image
File:Thinning_cartoon_face_thinned.png | Thinned image
</gallery>
</gallery>
</center>
</center>
Line 10: Line 10:


Example Code:
Example Code:
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.19/examples/src/boofcv/examples/imageprocessing/ExampleMorphologicalThinning.java ExampleMorphologicalThinning.java]
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.40/examples/src/main/java/boofcv/examples/imageprocessing/ExampleMorphologicalThinning.java ExampleMorphologicalThinning.java]


Concepts:
Concepts:
Line 21: Line 21:
<syntaxhighlight lang="java">
<syntaxhighlight lang="java">
/**
/**
  * Simple example showing you how to thin a binary image. This is also known as skeletonalization. Thinning
  * Simple example showing you how to thin a binary image. This is also known as skeletonalization. Thinning
  * discards most of objects foreground (value one) pixels are leaves behind a "skinny" object which still
  * discards most of objects foreground (value one) pixels are leaves behind a "skinny" object which still
  * mostly describes the original objects shape.
  * mostly describes the original objects shape.
Line 28: Line 28:
  */
  */
public class ExampleMorphologicalThinning {
public class ExampleMorphologicalThinning {
public static void main(String[] args) {
public static void main( String[] args ) {
// load and convert the image into a usable format
String[] images = new String[]{"drawings/drawing_text.png", "standard/fingerprint.jpg", "drawings/drawing_face.png"};
BufferedImage image = UtilImageIO.loadImage("../data/applet/standard/fingerprint.jpg");


// convert into a usable format
ListDisplayPanel uberPanel = new ListDisplayPanel();
ImageFloat32 input = ConvertBufferedImage.convertFromSingle(image, null, ImageFloat32.class);
for (String path : images) {
ImageUInt8 binary = new ImageUInt8(input.width,input.height);
// load and convert the image into a usable format
BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample(path));


// Adaptive threshold to better handle changes in local image intensity
// convert into a usable format
GThresholdImageOps.adaptiveGaussian(input,binary,10,0,true,null,null);
GrayF32 input = ConvertBufferedImage.convertFromSingle(image, null, GrayF32.class);
var binary = new GrayU8(input.width, input.height);


// Tell it to thin the image until there are no more changes
// Fixed threshold is best for B&W images, but the adaptive would improve results for the finger print
ImageUInt8 thinned = BinaryImageOps.thin(binary, -1, null);
GThresholdImageOps.threshold(input, binary, 120, true);
// GThresholdImageOps.adaptiveSquare(input, binary, 20,0,true,null,null);


// display the results
// Tell it to thin the image until there are no more changes
BufferedImage visualBinary = VisualizeBinaryData.renderBinary(binary, false, null);
GrayU8 thinned = BinaryImageOps.thin(binary, -1, null);
BufferedImage visualThinned = VisualizeBinaryData.renderBinary(thinned, false, null);


ListDisplayPanel panel = new ListDisplayPanel();
// display the results
panel.addImage(visualThinned, "Thinned");
BufferedImage visualBinary = VisualizeBinaryData.renderBinary(binary, false, null);
panel.addImage(visualBinary, "Binary");
BufferedImage visualThinned = VisualizeBinaryData.renderBinary(thinned, false, null);
panel.addImage(image, "Original");


ShowImages.showWindow(panel,"Thinned/Skeletonalized Image", true);
var panel = new ListDisplayPanel();
panel.addImage(visualThinned, "Thinned");
panel.addImage(visualBinary, "Binary");
panel.addImage(image, "Original");
 
uberPanel.addItem(panel, new File(path).getName());
}
ShowImages.showWindow(uberPanel, "Thinned/Skeletonalized Images", true);
}
}
}
}
</syntaxhighlight>
</syntaxhighlight>

Latest revision as of 15:07, 17 January 2022

Example of how to thin a binary image. The thinned image (or skeleton) is a common preprocessing step in shape analysis.

Example Code:

Concepts:

  • Binary Processing
  • Shapes
  • Thinning

Example Code

/**
 * Simple example showing you how to thin a binary image. This is also known as skeletonalization. Thinning
 * discards most of objects foreground (value one) pixels are leaves behind a "skinny" object which still
 * mostly describes the original objects shape.
 *
 * @author Peter Abeles
 */
public class ExampleMorphologicalThinning {
	public static void main( String[] args ) {
		String[] images = new String[]{"drawings/drawing_text.png", "standard/fingerprint.jpg", "drawings/drawing_face.png"};

		ListDisplayPanel uberPanel = new ListDisplayPanel();
		for (String path : images) {
			// load and convert the image into a usable format
			BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample(path));

			// convert into a usable format
			GrayF32 input = ConvertBufferedImage.convertFromSingle(image, null, GrayF32.class);
			var binary = new GrayU8(input.width, input.height);

			// Fixed threshold is best for B&W images, but the adaptive would improve results for the finger print
			GThresholdImageOps.threshold(input, binary, 120, true);
//			GThresholdImageOps.adaptiveSquare(input, binary, 20,0,true,null,null);

			// Tell it to thin the image until there are no more changes
			GrayU8 thinned = BinaryImageOps.thin(binary, -1, null);

			// display the results
			BufferedImage visualBinary = VisualizeBinaryData.renderBinary(binary, false, null);
			BufferedImage visualThinned = VisualizeBinaryData.renderBinary(thinned, false, null);

			var panel = new ListDisplayPanel();
			panel.addImage(visualThinned, "Thinned");
			panel.addImage(visualBinary, "Binary");
			panel.addImage(image, "Original");

			uberPanel.addItem(panel, new File(path).getName());
		}
		ShowImages.showWindow(uberPanel, "Thinned/Skeletonalized Images", true);
	}
}