Difference between revisions of "Example Superpixels"

From BoofCV
m
m
 
(7 intermediate revisions by the same user not shown)
Line 10: Line 10:
  
 
Example Code:
 
Example Code:
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.17/examples/src/boofcv/examples/segmentation/ExampleImageSegmentation.java ExampleImageSegmentation.java]
+
* [https://github.com/lessthanoptimal/BoofCV/blob/v0.23/examples/src/boofcv/examples/segmentation/ExampleSegmentSuperpixels.java ExampleSegmentSuperpixels.java]
  
 
Concepts:
 
Concepts:
Line 16: Line 16:
 
* Super Pixels
 
* Super Pixels
  
Relevant Applets:
+
Related Examples:
* [[Applet Image Segmentation| Image Segmentation]]
+
* [[Example_Color_Segmentation| Color Segmentation]]
 +
* [[Example_Watershed_with_Seeds| Watershed with Seeds]]
 +
* [[Example_Thresholding| Thresholding]]
 +
* [[Tutorial_Image_Segmentation| Tutorial Image Segmentation]]
  
 
= Example Code =
 
= Example Code =
Line 24: Line 27:
 
/**
 
/**
 
  * Example demonstrating high level image segmentation interface.  An image segmented using this
 
  * Example demonstrating high level image segmentation interface.  An image segmented using this
  * interface will have each pixel assigned a unique label from 0 to N-1, where N is the number of regions.
+
  * interface will have each pixel assigned a unique label from 0 to N-1, where N is the number of regions.
 
  * All pixels which belong to the same region are connected.  These regions are also known as superpixels.
 
  * All pixels which belong to the same region are connected.  These regions are also known as superpixels.
 
  *
 
  *
 
  * @author Peter Abeles
 
  * @author Peter Abeles
 
  */
 
  */
public class ExampleImageSegmentation {
+
public class ExampleSegmentSuperpixels {
  
 
/**
 
/**
Line 35: Line 38:
 
*/
 
*/
 
public static <T extends ImageBase>
 
public static <T extends ImageBase>
void performSegmentation( ImageSegmentation<T> alg , T color )
+
void performSegmentation( ImageSuperpixels<T> alg , T color )
 
{
 
{
 
// Segmentation often works better after blurring the image.  Reduces high frequency image components which
 
// Segmentation often works better after blurring the image.  Reduces high frequency image components which
Line 43: Line 46:
 
// Storage for segmented image.  Each pixel will be assigned a label from 0 to N-1, where N is the number
 
// Storage for segmented image.  Each pixel will be assigned a label from 0 to N-1, where N is the number
 
// of segments in the image
 
// of segments in the image
ImageSInt32 pixelToSegment = new ImageSInt32(color.width,color.height);
+
GrayS32 pixelToSegment = new GrayS32(color.width,color.height);
  
 
// Segmentation magic happens here
 
// Segmentation magic happens here
Line 49: Line 52:
  
 
// Displays the results
 
// Displays the results
visualize(pixelToSegment,color,alg.getTotalSegments());
+
visualize(pixelToSegment,color,alg.getTotalSuperpixels());
 
}
 
}
  
Line 58: Line 61:
 
*/
 
*/
 
public static <T extends ImageBase>
 
public static <T extends ImageBase>
void visualize( ImageSInt32 pixelToRegion , T color , int numSegments  )
+
void visualize(GrayS32 pixelToRegion , T color , int numSegments  )
 
{
 
{
 
// Computes the mean color inside each region
 
// Computes the mean color inside each region
Line 80: Line 83:
 
// Make region edges appear red
 
// Make region edges appear red
 
BufferedImage outBorder = new BufferedImage(color.width,color.height,BufferedImage.TYPE_INT_RGB);
 
BufferedImage outBorder = new BufferedImage(color.width,color.height,BufferedImage.TYPE_INT_RGB);
ConvertBufferedImage.convertTo(color,outBorder,true);
+
ConvertBufferedImage.convertTo(color, outBorder, true);
 
VisualizeRegions.regionBorders(pixelToRegion,0xFF0000,outBorder);
 
VisualizeRegions.regionBorders(pixelToRegion,0xFF0000,outBorder);
  
 
// Show the visualization results
 
// Show the visualization results
ShowImages.showWindow(outSegments, "Regions");
+
ListDisplayPanel gui = new ListDisplayPanel();
ShowImages.showWindow(outBorder,"Region Borders");
+
gui.addImage(outColor,"Color of Segments");
ShowImages.showWindow(outColor,"Color of Segments");
+
gui.addImage(outBorder, "Region Borders");
 +
gui.addImage(outSegments, "Regions");
 +
ShowImages.showWindow(gui,"Superpixels", true);
 
}
 
}
  
 
public static void main(String[] args) {
 
public static void main(String[] args) {
BufferedImage image = UtilImageIO.loadImage("../data/applet/segment/berkeley_horses.jpg");
+
BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("segment/berkeley_horses.jpg"));
// BufferedImage image = UtilImageIO.loadImage("../data/applet/segment/berkeley_kangaroo.jpg");
+
// BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("segment/berkeley_kangaroo.jpg"));
// BufferedImage image = UtilImageIO.loadImage("../data/applet/segment/berkeley_man.jpg");
+
// BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("segment/berkeley_man.jpg"));
// BufferedImage image = UtilImageIO.loadImage("../data/applet/segment/mountain_pines_people.jpg");
+
// BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("segment/mountain_pines_people.jpg"));
// BufferedImage image = UtilImageIO.loadImage("../data/applet/particles01.jpg");
+
// BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("particles01.jpg"));
 +
 
 +
// you probably don't want to segment along the image's alpha channel and the code below assumes 3 channels
 +
image = ConvertBufferedImage.stripAlphaChannel(image);
  
 
// Select input image type.  Some algorithms behave different depending on image type
 
// Select input image type.  Some algorithms behave different depending on image type
ImageType<MultiSpectral<ImageFloat32>> imageType = ImageType.ms(3,ImageFloat32.class);
+
ImageType<Planar<GrayF32>> imageType = ImageType.pl(3, GrayF32.class);
// ImageType<MultiSpectral<ImageUInt8>> imageType = ImageType.ms(3,ImageUInt8.class);
+
// ImageType<Planar<GrayU8>> imageType = ImageType.pl(3,GrayU8.class);
// ImageType<ImageFloat32> imageType = ImageType.single(ImageFloat32.class);
+
// ImageType<GrayF32> imageType = ImageType.single(GrayF32.class);
// ImageType<ImageUInt8> imageType = ImageType.single(ImageUInt8.class);
+
// ImageType<GrayU8> imageType = ImageType.single(GrayU8.class);
  
// ImageSegmentation alg = FactoryImageSegmentation.meanShift(null, imageType);
+
// ImageSuperpixels alg = FactoryImageSegmentation.meanShift(null, imageType);
// ImageSegmentation alg = FactoryImageSegmentation.slic(new ConfigSlic(800), imageType);
+
// ImageSuperpixels alg = FactoryImageSegmentation.slic(new ConfigSlic(400), imageType);
ImageSegmentation alg = FactoryImageSegmentation.fh04(new ConfigFh04(100,30), imageType);
+
ImageSuperpixels alg = FactoryImageSegmentation.fh04(new ConfigFh04(100,30), imageType);
// ImageSegmentation alg = FactoryImageSegmentation.watershed(ConnectRule.EIGHT);
+
// ImageSuperpixels alg = FactoryImageSegmentation.watershed(null,imageType);
  
 
// Convert image into BoofCV format
 
// Convert image into BoofCV format

Latest revision as of 19:43, 7 December 2016

Image segmentation is an important (and very much unsolved) problem in computer vision. In this example, different techniques are used to break the image up into regions (or superpixels). The goal of this segmentation is to simplify the image's description, which can then be used for object detection/recognition.

Example Code:

Concepts:

  • Image Segmentation
  • Super Pixels

Related Examples:

Example Code

/**
 * Example demonstrating high level image segmentation interface.  An image segmented using this
 * interface will have each pixel assigned a unique label from 0 to N-1, where N is the number of regions.
 * All pixels which belong to the same region are connected.  These regions are also known as superpixels.
 *
 * @author Peter Abeles
 */
public class ExampleSegmentSuperpixels {

	/**
	 * Segments and visualizes the image
	 */
	public static <T extends ImageBase>
	void performSegmentation( ImageSuperpixels<T> alg , T color )
	{
		// Segmentation often works better after blurring the image.  Reduces high frequency image components which
		// can cause over segmentation
		GBlurImageOps.gaussian(color, color, 0.5, -1, null);

		// Storage for segmented image.  Each pixel will be assigned a label from 0 to N-1, where N is the number
		// of segments in the image
		GrayS32 pixelToSegment = new GrayS32(color.width,color.height);

		// Segmentation magic happens here
		alg.segment(color,pixelToSegment);

		// Displays the results
		visualize(pixelToSegment,color,alg.getTotalSuperpixels());
	}

	/**
	 * Visualizes results three ways.  1) Colorized segmented image where each region is given a random color.
	 * 2) Each pixel is assigned the mean color through out the region. 3) Black pixels represent the border
	 * between regions.
	 */
	public static <T extends ImageBase>
	void visualize(GrayS32 pixelToRegion , T color , int numSegments  )
	{
		// Computes the mean color inside each region
		ImageType<T> type = color.getImageType();
		ComputeRegionMeanColor<T> colorize = FactorySegmentationAlg.regionMeanColor(type);

		FastQueue<float[]> segmentColor = new ColorQueue_F32(type.getNumBands());
		segmentColor.resize(numSegments);

		GrowQueue_I32 regionMemberCount = new GrowQueue_I32();
		regionMemberCount.resize(numSegments);

		ImageSegmentationOps.countRegionPixels(pixelToRegion, numSegments, regionMemberCount.data);
		colorize.process(color,pixelToRegion,regionMemberCount,segmentColor);

		// Draw each region using their average color
		BufferedImage outColor = VisualizeRegions.regionsColor(pixelToRegion,segmentColor,null);
		// Draw each region by assigning it a random color
		BufferedImage outSegments = VisualizeRegions.regions(pixelToRegion, numSegments, null);

		// Make region edges appear red
		BufferedImage outBorder = new BufferedImage(color.width,color.height,BufferedImage.TYPE_INT_RGB);
		ConvertBufferedImage.convertTo(color, outBorder, true);
		VisualizeRegions.regionBorders(pixelToRegion,0xFF0000,outBorder);

		// Show the visualization results
		ListDisplayPanel gui = new ListDisplayPanel();
		gui.addImage(outColor,"Color of Segments");
		gui.addImage(outBorder, "Region Borders");
		gui.addImage(outSegments, "Regions");
		ShowImages.showWindow(gui,"Superpixels", true);
	}

	public static void main(String[] args) {
		BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("segment/berkeley_horses.jpg"));
//		BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("segment/berkeley_kangaroo.jpg"));
//		BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("segment/berkeley_man.jpg"));
//		BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("segment/mountain_pines_people.jpg"));
//		BufferedImage image = UtilImageIO.loadImage(UtilIO.pathExample("particles01.jpg"));

		// you probably don't want to segment along the image's alpha channel and the code below assumes 3 channels
		image = ConvertBufferedImage.stripAlphaChannel(image);

		// Select input image type.  Some algorithms behave different depending on image type
		ImageType<Planar<GrayF32>> imageType = ImageType.pl(3, GrayF32.class);
//		ImageType<Planar<GrayU8>> imageType = ImageType.pl(3,GrayU8.class);
//		ImageType<GrayF32> imageType = ImageType.single(GrayF32.class);
//		ImageType<GrayU8> imageType = ImageType.single(GrayU8.class);

//		ImageSuperpixels alg = FactoryImageSegmentation.meanShift(null, imageType);
//		ImageSuperpixels alg = FactoryImageSegmentation.slic(new ConfigSlic(400), imageType);
		ImageSuperpixels alg = FactoryImageSegmentation.fh04(new ConfigFh04(100,30), imageType);
//		ImageSuperpixels alg = FactoryImageSegmentation.watershed(null,imageType);

		// Convert image into BoofCV format
		ImageBase color = imageType.createImage(image.getWidth(),image.getHeight());
		ConvertBufferedImage.convertFrom(image, color, true);

		// Segment and display results
		performSegmentation(alg,color);
	}
}