Difference between revisions of "Example Superpixels"
From BoofCV
Jump to navigationJump to searchm |
m |
||
(9 intermediate revisions by the same user not shown) | |||
Line 7: | Line 7: | ||
</center> | </center> | ||
Image segmentation is an important (and very much unsolved) problem in computer vision. | 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: | Example Code: | ||
* [https://github.com/lessthanoptimal/BoofCV/blob/v0. | * [https://github.com/lessthanoptimal/BoofCV/blob/v0.40/examples/src/main/java/boofcv/examples/segmentation/ExampleSegmentSuperpixels.java ExampleSegmentSuperpixels.java] | ||
Concepts: | Concepts: | ||
Line 19: | Line 19: | ||
* [[Example_Color_Segmentation| Color Segmentation]] | * [[Example_Color_Segmentation| Color Segmentation]] | ||
* [[Example_Watershed_with_Seeds| Watershed with Seeds]] | * [[Example_Watershed_with_Seeds| Watershed with Seeds]] | ||
* [[Example_Thresholding| Thresholding]] | |||
* [[Tutorial_Image_Segmentation| Tutorial Image Segmentation]] | |||
* [[ | |||
= Example Code = | = Example Code = | ||
Line 27: | Line 26: | ||
<syntaxhighlight lang="java"> | <syntaxhighlight lang="java"> | ||
/** | /** | ||
* Example demonstrating high level image segmentation interface. | * 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. | * 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 | public class ExampleSegmentSuperpixels { | ||
/** | /** | ||
* Segments and visualizes the image | * Segments and visualizes the image | ||
*/ | */ | ||
public static <T extends ImageBase> | public static <T extends ImageBase<T>> | ||
void performSegmentation( | 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. | |||
// can cause over segmentation | // can cause over segmentation | ||
GBlurImageOps.gaussian(color, color, 0.5, -1, null); | GBlurImageOps.gaussian(color, color, 0.5, -1, null); | ||
// Storage for segmented image. | // 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 | ||
var pixelToSegment = new GrayS32(color.width, color.height); | |||
// Segmentation magic happens here | // Segmentation magic happens here | ||
alg.segment(color,pixelToSegment); | alg.segment(color, pixelToSegment); | ||
// Displays the results | // Displays the results | ||
visualize(pixelToSegment,color,alg. | visualize(pixelToSegment, color, alg.getTotalSuperpixels()); | ||
} | } | ||
/** | /** | ||
* Visualizes results three ways. | * 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 | * 2) Each pixel is assigned the mean color through out the region. 3) Black pixels represent the border | ||
* between regions. | * between regions. | ||
*/ | */ | ||
public static <T extends ImageBase> | public static <T extends ImageBase<T>> | ||
void visualize( | void visualize( GrayS32 pixelToRegion, T color, int numSegments ) { | ||
// Computes the mean color inside each region | // Computes the mean color inside each region | ||
ImageType<T> type = color.getImageType(); | ImageType<T> type = color.getImageType(); | ||
ComputeRegionMeanColor<T> colorize = FactorySegmentationAlg.regionMeanColor(type); | ComputeRegionMeanColor<T> colorize = FactorySegmentationAlg.regionMeanColor(type); | ||
var segmentColor = new ColorQueue_F32(type.getNumBands()); | |||
segmentColor.resize(numSegments); | segmentColor.resize(numSegments); | ||
var regionMemberCount = new DogArray_I32(); | |||
regionMemberCount.resize(numSegments); | regionMemberCount.resize(numSegments); | ||
ImageSegmentationOps.countRegionPixels(pixelToRegion, numSegments, regionMemberCount.data); | ImageSegmentationOps.countRegionPixels(pixelToRegion, numSegments, regionMemberCount.data); | ||
colorize.process(color,pixelToRegion,regionMemberCount,segmentColor); | colorize.process(color, pixelToRegion, regionMemberCount, segmentColor); | ||
// Draw each region using their average color | // Draw each region using their average color | ||
BufferedImage outColor = VisualizeRegions.regionsColor(pixelToRegion,segmentColor,null); | BufferedImage outColor = VisualizeRegions.regionsColor(pixelToRegion, segmentColor, null); | ||
// Draw each region by assigning it a random color | // Draw each region by assigning it a random color | ||
BufferedImage outSegments = VisualizeRegions.regions(pixelToRegion, numSegments, null); | BufferedImage outSegments = VisualizeRegions.regions(pixelToRegion, numSegments, null); | ||
// Make region edges appear red | // Make region edges appear red | ||
var 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 | ||
var gui = new ListDisplayPanel(); | |||
gui.addImage(outColor, "Color of Segments"); | |||
ShowImages.showWindow( | 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. | BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("segment/berkeley_horses.jpg")); | ||
// BufferedImage image = UtilImageIO. | // BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("segment/berkeley_kangaroo.jpg")); | ||
// BufferedImage image = UtilImageIO. | // BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("segment/berkeley_man.jpg")); | ||
// BufferedImage image = UtilImageIO. | // BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("segment/mountain_pines_people.jpg")); | ||
// BufferedImage image = UtilImageIO. | // BufferedImage image = UtilImageIO.loadImageNotNull(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. | // Select input image type. Some algorithms behave different depending on image type | ||
ImageType< | ImageType<Planar<GrayF32>> imageType = ImageType.pl(3, GrayF32.class); | ||
// ImageType< | // ImageType<Planar<GrayU8>> imageType = ImageType.pl(3, GrayU8.class); | ||
// ImageType< | // ImageType<GrayF32> imageType = ImageType.single(GrayF32.class); | ||
// ImageType< | // 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 | // Convert image into BoofCV format | ||
ImageBase color = imageType.createImage(image.getWidth(),image.getHeight()); | ImageBase color = imageType.createImage(image.getWidth(), image.getHeight()); | ||
ConvertBufferedImage.convertFrom(image, color, true); | ConvertBufferedImage.convertFrom(image, color, true); | ||
// Segment and display results | // Segment and display results | ||
performSegmentation(alg,color); | performSegmentation(alg, color); | ||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> |
Latest revision as of 15:26, 17 January 2022
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<T>>
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
var 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<T>>
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);
var segmentColor = new ColorQueue_F32(type.getNumBands());
segmentColor.resize(numSegments);
var regionMemberCount = new DogArray_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
var 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
var 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.loadImageNotNull(UtilIO.pathExample("segment/berkeley_horses.jpg"));
// BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("segment/berkeley_kangaroo.jpg"));
// BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("segment/berkeley_man.jpg"));
// BufferedImage image = UtilImageIO.loadImageNotNull(UtilIO.pathExample("segment/mountain_pines_people.jpg"));
// BufferedImage image = UtilImageIO.loadImageNotNull(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);
}
}