/*
* 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.flow;
import boofcv.struct.flow.ImageFlow;
import boofcv.struct.image.GrayU8;
import boofcv.struct.image.ImageGray;
import org.junit.Test;
import java.util.Arrays;
import static org.junit.Assert.*;
/**
* @author Peter Abeles
*/
public class TestDenseOpticalFlowBlockPyramid {
@Test
public void findFlow() {
Dummy alg = new Dummy(3,2,200,GrayU8.class);
alg.minScore = 0.1f;
alg.targetX = 4;
alg.targetY = 8;
GrayU8 image = new GrayU8(30,40);
ImageFlow.D flow = new ImageFlow.D();
// see if it selects the obvious minimum
assertEquals(0.1f, alg.findFlow(6, 7, image, flow), 1e-4);
assertTrue(flow.isValid());
assertEquals(-2,flow.x,1e-4);
assertEquals(1,flow.y,1e-4);
// now try the case where the error is too high
alg.minScore = 100000000f;
alg.findFlow(6, 7, image, flow);
assertFalse(flow.isValid());
// now give it a case where everything has the same score. See if it picks the one with the least motion
alg.sameScore = true;
alg.minScore = 0.1f;
alg.findFlow(6, 7, image, flow);
assertTrue(flow.isValid());
assertEquals(0,flow.x,1e-4);
assertEquals(0,flow.y,1e-4);
}
@Test
public void checkNeighbors() {
int sr = 3;
int rr = 2;
Dummy alg = new Dummy(sr,rr,200,GrayU8.class);
alg.scores = new float[20*30];
Arrays.fill(alg.scores,20);
ImageFlow flows = new ImageFlow(20,30);
flows.invalidateAll();
ImageFlow.D tmp = new ImageFlow.D();
tmp.x = -1;
tmp.y = 2;
// checks to see if a pixel is invalid that it's flow is always set
// if a pixel is valid then the score is only set if the score is better
flows.get(6,5).x = 1;
flows.get(6,5).y = 2;
alg.scores[ 5*20+6 ] = 10;
flows.get(5,5).x = 1;
flows.get(5,5).y = 2;
alg.scores[ 5*20+5 ] = 4;
// same score, but more motion
alg.scores[ 6*20+5 ] = 5;
flows.get(5,6).x = 2;
flows.get(5,6).y = 2;
// same score, but less motion
alg.scores[ 6*20+6 ] = 5;
flows.get(6,6).x = 0;
flows.get(6,6).y = 1;
alg.checkNeighbors(6,7,tmp,flows,5);
for( int i = -rr; i <= rr; i++ ) {
for( int j = -rr; j <= rr; j++ ) {
int x = j+6;
int y = i+7;
ImageFlow.D f = flows.get(x,y);
assertTrue(f.isValid());
if( x == 5 && y == 5 ) {
assertEquals(4,alg.scores[y*20+x],1e-4);
assertEquals(1,f.x,1e-4);
assertEquals(2,f.y,1e-4);
} else if( x == 6 && y == 6 ) {
assertEquals(5,alg.scores[y*20+x],1e-4);
assertEquals(0,f.x,1e-4);
assertEquals(1,f.y,1e-4);
} else {
assertEquals(x+" "+y,5,alg.scores[y*20+x],1e-4);
assertEquals(-1,f.x,1e-4);
assertEquals(2,f.y,1e-4);
}
}
}
}
public static class Dummy extends DenseOpticalFlowBlockPyramid {
public boolean sameScore = false;
public int targetX;
public int targetY;
public float minScore;
public Dummy(int searchRadius, int regionRadius, int maxPerPixelError, Class imageType) {
super(searchRadius, regionRadius, maxPerPixelError, imageType);
}
@Override
protected void extractTemplate(int cx, int cy, ImageGray prev) {}
@Override
protected float computeError(int cx, int cy, ImageGray curr) {
if( sameScore )
return minScore;
else {
int dx = cx-targetX;
int dy = cy-targetY;
return dx*dx + dy*dy + minScore;
}
}
}
}