/*
* 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.tracker.meanshift;
import boofcv.alg.interpolate.InterpolatePixelMB;
import boofcv.alg.interpolate.InterpolatePixelS;
import boofcv.alg.misc.GImageMiscOps;
import boofcv.core.image.border.BorderType;
import boofcv.factory.interpolate.FactoryInterpolation;
import boofcv.struct.RectangleRotate_F32;
import boofcv.struct.image.GrayF32;
import boofcv.struct.image.Planar;
import org.ddogleg.util.UtilDouble;
import org.junit.Test;
import java.util.Random;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @author Peter Abeles
*/
public class TestTrackerMeanShiftComaniciu2003 {
Random rand = new Random(234);
@Test
public void track() {
InterpolatePixelS interpSB = FactoryInterpolation.bilinearPixelS(GrayF32.class, BorderType.EXTENDED);
InterpolatePixelMB interpolate = FactoryInterpolation.createPixelPL(interpSB);
LocalWeightedHistogramRotRect calcHistogram = new LocalWeightedHistogramRotRect(30,3,10,3,255,interpolate);
TrackerMeanShiftComaniciu2003 alg = new TrackerMeanShiftComaniciu2003(false,100,1e-8f,0.0f,0.0f,0.1f,calcHistogram);
Planar<GrayF32> image = new Planar<>(GrayF32.class,100,150,3);
// odd width and height so samples land on pixels
render(image,50,40,21,31);
RectangleRotate_F32 found = new RectangleRotate_F32(50,40,21,31,0);
alg.initialize(image,found);
// test no change
alg.track(image);
check(alg.getRegion(),50,40,21,31,0);
// test translation
render(image,55,34,21,31);
alg.track(image);
check(alg.getRegion(),55,34,21,31,0);
// test scale
render(image,55,34,23,34);
alg.track(image);
assertEquals(alg.getRegion().cx,55,1f);
assertEquals(alg.getRegion().cy,34,1f);
assertEquals(alg.getRegion().width,23,1);
assertEquals(alg.getRegion().height,34,1);
}
@Test
public void updateLocation() {
InterpolatePixelS interpSB = FactoryInterpolation.bilinearPixelS(GrayF32.class, BorderType.EXTENDED);
InterpolatePixelMB interpolate = FactoryInterpolation.createPixelPL(interpSB);
LocalWeightedHistogramRotRect calcHistogram = new LocalWeightedHistogramRotRect(30,3,10,3,255,interpolate);
TrackerMeanShiftComaniciu2003 alg = new TrackerMeanShiftComaniciu2003(false,100,1e-8f,0.1f,0.0f,0.1f,calcHistogram);
Planar<GrayF32> image = new Planar<>(GrayF32.class,100,150,3);
// odd width and height so samples land on pixels
render(image,50,40,21,31);
RectangleRotate_F32 found = new RectangleRotate_F32(50,40,21,31,0);
alg.initialize(image,found);
// test no change
alg.updateLocation(image,found);
check(found,50,40,21,31,0);
// test translation
render(image,55,34,21,31);
alg.updateLocation(image,found);
check(found,55,34,21,31,0);
}
private void check( RectangleRotate_F32 found , float cx, float cy, float width, float height, float theta ) {
float tol = 0.5f;
assertEquals(found.cx,cx,tol);
assertEquals(found.cy,cy,tol);
assertEquals(found.width,width,tol);
assertEquals(found.height,height,tol);
assertEquals(found.theta,theta,tol);
}
@Test
public void distanceHistogram() {
LocalWeightedHistogramRotRect calcHist = new LocalWeightedHistogramRotRect(10,3,5,3,255,null);
TrackerMeanShiftComaniciu2003 alg = new TrackerMeanShiftComaniciu2003(true,100,1e-4f,0.1f,0.0f,0.1f,calcHist);
float histogramA[] = new float[ calcHist.getHistogram().length ];
float histogramB[] = new float[ calcHist.getHistogram().length ];
// score for identical histograms
for( int i = 0; i < histogramA.length; i++ ) {
histogramA[i] = histogramB[i] = rand.nextFloat();
}
UtilDouble.normalize(histogramA);
UtilDouble.normalize(histogramB);
double foundIdentical = alg.distanceHistogram(histogramA,histogramB);
assertEquals(0,foundIdentical,1e-3);
// make the histograms very different
for( int i = 0; i < histogramA.length; i++ ) {
histogramA[i] = rand.nextFloat();
}
UtilDouble.normalize(histogramA);
double foundDifferent = alg.distanceHistogram(histogramA,histogramB);
assertTrue(foundDifferent <= 1.0 );
assertTrue(foundDifferent > 0.05);
}
private void render(Planar<GrayF32> image , int cx , int cy , int w , int h ) {
GImageMiscOps.fill(image,0);
int tl_x = cx-w/2;
int tl_y = cy-h/2;
for( int y = 0; y < h; y++ ) {
for( int x = 0; x < w; x++ ) {
if( x > w/4 && x < 3*w/4 ) {
image.getBand(0).set(x+tl_x,y+tl_y,100);
image.getBand(1).set(x+tl_x,y+tl_y,200);
image.getBand(2).set(x+tl_x,y+tl_y,150);
} else {
image.getBand(0).set(x+tl_x,y+tl_y,200);
image.getBand(1).set(x+tl_x,y+tl_y,76);
image.getBand(2).set(x+tl_x,y+tl_y,40);
}
}
}
}
}