/*
* Copyright (c) 2011-2016, Peter Abeles. All Rights Reserved.
*
* This file is part of BoofCV (http://boofcv.org).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package boofcv.examples.segmentation;
import boofcv.abst.segmentation.ImageSuperpixels;
import boofcv.alg.filter.blur.GBlurImageOps;
import boofcv.alg.segmentation.ComputeRegionMeanColor;
import boofcv.alg.segmentation.ImageSegmentationOps;
import boofcv.factory.segmentation.ConfigFh04;
import boofcv.factory.segmentation.FactoryImageSegmentation;
import boofcv.factory.segmentation.FactorySegmentationAlg;
import boofcv.gui.ListDisplayPanel;
import boofcv.gui.feature.VisualizeRegions;
import boofcv.gui.image.ShowImages;
import boofcv.io.UtilIO;
import boofcv.io.image.ConvertBufferedImage;
import boofcv.io.image.UtilImageIO;
import boofcv.struct.feature.ColorQueue_F32;
import boofcv.struct.image.*;
import org.ddogleg.struct.FastQueue;
import org.ddogleg.struct.GrowQueue_I32;
import java.awt.image.BufferedImage;
/**
* 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);
}
}