/* * 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.abst.feature.dense; import boofcv.abst.feature.describe.DescribeRegionPoint; import boofcv.struct.feature.TupleDesc; import boofcv.struct.feature.TupleDesc_F64; import boofcv.struct.image.GrayU8; import boofcv.struct.image.ImageBase; import boofcv.struct.image.ImageType; import georegression.struct.point.Point2D_I32; import org.ddogleg.struct.FastQueue; import org.junit.Test; import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** * @author Peter Abeles */ public class TestGenericDenseDescribeImage { /** * Give it a known situation and see if it produces the expected results */ @Test public void process() { DummyFeature sparse = new DummyFeature(); GenericDenseDescribeImageDense alg = new GenericDenseDescribeImageDense(sparse,1,1.5,3,4); GrayU8 image = new GrayU8(100,110); alg.process(image); List<TupleDesc_F64> descs = alg.getDescriptions(); List<Point2D_I32> points = alg.getLocations(); assertEquals(descs.size(),points.size()); int featureRadius = (int)Math.round(1.5*7.0/2.0); int w = (100-2*featureRadius)/3; int h = (110-2*featureRadius)/4; // -1 since it intentionally skips feature 20 assertEquals(w*h-1,points.size()); int count = 0; for (int y = 0; y < h; y++) { int pixelY = featureRadius + y*y; for (int x = 0; x < w; x++) { int pixelX = featureRadius + x*3; Point2D_I32 p = null; if( count < 19 ) { p = points.get(count); } else if( count > 20 ) { p = points.get(count+1); } else { continue; } assertEquals("count = "+count,pixelX,p.x); assertEquals(pixelY,p.y); count++; } } } @Test public void checkDescriptorScale() { DummyFeature sparse = new DummyFeature(); GrayU8 image = new GrayU8(100,110); GenericDenseDescribeImageDense alg = new GenericDenseDescribeImageDense(sparse,1,1,8,9); alg.configure(1, 8, 9); alg.process(image); int found10 = alg.getDescriptions().size(); alg.configure(1.5, 8, 9); alg.process(image); int found15 = alg.getDescriptions().size(); alg.configure(0.75, 8, 9); alg.process(image); int found07a = alg.getDescriptions().size(); alg.configure(0.75, 8*0.75, 9*0.75); alg.process(image); int found07b = alg.getDescriptions().size(); // same sampling period, should have same number of samples assertTrue(found07a == found10); assertTrue(found10 == found15); // sampling period is shorter so there should be more features assertTrue(found07b > found10); } public static class DummyFeature implements DescribeRegionPoint { ImageType type = ImageType.single(GrayU8.class); double inputRadius; ImageBase image; FastQueue<Point2D_I32> points = new FastQueue<>(Point2D_I32.class, true); int count = 0; @Override public void setImage(ImageBase image) { this.image = image; count = 0; } @Override public boolean process(double x, double y, double orientation, double radius, TupleDesc description) { assertTrue(description!=null); if( ++count != 20 ) { points.grow().set((int) x, (int) y); inputRadius = radius; return true; } else { return false; } } @Override public boolean requiresRadius() {return false;} @Override public boolean requiresOrientation() {return false;} @Override public ImageType getImageType() { return type; } @Override public double getCanonicalWidth() { return 7; } @Override public TupleDesc createDescription() { return new TupleDesc_F64(10); } @Override public Class getDescriptionType() { return TupleDesc_F64.class; } } }