/*
* 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.alg.segmentation.slic;
import boofcv.struct.ConnectRule;
import boofcv.struct.feature.ColorQueue_F32;
import boofcv.struct.image.GrayS32;
import boofcv.struct.image.GrayU8;
import boofcv.struct.image.ImageType;
import org.ddogleg.struct.FastQueue;
import org.ddogleg.struct.GrowQueue_I32;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Peter Abeles
*/
public class TestSegmentSlic {
@Test
public void initializeClusters() {
DummySlic alg = new DummySlic(4,1,10) {
@Override
protected void perturbCenter(Cluster c, int x, int y) {
c.x = x; c.y = y;
}
};
alg.input = new GrayU8(100,122);
alg.gridInterval = 10;
alg.clusters.resize(120);
alg.initializeClusters();
assertEquals(4,alg.clusters.get(0).x,1e-4);
assertEquals(2,alg.clusters.get(0).y,1e-4);
assertEquals(14,alg.clusters.get(1).x,1e-4);
assertEquals(2,alg.clusters.get(1).y,1e-4);
assertEquals(94,alg.clusters.get(9).x,1e-4);
assertEquals(2,alg.clusters.get(9).y,1e-4);
assertEquals(4,alg.clusters.get(10).x,1e-4);
assertEquals(12,alg.clusters.get(10).y,1e-4);
}
/**
* Makes sure bounds checking is properly done. places a cluster at each corner and sees if the pixels around
* the corner has that specific cluster
*/
@Test
public void computeClusterDistance() {
DummySlic alg = new DummySlic(4,1,10);
GrayU8 input = new GrayU8(7,9);
alg.initalize(input);
SegmentSlic.Cluster c0 = alg.clusters.grow();
SegmentSlic.Cluster c1 = alg.clusters.grow();
SegmentSlic.Cluster c2 = alg.clusters.grow();
SegmentSlic.Cluster c3 = alg.clusters.grow();
c0.x = 0; c0.y = 0;
c1.x = 6; c1.y = 0;
c2.x = 6; c2.y = 8;
c3.x = 0; c3.y = 8;
alg.gridInterval = 2;
alg.computeClusterDistance();
checkPixelContains(0,2,0,2,c0,alg);
checkPixelContains(5,7,0,2,c1,alg);
checkPixelContains(5,7,7,9,c2,alg);
checkPixelContains(0,2,7,9,c3,alg);
}
private void checkPixelContains( int x0 , int x1 , int y0 , int y1 ,
SegmentSlic.Cluster c ,
DummySlic alg ) {
for( int y = y0; y < y1; y++ ) {
for( int x = x0; x < x1; x++ ) {
int index = y*alg.input.width + x;
SegmentSlic.Pixel p = alg.pixels.get(index);
boolean contains = false;
for( int i = 0; i < p.clusters.size; i++ ) {
if( p.clusters.data[i].cluster == c )
contains = true;
}
assertTrue(contains);
}
}
}
@Test
public void updateClusters() {
DummySlic alg = new DummySlic(4,1,10);
SegmentSlic.Cluster c0 = alg.clusters.grow();
SegmentSlic.Cluster c1 = alg.clusters.grow();
SegmentSlic.Cluster c2 = alg.clusters.grow();
alg.pixels.resize(6);
alg.pixels.get(0).add(c0,2); // 0.666666
alg.pixels.get(0).add(c1,4); // 0.333333
alg.pixels.get(1).add(c1,1); // 0.75
alg.pixels.get(1).add(c0,3); // 0.25
for( int i = 2; i < 6; i++ ) {
alg.pixels.get(i).add(c2,0.2f);
}
alg.input = new GrayU8(2,3);
alg.updateClusters();
double w = (2.0/3.0) + 0.25;
assertEquals((0*0.666 + 1*0.25)/w,c0.x,1e-4);
assertEquals((0*0.666 + 0*0.25)/w,c0.y,1e-4);
w = (1.0/3.0) + 0.75;
assertEquals((0*0.333 + 1*0.75)/w,c1.x,1e-4);
assertEquals((0*0.333 + 0*0.75)/w,c1.y,1e-4);
assertEquals(0.5,c2.x,1e-4);
assertEquals(1.5,c2.y,1e-4);
}
@Test
public void assignLabelsToPixels() {
DummySlic alg = new DummySlic(4,1,10);
SegmentSlic.Cluster c0 = alg.clusters.grow();
SegmentSlic.Cluster c1 = alg.clusters.grow();
SegmentSlic.Cluster c2 = alg.clusters.grow();
c0.id = 0; c1.id = 1; c2.id = 2;
alg.pixels.resize(6);
alg.pixels.get(0).add(c0,2);
alg.pixels.get(0).add(c1,4);
alg.pixels.get(0).add(c2,0.1f);
alg.pixels.get(1).add(c1,1);
alg.pixels.get(1).add(c0,2);
for( int i = 2; i < 6; i++ ) {
alg.pixels.get(i).add(c1,0);
alg.pixels.get(i).add(c2,0.2f);
}
GrayS32 image = new GrayS32(2,3);
GrowQueue_I32 regionMemberCount = new GrowQueue_I32();
FastQueue<float[]> regionColor = new ColorQueue_F32(1);
alg.assignLabelsToPixels(image,regionMemberCount,regionColor);
assertEquals(3,regionMemberCount.size);
assertEquals(3,regionColor.size);
assertEquals(0,regionMemberCount.get(0));
assertEquals(5,regionMemberCount.get(1));
assertEquals(1,regionMemberCount.get(2));
assertEquals(2,image.get(0,0));
assertEquals(1,image.get(1,0));
for( int i = 2; i < 6; i++ ) {
assertEquals(1,image.data[i]);
}
}
@Test
public void Pixel_add()
{
SegmentSlic.Cluster c0 = new SegmentSlic.Cluster();
SegmentSlic.Cluster c1 = new SegmentSlic.Cluster();
SegmentSlic.Pixel p = new SegmentSlic.Pixel();
assertEquals(0,p.clusters.size);
p.add(c0, 2.2f);
assertEquals(1, p.clusters.size);
assertEquals(2.2f, p.clusters.data[0].distance, 1e-4f);
assertTrue(c0 == p.clusters.data[0].cluster);
p.add(c1, 1.2f);
assertEquals(2, p.clusters.size);
assertEquals(1.2f, p.clusters.data[1].distance, 1e-4f);
assertTrue(c1 == p.clusters.data[1].cluster);
}
@Test
public void Pixel_computeWeights() {
SegmentSlic.Pixel p = new SegmentSlic.Pixel();
p.clusters.grow().distance = 2;
p.clusters.grow().distance = 0.3f;
p.computeWeights();
assertEquals(1.0f - 2f/2.3f,p.clusters.data[0].distance,1e-4f);
assertEquals(1.0f - 0.3f/2.3f,p.clusters.data[1].distance,1e-4f);
// check special case of 1 item. The weight will be 1 since it is the only one
p.clusters.size = 1;
p.clusters.data[0].distance = 2;
p.computeWeights();
assertEquals(1.0f,p.clusters.data[0].distance,1e-4f);
}
@Test
public void Cluster_update() {
SegmentSlic.Cluster c = new SegmentSlic.Cluster();
float x = 6.1f;
float y = 7.5f;
c.totalWeight = 10.05f;
c.x = x*c.totalWeight;
c.y = y*c.totalWeight;
c.color = new float[]{1.2f,56.8f};
c.color[0] *= c.totalWeight;
c.color[1] *= c.totalWeight;
c.update();
assertEquals(x,c.x,1e-4f);
assertEquals(y,c.y,1e-4f);
assertEquals(1.2f,c.color[0],1e-4f);
assertEquals(56.8f,c.color[1],1e-4f);
}
public static class DummySlic extends SegmentSlic<GrayU8> {
public DummySlic(int numberOfRegions, float m, int totalIterations) {
super(numberOfRegions, m, totalIterations, ConnectRule.EIGHT, ImageType.single(GrayU8.class));
}
@Override
public void setColor(float[]color, int x, int y) {
}
@Override
public void addColor(float[]color, int index, float weight) {
}
@Override
public float colorDistance(float[] color, int index) {
return 0;
}
@Override
public float getIntensity(int x, int y) {
return 0;
}
}
}