00001
00002
00003 #ifndef _JAFAR_CORREL_ZNCC_HPP_
00004 #define _JAFAR_CORREL_ZNCC_HPP_
00005
00006 #include <fstream>
00007 #include <iostream>
00008
00009 #include <kernel/jafarMacro.hpp>
00010 #include "image/Image.hpp"
00011
00012 namespace jafar {
00013 namespace correl {
00014
00015
00016
00021 class Zncc {
00022 template<int depth, typename worktype, typename bornetype, bornetype borneinf, bornetype bornesup, bool useBornes, bool useWeightMatrix>
00023 static double computeTpl(image::Image const& im1, image::Image const& im2, float const* weightMatrix = NULL);
00024 public:
00025
00036 static double compute(image::Image const& im1, image::Image const& im2, float const* weightMatrix = NULL);
00037 static double compute8noborne(image::Image const& im1, image::Image const& im2);
00044 static double exploreRotation(image::Image const* im1, image::Image const* im2, int rotationStep);
00045
00046 };
00047
00048
00052 class FastZncc {
00053 template<int depth, typename worktype>
00054 static inline double computeTpl(image::Image const& im1, image::Image const& im2, double sum1, double sumSqr1, double sum2, double sumSqr2, double minScore, int partialLine, double partialSum1, double partialSumSqr1, double partialSum2, double partialSumSqr2);
00055 public:
00056
00072 static inline double compute(image::Image const& im1, image::Image const& im2, double sum1, double sumSqr1, double sum2, double sumSqr2, double minScore, int partialLine, double partialSum1, double partialSumSqr1, double partialSum2, double partialSumSqr2);
00073
00077 static inline double computeChar(image::Image const& im1, image::Image const& im2, double sum1, double sumSqr1, double sum2, double sumSqr2, double minScore, int partialLine, double partialSum1, double partialSumSqr1, double partialSum2, double partialSumSqr2)
00078 {
00079 JFR_PRECOND(im1.depth() == im2.depth(), "The depth of both images is different");
00080 JFR_PRECOND(im1.depth() == CV_8U, "The depth of images is not 8 bits");
00081 return computeTpl<CV_8U, uint8_t>(im1,im2,sum1,sumSqr1,sum2,sumSqr2,minScore,partialLine,partialSum1,partialSumSqr1,partialSum2,partialSumSqr2);
00082 }
00083 };
00084
00085
00086
00088
00089
00090 template<int depth, typename worktype>
00091 double FastZncc::computeTpl(image::Image const& im1, image::Image const& im2, double sum1, double sumSqr1, double sum2, double sumSqr2, double minScore, int partialLine, double partialSum1, double partialSumSqr1, double partialSum2, double partialSumSqr2)
00092 {
00093
00094 JFR_PRECOND( im1.depth() == depth, "Image 1 depth is different from the template parameter" );
00095 JFR_PRECOND( im2.depth() == depth, "Image 2 depth is different from the template parameter" );
00096 JFR_PRECOND( im1.channels() == im2.channels(), "The channels number of both images are different" );
00097 JFR_PRECOND( im1.size() == im2.size() , "The size of images or roi are different (" << im1.width() << "," << im1.height() << " != " << im2.width() << "," << im2.height() << ")" );
00098
00099
00100
00101 int height = im1.height();
00102 int width = im1.width();
00103 int step1 = im1.step1()/sizeof(worktype) - width;
00104 int step2 = im2.step1()/sizeof(worktype) - width;
00105
00106 int count = height*width;
00107 double mean1 = sum1/(double)count;
00108 double mean2 = sum2/(double)count;
00109 double mean12 = mean1*mean2;
00110 double sigma12 = (sumSqr1 - count*mean1*mean1)*(sumSqr2 - count*mean2*mean2);
00111 sigma12 = sigma12 > 0.0 ? sqrt(sigma12) : 0.0;
00112
00113 worktype const* im1ptr = reinterpret_cast<worktype const*>(im1.data());
00114 worktype const* im2ptr = reinterpret_cast<worktype const*>(im2.data());
00115
00116
00117 double zncc_sum = 0.;
00118 double best_score1 = 1.0;
00119
00120 for(int i = 0; i < height; ++i, im1ptr += step1, im2ptr += step2)
00121 {
00122 for(int j = 0; j < width; ++j)
00123 zncc_sum += *(im1ptr++) * *(im2ptr++);
00124
00125 if (i == partialLine)
00126 {
00127 int partialCount = (height-partialLine-1)*width;
00128 double current = (zncc_sum - mean2*(sum1-partialSum1) - mean1*(sum2-partialSum2) + (count-partialCount)*mean12);
00129
00130 double best_remain1 = sqrt((partialSumSqr2 + partialCount*mean2*mean2 - 2*mean2*partialSum2) *
00131 (partialSumSqr1 + partialCount*mean1*mean1 - 2*mean1*partialSum1));
00132
00133
00134
00135 #ifndef JFR_NDEBUG
00136 if (sigma12 == 0.0) best_score1 = 1.0; else
00137 #endif
00138 best_score1 = (current + best_remain1) / (sigma12);
00139
00140 if (best_score1 < minScore) return -2;
00141
00142 }
00143
00144 }
00145
00146
00147
00148 double score = (sigma12 < 1e-6 ? -1 : (zncc_sum - count*mean12) / (sigma12));
00149
00150
00151
00152
00153
00155
00156
00157 JFR_ASSERT(score >= -1.01, "error with score" << score);
00158 return score;
00159 }
00160
00161
00162 double FastZncc::compute(image::Image const& im1, image::Image const& im2, double sum1, double sumSqr1, double sum2, double sumSqr2, double minScore, int partialLine, double partialSum1, double partialSumSqr1, double partialSum2, double partialSumSqr2)
00163 {
00164 JFR_PRECOND(im1.depth() == im2.depth(), "The depth of both images is different");
00165 switch(im1.depth())
00166 {
00167
00168
00169
00170
00171
00172 case CV_8U:
00173 return computeTpl<CV_8U, uint8_t>(im1,im2,sum1,sumSqr1,sum2,sumSqr2,minScore,partialLine,partialSum1,partialSumSqr1,partialSum2,partialSumSqr2);
00174 case CV_8S:
00175 return computeTpl<CV_8S, int8_t>(im1,im2,sum1,sumSqr1,sum2,sumSqr2,minScore,partialLine,partialSum1,partialSumSqr1,partialSum2,partialSumSqr2);
00176 case CV_16U:
00177 return computeTpl<CV_16U, uint16_t>(im1,im2,sum1,sumSqr1,sum2,sumSqr2,minScore,partialLine,partialSum1,partialSumSqr1,partialSum2,partialSumSqr2);
00178 case CV_16S:
00179 return computeTpl<CV_16S, int16_t>(im1,im2,sum1,sumSqr1,sum2,sumSqr2,minScore,partialLine,partialSum1,partialSumSqr1,partialSum2,partialSumSqr2);
00180 case CV_32F:
00181 return computeTpl<CV_32F, float>(im1,im2,sum1,sumSqr1,sum2,sumSqr2,minScore,partialLine,partialSum1,partialSumSqr1,partialSum2,partialSumSqr2);
00182 case CV_64F:
00183 return computeTpl<CV_64F, double>(im1,im2,sum1,sumSqr1,sum2,sumSqr2,minScore,partialLine,partialSum1,partialSumSqr1,partialSum2,partialSumSqr2);
00184 default:
00185 JFR_PRECOND(false, "Unknown image depth");
00186 return FP_NAN;
00187 }
00188 }
00189
00190
00191
00192 }
00193 }
00194
00195 #endif