From: Enblend <enb...@li...> - 2011-09-04 08:14:58
|
branch: details: http://enblend.hg.sourceforge.net/hgweb/enblend/enblend/hgrepo/e/en/enblend/enblend/rev/e06e25890af6 changeset: 755:e06e25890af6 user: Chris <cs...@us...> date: Sun Sep 04 09:50:56 2011 +0200 description: Let the user inquire statistics on the image differences in the overlap areas. diffstat: VERSION | 2 +- doc/enblend.info | 0 doc/enblend.texi | 10 +++++++ doc/enfuse.info | 0 doc/versenblend.texi | 4 +- src/enblend.cc | 31 ++++++++++++---------- src/global.h | 1 + src/mask.h | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 99 insertions(+), 17 deletions(-) diffs (197 lines): diff -r c37bd34b11a0 -r e06e25890af6 VERSION --- a/VERSION Sun Sep 04 09:50:33 2011 +0200 +++ b/VERSION Sun Sep 04 09:50:56 2011 +0200 @@ -1,1 +1,1 @@ -4.1-3552fc1e940f +4.1-c37bd34b11a0 diff -r c37bd34b11a0 -r e06e25890af6 doc/enblend.info Binary file doc/enblend.info has changed diff -r c37bd34b11a0 -r e06e25890af6 doc/enblend.texi --- a/doc/enblend.texi Sun Sep 04 09:50:33 2011 +0200 +++ b/doc/enblend.texi Sun Sep 04 09:50:56 2011 +0200 @@ -2196,6 +2196,16 @@ The default @var{LUMINANCE-WEIGHT} is @value{src::default-luminance-difference-weight} and the default @var{CHROMINANCE-WEIGHT} is @value{src::default-chrominance-difference-weight}. +@cindex match quality +@cindex quality, match +At higher verbosity levels Enblend computes the true size of the +overlap area in pixels and it calculates the average and standard +deviation of the difference per pixel in the normalized luminance +interval@tie{}[0@dots{}1]. These statistical measures are based on +@var{ALGORITHM}, therefore they should only be compared for identical +@var{ALGORITHM}s. The average difference is a rough measure of +quality with lower values meaning better matches. + @item --load-masks[=@var{IMAGE-TEMPLATE}] @opindex --load-masks @cindex mask, load diff -r c37bd34b11a0 -r e06e25890af6 doc/enfuse.info Binary file doc/enfuse.info has changed diff -r c37bd34b11a0 -r e06e25890af6 doc/versenblend.texi --- a/doc/versenblend.texi Sun Sep 04 09:50:33 2011 +0200 +++ b/doc/versenblend.texi Sun Sep 04 09:50:56 2011 +0200 @@ -1,4 +1,4 @@ @set UPDATED 1 September 2011 @set UPDATED-MONTH September 2011 -@set EDITION 4.1-16616bb7bf4b -@set VERSION 4.1-16616bb7bf4b +@set EDITION 4.1-3ba5ddfda816 +@set VERSION 4.1-3ba5ddfda816 diff -r c37bd34b11a0 -r e06e25890af6 src/enblend.cc --- a/src/enblend.cc Sun Sep 04 09:50:33 2011 +0200 +++ b/src/enblend.cc Sun Sep 04 09:50:56 2011 +0200 @@ -75,12 +75,28 @@ #include "self_test.h" #include "tiff_message.h" + typedef enum { UnknownDifference, HueLuminanceMaxDifference, // maximum of hue difference and luminance difference DeltaEDifference // L*a*b*-based Delta E } difference_functor_t; + +std::string +stringOfPixelDifferenceFunctor(difference_functor_t aFunctor) +{ + switch (aFunctor) + { + case HueLuminanceMaxDifference: return "maximum-hue-luminance"; + case DeltaEDifference: return "delta-e"; + default: assert(false); + } + + return "unknown"; +} + + typedef struct { unsigned int kmax; // maximum number of moves for a line segment double tau; // temperature reduction factor, "cooling factor"; 0 < tau < 1 @@ -88,6 +104,7 @@ double deltaEMin; // minimum cost change possible by any single annealing move } anneal_para_t; + // Globals const std::string command("enblend"); const int minimumVectorizeDistance = 4; //< src::minimum-vectorize-distance 4 @@ -219,20 +236,6 @@ } -std::string -stringOfPixelDifferenceFunctor(difference_functor_t aFunctor) -{ - switch (aFunctor) - { - case HueLuminanceMaxDifference: return "maximum-hue-luminance"; - case DeltaEDifference: return "delta-e"; - default: assert(false); - } - - return "unknown"; -} - - #define DUMP_GLOBAL_VARIABLES(...) dump_global_variables(__FILE__, __LINE__, ##__VA_ARGS__) void dump_global_variables(const char* file, unsigned line, std::ostream& out = std::cout) diff -r c37bd34b11a0 -r e06e25890af6 src/global.h --- a/src/global.h Sun Sep 04 09:50:33 2011 +0200 +++ b/src/global.h Sun Sep 04 09:50:56 2011 +0200 @@ -44,6 +44,7 @@ #define VERBOSE_COLOR_CONVERSION_MESSAGES 3 +#define VERBOSE_DIFFERENCE_STATISTICS 3 #define VERBOSE_LAYER_SELECTION 3 #define VERBOSE_RESPONSE_FILES 3 diff -r c37bd34b11a0 -r e06e25890af6 src/mask.h --- a/src/mask.h Sun Sep 04 09:50:33 2011 +0200 +++ b/src/mask.h Sun Sep 04 09:50:56 2011 +0200 @@ -305,6 +305,54 @@ } } + +template <typename value, typename predicate> +class FindAverageAndVarianceIf +{ +public: + typedef value argument_type; + typedef value first_argument_type; + typedef double second_argument_type; + typedef typename vigra::NumericTraits<value>::RealPromote result_type; + typedef typename vigra::NumericTraits<value>::RealPromote value_type; + + FindAverageAndVarianceIf(predicate aPredicate) : + sum_(0.0), sum_of_squares_(0.0), count_(0.0), pred_(aPredicate) {} + + void reset() { + count_ = 0.0; + sum_of_squares_ = 0.0; + count_ = 0.0; + } + + void operator()(const argument_type& v) { + if (pred_(v)) { + count_ += 1.0; + sum_ += static_cast<double>(v); + sum_of_squares_ += square(static_cast<double>(v)); + } + } + + unsigned count() const {return static_cast<unsigned>(count_);} + + result_type average() const { + assert(count_ != 0.0); + return static_cast<result_type>(sum_ / count_); + } + + result_type variance() const { + assert(count_ != 0.0); + return static_cast<result_type>((sum_of_squares_ - square(sum_) / count_) / count_); + } + +private: + double sum_; + double sum_of_squares_; + double count_; + predicate pred_; +}; + + template <typename ValueType, typename AccessorType> class XorAccessor { @@ -1063,6 +1111,26 @@ assert(false); } + if (Verbose >= VERBOSE_DIFFERENCE_STATISTICS) { + typedef std::binder2nd<std::not_equal_to<MismatchImagePixelType> > predicate; + + predicate non_maximum(std::bind2nd(std::not_equal_to<MismatchImagePixelType>(), + vigra::NumericTraits<MismatchImagePixelType>::max())); + enblend::FindAverageAndVarianceIf<MismatchImagePixelType, predicate> statistics(non_maximum); + const double range = static_cast<double>(vigra::NumericTraits<MismatchImagePixelType>::max() - + vigra::NumericTraits<MismatchImagePixelType>::min()); + + vigra::inspectImage(srcImageRange(mismatchImage), statistics); + cerr << command << ": info: difference statistics: overlap size = " + << std::count_if(mismatchImage.begin(), mismatchImage.end(), non_maximum) << " pixels\n" + << command << ": info: difference statistics: mismatch average = " + << statistics.average() / range << " [" + << stringOfPixelDifferenceFunctor(PixelDifferenceFunctor) << "]\n" + << command << ": info: difference statistics: standard deviation = " + << sqrt(statistics.variance()) / range << " [" + << stringOfPixelDifferenceFunctor(PixelDifferenceFunctor) << "]" << endl; + } + if (DifferenceBlurRadius > 0.0) { gaussianSmoothing(srcImageRange(mismatchImage), destImage(mismatchImage), |