/* * 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.alg.filter.derivative.DerivativeType; import boofcv.alg.filter.derivative.GImageDerivativeOps; import boofcv.alg.interpolate.InterpolatePixelS; import boofcv.alg.misc.ImageMiscOps; import boofcv.core.image.border.BorderType; import boofcv.factory.flow.ConfigHornSchunckPyramid; import boofcv.factory.interpolate.FactoryInterpolation; import boofcv.struct.image.GrayF32; import boofcv.struct.pyramid.PyramidFloat; import org.junit.Test; import java.util.Random; import static org.junit.Assert.assertEquals; /** * @author Peter Abeles */ public class TestHornSchunckPyramid { int width = 10; int height = 13; Random rand = new Random(234); @Test public void process() { int width = 30; int height = 40; GrayF32 original1 = new GrayF32(width,height); GrayF32 original2 = new GrayF32(width,height); ImageMiscOps.fillRectangle(original1, 40, 10, 0, 10, height); ImageMiscOps.fillRectangle(original2, 40, 15, 0, 10, height); PyramidFloat<GrayF32> pyr1 = UtilDenseOpticalFlow.standardPyramid(width,height,0.7,0,5,12,GrayF32.class); PyramidFloat<GrayF32> pyr2 = UtilDenseOpticalFlow.standardPyramid(width,height,0.7,0,5,12,GrayF32.class); pyr1.process(original1); pyr2.process(original2); InterpolatePixelS<GrayF32> interpolate = FactoryInterpolation.bilinearPixelS( GrayF32.class, BorderType.EXTENDED); HornSchunckPyramid alg = new HornSchunckPyramid(new ConfigHornSchunckPyramid(20f,100),interpolate); alg.process(pyr1,pyr2); for( int y = 0; y < height; y++ ) { for( int x = 0; x < width; x++ ) { assertEquals(5,alg.getFlowX().get(x,y),0.25f); assertEquals(0,alg.getFlowY().get(x,y),0.25f); } } } @Test public void processLayer() { GrayF32 image1 = new GrayF32(width,height); GrayF32 image2 = new GrayF32(width,height); GrayF32 deriv2X = new GrayF32(width,height); GrayF32 deriv2Y = new GrayF32(width,height); ImageMiscOps.fillRectangle(image1,40,4,0,3,height); ImageMiscOps.fillRectangle(image2,40,5,0,3,height); GImageDerivativeOps.gradient(DerivativeType.TWO_0,image2, deriv2X, deriv2Y, BorderType.EXTENDED); // have the smoothness constraint be weak InterpolatePixelS<GrayF32> interpolate = FactoryInterpolation.bilinearPixelS( GrayF32.class, BorderType.EXTENDED); HornSchunckPyramid alg = new HornSchunckPyramid(new ConfigHornSchunckPyramid(100,200),interpolate); alg.initFlowX.reshape(width,height); alg.initFlowY.reshape(width,height); alg.flowX.reshape(width,height); alg.flowY.reshape(width,height); alg.warpDeriv2X.reshape(width,height); alg.warpDeriv2Y.reshape(width,height); alg.warpImage2.reshape(width,height); alg.processLayer(image1,image2,deriv2X,deriv2Y); // alg.getFlowX().print("%4f"); for( int y = 0; y < height; y++ ) { for( int x = 0; x < width; x++ ) { assertEquals(x+" "+y,1,alg.getFlowX().get(x,y),0.1f); assertEquals(0,alg.getFlowY().get(x,y),0.1f); } } } @Test public void A() { GrayF32 flow = new GrayF32(width,height); ImageMiscOps.fillUniform(flow,rand,0,10); int x = 5,y=6; float left = flow.get(x-1,y) + flow.get(x+1,y) + flow.get(x,y-1) + flow.get(x,y+1); float right = flow.get(x-1,y-1) + flow.get(x+1,y-1) + flow.get(x-1,y+1) + flow.get(x+1,y+1); assertEquals((1.0f/6.0f)*left + (1.0f/12.0f)*right,HornSchunckPyramid.A(x,y,flow),1e-4); } @Test public void safe() { GrayF32 flow = new GrayF32(width,height); ImageMiscOps.fillUniform(flow,rand,0,10); assertEquals(flow.get(0,0),HornSchunckPyramid.safe(-1,0,flow),1e-4f); assertEquals(flow.get(0,0),HornSchunckPyramid.safe(0,-1,flow),1e-4f); assertEquals(flow.get(5,0),HornSchunckPyramid.safe(5,-1,flow),1e-4f); assertEquals(flow.get(5,height-1),HornSchunckPyramid.safe(5,height,flow),1e-4f); assertEquals(flow.get(0,5),HornSchunckPyramid.safe(-1,5,flow),1e-4f); assertEquals(flow.get(width-1,5),HornSchunckPyramid.safe(width,5,flow),1e-4f); } }