/* * 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.enhance.impl; import boofcv.alg.enhance.EnhanceImageOps; import boofcv.alg.enhance.GEnhanceImageOps; import boofcv.alg.misc.GImageMiscOps; import boofcv.alg.misc.GImageStatistics; import boofcv.core.image.GeneralizedImageOps; import boofcv.struct.image.GrayI; import boofcv.struct.image.ImageGray; import boofcv.testing.BoofTesting; import org.junit.Test; import java.lang.reflect.Method; import java.util.Random; import static org.junit.Assert.assertEquals; /** * @author Peter Abeles */ @SuppressWarnings("unchecked") public class TestImplEnhanceHistogram { int width = 15; int height = 20; Random rand = new Random(234); @Test public void applyTransform() { int numFound = 0; Method methods[] = ImplEnhanceHistogram.class.getMethods(); for( int i = 0; i < methods.length; i++ ) { if( methods[i].getName().compareTo("applyTransform") != 0 ) continue; numFound++; Class imageType = methods[i].getParameterTypes()[0]; ImageGray input = GeneralizedImageOps.createSingleBand(imageType,width,height); ImageGray output = GeneralizedImageOps.createSingleBand(imageType,width,height); applyTransform( input , output ); BoofTesting.checkSubImage(this,"applyTransform",true,input,output); } assertEquals(5,numFound); } public void applyTransform(ImageGray input , ImageGray output ) { int min = input.getDataType().isSigned() ? -10 : 0; int transform[] = new int[10-min]; GImageMiscOps.fillUniform(input, rand, Math.min(min+1,0), 10); for( int i = min; i < 10; i++ ) transform[i-min] = i*2; if(input.getDataType().isSigned() ) { BoofTesting.callStaticMethod(ImplEnhanceHistogram.class,"applyTransform", input,transform,-10,output); } else { BoofTesting.callStaticMethod(ImplEnhanceHistogram.class,"applyTransform", input,transform,output); } for( int y = 0; y < height; y++ ) { for( int x = 0; x < width; x++ ) { double valueIn = GeneralizedImageOps.get(input,x,y); double valueOut = GeneralizedImageOps.get(output,x,y); assertEquals(2*valueIn,valueOut,1e-5); } } } /** * Validate naive algorithm by comparing it against to the full image equalization that has been passed * sub-images. */ @Test public void equalizeLocalNaive() { int numFound = 0; Method methods[] = ImplEnhanceHistogram.class.getMethods(); for (Method method : methods) { if (method.getName().compareTo("equalizeLocalNaive") != 0) continue; numFound++; Class imageType = method.getParameterTypes()[0]; GrayI input = (GrayI) GeneralizedImageOps.createSingleBand(imageType, width, height); GrayI output = (GrayI) GeneralizedImageOps.createSingleBand(imageType, width, height); equalizeLocalNaive(input, output); BoofTesting.checkSubImage(this, "equalizeLocalNaive", true, input, output); } assertEquals(2,numFound); } public void equalizeLocalNaive(GrayI input , GrayI output ) { GrayI tmp = GeneralizedImageOps.createSingleBand(input.getClass(),input.width, input.height); int transform[] = new int[10]; int histogram[] = new int[10]; GImageMiscOps.fillUniform(input,rand,0,10); for( int radius = 1; radius < 11; radius++ ) { BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalNaive", input, radius, output, histogram); int width = 2*radius+1; for( int y = 0; y < height; y++ ) { int y0 = y - radius; int y1 = y + radius+1; if( y0 < 0 ) { y0 = 0; y1 = y0 +width; if( y1 > input.height ) y1 = input.height; } else if( y1 > input.height ) { y1 = input.height; y0 = y1 - width; if( y0 < 0 ) y0 = 0; } for( int x = 0; x < input.width; x++ ) { int x0 = x - radius; int x1 = x + radius+1; if( x0 < 0 ) { x0 = 0; x1 = x0 + width; if( x1 > input.width ) x1 = input.width; } else if( x1 > input.width ) { x1 = input.width; x0 = x1 - width; if( x0 < 0 ) x0 = 0; } // use the full image algorithm GrayI subIn = (GrayI)input.subimage(x0,y0,x1,y1, null); GrayI subOut = (GrayI)tmp.subimage(x0,y0,x1,y1, null); GImageStatistics.histogram(subIn,0, histogram); EnhanceImageOps.equalize(histogram, transform); GEnhanceImageOps.applyTransform(subIn, transform, 0,subOut); int expected = subOut.get(x-x0,y-y0); int found = output.get(x,y); assertEquals(x+" "+y,expected,found); } } } } @Test public void equalizeLocalInner() { int numFound = 0; Method methods[] = ImplEnhanceHistogram.class.getMethods(); for (Method method : methods) { if (method.getName().compareTo("equalizeLocalNaive") != 0) continue; numFound++; Class imageType = method.getParameterTypes()[0]; GrayI input = (GrayI) GeneralizedImageOps.createSingleBand(imageType, width, height); GrayI output = (GrayI) GeneralizedImageOps.createSingleBand(imageType, width, height); equalizeLocalInner(input, output); BoofTesting.checkSubImage(this, "equalizeLocalInner", true, input, output); } assertEquals(2,numFound); } public void equalizeLocalInner(GrayI input , GrayI found ) { GrayI expected = GeneralizedImageOps.createSingleBand(input.getClass(),input.width, input.height); int histogram[] = new int[10]; GImageMiscOps.fillUniform(input,rand,0,10); for( int radius = 1; radius < 6; radius++ ) { // fill with zeros so it can be tested using checkBorderZero GImageMiscOps.fill(found,0); BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalNaive", input, radius, expected, histogram); BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalInner", input, radius, found, histogram); BoofTesting.assertEqualsInner(expected,found,1e-10,radius,radius,false); BoofTesting.checkBorderZero(found,radius); } } @Test public void equalizeLocalRow() { int numFound = 0; Method methods[] = ImplEnhanceHistogram.class.getMethods(); for (Method method : methods) { if (method.getName().compareTo("equalizeLocalRow") != 0) continue; numFound++; Class imageType = method.getParameterTypes()[0]; GrayI input = (GrayI) GeneralizedImageOps.createSingleBand(imageType, width, height); GrayI output = (GrayI) GeneralizedImageOps.createSingleBand(imageType, width, height); equalizeLocalRow(input, output); BoofTesting.checkSubImage(this, "equalizeLocalRow", true, input, output); } assertEquals(2,numFound); } public void equalizeLocalRow(GrayI input , GrayI found ) { GrayI expected = GeneralizedImageOps.createSingleBand(input.getClass(),input.width, input.height); int histogram[] = new int[10]; int transform[] = new int[10]; GImageMiscOps.fillUniform(input,rand,0,10); // check the top row for( int radius = 1; radius < 6; radius++ ) { // fill with zeros so it can be tested using checkBorderZero GImageMiscOps.fill(found,0); BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalNaive", input, radius, expected, histogram); BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalRow", input, radius, 0, found, histogram,transform); GrayI subExpected = (GrayI)expected.subimage(0,0,width,radius, null); GrayI subFound = (GrayI)found.subimage(0,0,width,radius, null); // check solution BoofTesting.assertEquals(subExpected,subFound,1e-10); checkZeroOutsideRows(found,0,radius); } // check the bottom row for( int radius = 1; radius < 6; radius++ ) { // fill with zeros so it can be tested using checkBorderZero GImageMiscOps.fill(found,0); int start = input.height-radius; BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalNaive", input, radius, expected, histogram); BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalRow", input, radius, start, found, histogram,transform); GrayI subExpected = (GrayI)expected.subimage(0,start,width,height, null); GrayI subFound = (GrayI)found.subimage(0,start,width,height, null); // check solution BoofTesting.assertEquals(subExpected,subFound,1e-10); checkZeroOutsideRows(found,start,height); } } private void checkZeroOutsideRows(GrayI image , int y0 , int y1) { for( int y = 0; y < height; y++ ) { if( y >= y0 && y < y1) continue; for( int x = 0; x < width; x ++ ) { assertEquals(x+" "+y,0,image.get(x,y)); } } } @Test public void equalizeLocalCol() { int numFound = 0; Method methods[] = ImplEnhanceHistogram.class.getMethods(); for (Method method : methods) { if (method.getName().compareTo("equalizeLocalCol") != 0) continue; numFound++; Class imageType = method.getParameterTypes()[0]; GrayI input = (GrayI) GeneralizedImageOps.createSingleBand(imageType, width, height); GrayI output = (GrayI) GeneralizedImageOps.createSingleBand(imageType, width, height); equalizeLocalCol(input, output); BoofTesting.checkSubImage(this, "equalizeLocalCol", true, input, output); } assertEquals(2,numFound); } public void equalizeLocalCol(GrayI input , GrayI found ) { GrayI expected = GeneralizedImageOps.createSingleBand(input.getClass(),input.width, input.height); int histogram[] = new int[10]; int transform[] = new int[10]; GImageMiscOps.fillUniform(input,rand,1,10); // check the left column for( int radius = 1; radius < 6; radius++ ) { // fill with zeros so it can be tested using checkBorderZero GImageMiscOps.fill(found,0); BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalNaive", input, radius, expected, histogram); BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalCol", input, radius, 0, found, histogram, transform); GrayI subExpected = (GrayI)expected.subimage(0,radius,radius,height-radius-1, null); GrayI subFound = (GrayI)found.subimage(0,radius,radius,height-radius-1, null); // check solution BoofTesting.assertEquals(subExpected,subFound,1e-10); checkZeroOutsideColumns(found, 0, radius, radius); } // check the right column for( int radius = 1; radius < 6; radius++ ) { // fill with zeros so it can be tested using checkBorderZero GImageMiscOps.fill(found,0); int start = input.width-radius; BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalNaive", input, radius, expected, histogram); BoofTesting.callStaticMethod(ImplEnhanceHistogram.class, "equalizeLocalCol", input, radius, start, found, histogram, transform); GrayI subExpected = (GrayI)expected.subimage(start,radius,width,height-radius-1, null); GrayI subFound = (GrayI)found.subimage(start,radius,width,height-radius-1, null); // check solution BoofTesting.assertEquals(subExpected,subFound,1e-10); checkZeroOutsideColumns(found, start, width, radius); } } private void checkZeroOutsideColumns(GrayI image , int x0 , int x1, int radius) { for( int y = 0; y < height; y++ ) { if( y < radius || y >= height-radius) { continue; } for( int x = 0; x < width; x ++ ) { if( x >= x0 && x < x1) continue; assertEquals(x+" "+y,0,image.get(x,y)); } } } }