/*
* Copyright 2010, 2011 Institut Pasteur.
*
* This file is part of NHerve Main Toolbox, which is an ICY plugin.
*
* NHerve Main Toolbox is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* NHerve Main Toolbox is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with NHerve Main Toolbox. If not, see <http://www.gnu.org/licenses/>.
*/
package plugins.nherve.toolbox.image.segmentation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import plugins.nherve.toolbox.image.DifferentColorsMap;
import plugins.nherve.toolbox.image.feature.DefaultClusteringAlgorithmImpl;
import plugins.nherve.toolbox.image.feature.Segmentable;
import plugins.nherve.toolbox.image.feature.SegmentationAlgorithm;
import plugins.nherve.toolbox.image.feature.Signature;
import plugins.nherve.toolbox.image.feature.IcySupportRegion;
import plugins.nherve.toolbox.image.feature.IcySupportRegionFactory;
import plugins.nherve.toolbox.image.feature.clustering.ClusteringException;
import plugins.nherve.toolbox.image.feature.descriptor.DefaultDescriptorImpl;
import plugins.nherve.toolbox.image.feature.descriptor.MultiThreadedSignatureExtractor;
import plugins.nherve.toolbox.image.feature.region.IcyPixel;
import plugins.nherve.toolbox.image.feature.region.SupportRegionException;
import plugins.nherve.toolbox.image.feature.signature.BagOfSignatures;
import plugins.nherve.toolbox.image.feature.signature.SignatureException;
import plugins.nherve.toolbox.image.feature.signature.DefaultVectorSignature;
import plugins.nherve.toolbox.image.mask.Mask;
import plugins.nherve.toolbox.image.mask.MaskException;
/**
* The Class DefaultSegmentationAlgorithm.
*
* @param <T>
* the generic type
* @author Nicolas HERVE - nicolas.herve@pasteur.fr
*/
public class DefaultSegmentationAlgorithm<T extends Segmentable> extends SegmentationAlgorithm<T> {
/** The clustering. */
private DefaultClusteringAlgorithmImpl<DefaultVectorSignature> clustering;
/** The descriptor. */
private DefaultDescriptorImpl<T, ? extends Signature> descriptor;
/** The factory. */
private IcySupportRegionFactory factory;
/**
* Instantiates a new default segmentation algorithm.
*
* @param descriptor
* the descriptor
* @param factory
* the factory
* @param clustering
* the clustering
*/
public DefaultSegmentationAlgorithm(DefaultDescriptorImpl<T, ? extends Signature> descriptor, IcySupportRegionFactory factory, DefaultClusteringAlgorithmImpl<DefaultVectorSignature> clustering) {
super();
this.descriptor = descriptor;
this.clustering = clustering;
this.factory = factory;
}
/**
* Instantiates a new default segmentation algorithm.
*
* @param descriptor
* the descriptor
* @param clustering
* the clustering
*/
public DefaultSegmentationAlgorithm(DefaultDescriptorImpl<T, ? extends Signature> descriptor, DefaultClusteringAlgorithmImpl<DefaultVectorSignature> clustering) {
this(descriptor, null, clustering);
}
/**
* Instantiates a new default segmentation algorithm.
*
* @param clustering
* the clustering
*/
public DefaultSegmentationAlgorithm(DefaultClusteringAlgorithmImpl<DefaultVectorSignature> clustering) {
this(null, null, clustering);
}
/**
* Creates the segmentation.
*
* @param w
* the w
* @param h
* the h
* @param c
* the c
* @param regions
* the regions
* @param affectation
* the affectation
* @return the segmentation
* @throws MaskException
* the mask exception
*/
private Segmentation createSegmentation(int w, int h, int c, IcySupportRegion[] regions, int[] affectation) throws MaskException {
Segmentation seg = new Segmentation(w, h);
DifferentColorsMap colorMap = new DifferentColorsMap(c, 1);
for (int m = 0; m < c; m++) {
seg.createNewMask("Segment " + m, true, colorMap.get(m), 1.0f);
}
int p = 0;
for (IcySupportRegion sr : regions) {
Mask mask = seg.getByIndex(affectation[p]);
IcyPixel px = sr.getCenter();
mask.getBinaryData().set((int)px.x, (int)px.y, true);
p++;
}
return seg;
}
/* (non-Javadoc)
* @see plugins.nherve.toolbox.image.feature.SegmentationAlgorithm#segment(plugins.nherve.toolbox.image.feature.Segmentable)
*/
@Override
public Segmentation segment(T img) throws SegmentationException {
if (factory == null) {
throw new SegmentationException("DefaultSegmentationAlgorithm : SupportRegionFactory not initialized");
}
try {
factory.setLogEnabled(isLogEnabled());
List<IcySupportRegion> regions = factory.extractRegions(img);
IcySupportRegion[] aRegions = (IcySupportRegion[])regions.toArray(new IcySupportRegion[regions.size()]);
return segment(img, aRegions);
} catch (SupportRegionException e) {
throw new SegmentationException(e);
}
}
/**
* Segment.
*
* @param img
* the img
* @param regions
* the regions
* @return the segmentation
* @throws SegmentationException
* the segmentation exception
*/
@SuppressWarnings("unchecked")
public Segmentation segment(T img, IcySupportRegion[] regions) throws SegmentationException {
if (descriptor == null) {
throw new SegmentationException("DefaultSegmentationAlgorithm : Descriptor not initialized");
}
try {
descriptor.setLogEnabled(isLogEnabled());
MultiThreadedSignatureExtractor<T> mex = new MultiThreadedSignatureExtractor<T>(descriptor);
mex.setLogEnabled(isLogEnabled());
Signature[] sigs = mex.extractSignatures(img, regions);
if (sigs.length > 0) {
if (sigs[0] instanceof DefaultVectorSignature) {
DefaultVectorSignature[] vs = new DefaultVectorSignature[sigs.length];
for (int i = 0; i < sigs.length; i++) {
vs[i] = (DefaultVectorSignature)sigs[i];
}
return segment(img, regions, vs);
} else if (sigs[0] instanceof BagOfSignatures<?>) {
BagOfSignatures<DefaultVectorSignature>[] bs = new BagOfSignatures[sigs.length];
for (int i = 0; i < sigs.length; i++) {
bs[i] = (BagOfSignatures<DefaultVectorSignature>)sigs[i];
}
return segmentBag(img, regions, bs);
}
}
return null;
} catch (SignatureException e) {
throw new SegmentationException(e);
}
}
/**
* Segment.
*
* @param img
* the img
* @param regions
* the regions
* @param sigs
* the sigs
* @return the segmentation
* @throws SegmentationException
* the segmentation exception
*/
public Segmentation segment(T img, IcySupportRegion[] regions, DefaultVectorSignature[] sigs) throws SegmentationException {
if (clustering == null) {
throw new SegmentationException("DefaultSegmentationAlgorithm : ClusteringAlgorithm not initialized");
}
try {
clustering.setLogEnabled(isLogEnabled());
clustering.compute(sigs);
List<DefaultVectorSignature> centroids = clustering.getCentroids();
int[] affectation = clustering.getAffectations(sigs);
return createSegmentation(img.getWidth(), img.getHeight(), centroids.size(), regions, affectation);
} catch (ClusteringException e) {
throw new SegmentationException(e);
} catch (MaskException e) {
throw new SegmentationException(e);
}
}
/**
* Segment using previous quantization.
*
* @param img
* the img
* @param regions
* the regions
* @param sigs
* the sigs
* @return the segmentation
* @throws SegmentationException
* the segmentation exception
*/
public Segmentation segmentUsingPreviousQuantization(T img, IcySupportRegion[] regions, DefaultVectorSignature[] sigs) throws SegmentationException {
if (clustering == null) {
throw new SegmentationException("DefaultSegmentationAlgorithm : ClusteringAlgorithm not initialized");
}
try {
List<DefaultVectorSignature> centroids = clustering.getCentroids();
int[] affectation = clustering.getAffectations(sigs);
return createSegmentation(img.getWidth(), img.getHeight(), centroids.size(), regions, affectation);
} catch (ClusteringException e) {
throw new SegmentationException(e);
} catch (MaskException e) {
throw new SegmentationException(e);
}
}
/**
* Segment bag.
*
* @param img
* the img
* @param regions
* the regions
* @param sigs
* the sigs
* @return the segmentation
* @throws SegmentationException
* the segmentation exception
*/
public Segmentation segmentBag(T img, IcySupportRegion[] regions, BagOfSignatures<DefaultVectorSignature>[] sigs) throws SegmentationException {
if (clustering == null) {
throw new SegmentationException("DefaultSegmentationAlgorithm : ClusteringAlgorithm not initialized");
}
try {
clustering.setLogEnabled(isLogEnabled());
List<DefaultVectorSignature> lsigs = new ArrayList<DefaultVectorSignature>();
for (int i = 0; i < sigs.length; i++) {
for (DefaultVectorSignature vs : sigs[i]) {
lsigs.add(vs);
}
}
clustering.compute(lsigs);
List<DefaultVectorSignature> centroids = clustering.getCentroids();
int[] affectation = clustering.getAffectations(lsigs);
Segmentation seg = new Segmentation(img.getWidth(), img.getHeight());
DifferentColorsMap colorMap = new DifferentColorsMap(centroids.size(), 1);
for (int m = 0; m < centroids.size(); m++) {
seg.createNewMask("Segment " + m, true, colorMap.get(m), 1.0f);
}
int a = 0;
for (int r = 0; r < sigs.length; r++) {
HashMap<Integer, Integer> count = new HashMap<Integer, Integer>();
for (DefaultVectorSignature vs : sigs[r]) {
int aff = affectation[a++];
if (count.containsKey(aff)) {
count.put(aff, count.get(aff) + 1);
} else {
count.put(aff, 1);
}
}
int max = 0;
int affect = 0;
for (int c : count.keySet()) {
if (count.get(c) > max) {
affect = c;
max = count.get(c);
}
}
Mask mask = seg.getByIndex(affect);
IcyPixel px = regions[r].getCenter();
mask.getBinaryData().set((int)px.x, (int)px.y, true);
}
return seg;
} catch (ClusteringException e) {
throw new SegmentationException(e);
} catch (MaskException e) {
throw new SegmentationException(e);
}
}
}