/************************************************************************/ /* */ /* Copyright 2004 by Ullrich Koethe */ /* Cognitive Systems Group, University of Hamburg, Germany */ /* */ /* This file is part of the VIGRA computer vision library. */ /* ( Version 1.5.0, Dec 07 2006 ) */ /* The VIGRA Website is */ /* http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/ */ /* Please direct questions, bug reports, and contributions to */ /* koethe@informatik.uni-hamburg.de or */ /* vigra@kogs1.informatik.uni-hamburg.de */ /* */ /* Permission is hereby granted, free of charge, to any person */ /* obtaining a copy of this software and associated documentation */ /* files (the "Software"), to deal in the Software without */ /* restriction, including without limitation the rights to use, */ /* copy, modify, merge, publish, distribute, sublicense, and/or */ /* sell copies of the Software, and to permit persons to whom the */ /* Software is furnished to do so, subject to the following */ /* conditions: */ /* */ /* The above copyright notice and this permission notice shall be */ /* included in all copies or substantial portions of the */ /* Software. */ /* */ /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND */ /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES */ /* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */ /* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT */ /* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, */ /* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING */ /* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR */ /* OTHER DEALINGS IN THE SOFTWARE. */ /* */ /************************************************************************/ #include "unittest.hxx" #include #include #include #include #include #include #include #include #include #include using namespace std; using namespace vigra; using namespace vigra::functor; struct Compare1 { double s; typedef vigra::FFTWComplexImage::value_type value_type; typedef vigra::FFTWComplexImage::value_type result_type; Compare1(double is) : s(is) {} result_type operator()(value_type v1, value_type v2) const { return v1 - v2/s; } }; struct FFTWComplexTest { FFTWComplex clx0, clx1, clx2, clx3; template void printVector(VECTOR const & v) { std::cerr << "("; for(int i=0; i average; inspectImage(srcImageRange(out, vigra::FFTWImaginaryAccessor()), average); shouldEqualTolerance(average(), 0.0, 1e-14); combineTwoImages(srcImageRange(in), srcImage(out), destImage(out), Compare1((double)w*h)); average = vigra::FindAverage(); inspectImage(srcImageRange(out, vigra::FFTWMagnitudeAccessor()), average); shouldEqualTolerance(average(), 0.0, 1e-14); for (int y=0; y caverage; inspectImage(srcImageRange(out), caverage); shouldEqualTolerance(caverage().magnitude(), 0.0, 1e-14); } void testRearrangeQuadrants() { double t4[] = { 0, 1, 2, 2, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 4, 4}; double t4res[] = { 4, 4, 3, 3, 4, 4, 3, 3, 2, 2, 0, 1, 2, 2, 1, 1}; FFTWComplexImage in4(4,4), out4(4,4); copy(t4, t4+16, in4.begin()); moveDCToCenter(srcImageRange(in4), destImage(out4)); moveDCToUpperLeft(srcImageRange(out4), destImage(in4)); for(int i=0; i<16; ++i) { should(out4.begin()[i] == t4res[i]); should(in4.begin()[i] == t4[i]); } double t5[] = { 0, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 3, 3, 3, 4, 4}; double t5res[] = { 4, 4, 3, 3, 3, 4, 4, 3, 3, 3, 2, 2, 0, 1, 1, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1}; FFTWComplexImage in5(5,5), out5(5,5); copy(t5, t5+25, in5.begin()); moveDCToCenter(srcImageRange(in5), destImage(out5)); moveDCToUpperLeft(srcImageRange(out5), destImage(in5)); for(int i=0; i<25; ++i) { should(out5.begin()[i] == t5res[i]); should(in5.begin()[i] == t5[i]); } } }; struct FFTWTestSuite : public vigra::test_suite { FFTWTestSuite() : vigra::test_suite("FFTWTest") { add( testCase(&FFTWComplexTest::testConstruction)); add( testCase(&FFTWComplexTest::testComparison)); add( testCase(&FFTWComplexTest::testArithmetic)); add( testCase(&FFTWComplexTest::testAccessor)); add( testCase(&FFTWComplexTest::testForwardBackwardTrans)); add( testCase(&FFTWComplexTest::testRearrangeQuadrants)); } }; int initializing; struct CompareFunctor { double sumDifference_; CompareFunctor(): sumDifference_(0) {} void operator()(const float &a, const float &b) { sumDifference_+= abs(a-b); } double operator()() { return sumDifference_; } }; struct GaborTests { ImageImportInfo info; int w, h; FImage image; GaborTests() : info("ghouse.gif"), w(info.width()), h(info.height()), image(w, h) { importImage(info, destImage(image)); } template void checkImage(triple src, char *filename) { if (initializing) { exportImage(src, ImageExportInfo(filename)); cout << "wrote " << filename << endl; } else { ImageImportInfo info(filename); FImage image(info.width(), info.height()); importImage(info, destImage(image)); CompareFunctor cmp; inspectTwoImages(src, srcImage(image), cmp); cout << "difference to " << filename << ": " << cmp() << endl; shouldEqualTolerance(cmp(), 0.0, 1e-4); } } void testImages() { FImage filter(w, h); int directionCount= 8; int dir= 1, scale= 1; double angle = dir * M_PI / directionCount; double centerFrequency = 3.0/8.0 / VIGRA_CSTD::pow(2.0,scale); createGaborFilter(destImageRange(filter), angle, centerFrequency, angularGaborSigma(directionCount, centerFrequency), radialGaborSigma(centerFrequency)); checkImage(srcImageRange(filter), "filter.xv"); cout << "Applying filter...\n"; FFTWComplexImage result(w, h); applyFourierFilter(srcImageRange(image), srcImage(filter), destImage(result)); checkImage(srcImageRange(result, FFTWMagnitudeAccessor()), "gaborresult.xv"); FImage realPart(w, h); applyFourierFilter(srcImageRange(image), srcImage(filter), destImage(realPart)); CompareFunctor cmp; inspectTwoImages(srcImageRange(result, FFTWRealAccessor()), srcImage(realPart), cmp); cout << "difference between real parts: " << cmp() << endl; shouldEqualTolerance(cmp(), 0.0, 1e-4); cout << "testing vector results..\n"; FVector2Image vectorResult(w,h); applyFourierFilter(srcImageRange(image), srcImage(filter), destImage(vectorResult)); CompareFunctor iCmp; inspectTwoImages(srcImageRange(result, FFTWImaginaryAccessor()), srcImage(vectorResult, VectorComponentAccessor(1)), iCmp); cout << "difference between imaginary parts: " << iCmp() << endl; shouldEqualTolerance(cmp(), 0.0, 1e-4); cout << "applying on ROI...\n"; FImage bigImage(w+20, h+20); FImage::Iterator bigUL= bigImage.upperLeft() + Diff2D(5, 5); copyImage(srcImageRange(image), destIter(bigUL)); applyFourierFilter(srcIterRange(bigUL, bigUL + Diff2D(w, h)), srcImage(filter), destImage(result)); checkImage(srcImageRange(result, FFTWMagnitudeAccessor()), "gaborresult.xv"); #if 0 cout << "Creating plans with measurement...\n"; fftwnd_plan forwardPlan= fftw2d_create_plan(h, w, FFTW_FORWARD, FFTW_MEASURE ); fftwnd_plan backwardPlan= fftw2d_create_plan(h, w, FFTW_BACKWARD, FFTW_MEASURE | FFTW_IN_PLACE); cout << "Applying again...\n"; applyFourierFilter(srcImageRange(image), srcImage(filter), destImage(result), forwardPlan, backwardPlan); checkImage(srcImageRange(result, FFTWMagnitudeAccessor()), "gaborresult.xv"); #endif } void testFamily() { cout << "testing 8x2 GaborFilterFamily...\n"; GaborFilterFamily filters(w, h, 8, 2); ImageArray results((unsigned int)filters.size(), filters.imageSize()); applyFourierFilterFamily(srcImageRange(image), filters, results); checkImage(srcImageRange(results[filters.filterIndex(1,1)], FFTWMagnitudeAccessor()), "gaborresult.xv"); ImageArray realParts((unsigned int)filters.size(), filters.imageSize()); applyFourierFilterFamily(srcImageRange(image), filters, realParts); CompareFunctor cmp; inspectTwoImages(srcImageRange(results[3], FFTWRealAccessor()), srcImage(realParts[3]), cmp); cout << "difference between real parts: " << cmp() << endl; shouldEqualTolerance(cmp(), 0.0, 1e-4); } }; struct GaborTestSuite : public vigra::test_suite { GaborTestSuite() : vigra::test_suite("FFTWWithGaborTest") { add(testCase(&GaborTests::testImages)); add(testCase(&GaborTests::testFamily)); } }; int main(int argc, char **argv) { initializing= argc>1; // global variable, // initializing means: don't compare with image files but create them FFTWTestSuite fftwTest; int failed = fftwTest.run(); std::cout << fftwTest.report() << std::endl; GaborTestSuite gaborTest; failed = failed || gaborTest.run(); std::cout << gaborTest.report() << std::endl; return (failed != 0); }