Jafar
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
zncc.hpp
00001 /* $Id$ */
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     // TODO : SSD, can use integral image for zncc, 
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     }; // class Zncc
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     }; // class Zncc
00084 
00085 
00086 
00088     // IMPLEMENTATIONS
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       // preconds
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 // std::cout << "zncc with sum1 " << sum1 << ", sumSqr1 " << sumSqr1 << ", sum2 " << sum2 << ", sumSqr2 " << sumSqr2 << ", halfLine " << halfLine << std::endl;
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       // start the loops
00117       double zncc_sum = 0.;
00118       double best_score1 = 1.0;
00119       //double best_score2 = 1.0;
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) // if ((((zncc_sum+halfSumSqr1)/count - mean12) / sigma12) < minScore) return -1;
00126         {
00127           int partialCount = (height-partialLine-1)*width;
00128           double current = (zncc_sum - mean2*(sum1-partialSum1) - mean1*(sum2-partialSum2) + (count-partialCount)*mean12);
00129           // this first bound seems more efficient at the beginning, at height/4
00130           double best_remain1 = sqrt((partialSumSqr2 + partialCount*mean2*mean2 - 2*mean2*partialSum2) *
00131                                      (partialSumSqr1 + partialCount*mean1*mean1 - 2*mean1*partialSum1));
00132           // this second bound seems globally less efficient, but more efficient at the end, after height/2
00133 //          double best_remain2 = sqrt(partialSumSqr1*partialSumSqr2) - mean2*partialSum1 - mean1*partialSum2 + partialCount*mean12;
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 //          best_score2 = (current + best_remain2) / (sigma12);
00140           if (best_score1 < minScore) return -2;
00141 //          if (best_score2 < minScore) return -1;
00142         }
00143         //if (i == halfLineB) if ((((zncc_sum+halfSumSqr1B)/count - mean12) / sigma12) < minScore) return -1;
00144       }
00145       
00146       // finish
00147 // std::cout << "fast: zncc_sum " << zncc_sum << ", count " << count << ", mean12 " << mean12 << ", sigma12 " << sigma12 << std::endl;
00148       double score = (sigma12 < 1e-6 ? -1 : (zncc_sum - count*mean12) / (sigma12));
00149       
00150 //std::cout << im2.getROI() << ": score " << score << ", estimated at " << partialLine << ": " << best_score1 << " / " << best_score2 << std::endl;
00151 //JFR_ASSERT(score <= best_score1+1e-6, "score1 est not upper bound");
00152 //JFR_ASSERT(score <= best_score2+1e-6, "score2 est not upper bound");
00153 //JFR_ASSERT(best_score1 <= 1+1e-6, "score1 est greater than 1");
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   //      case CV_1U:
00168   //        if (weightMatrix == NULL)
00169   //          return computeTpl<CV_1U, bool,bool,0,1,true,false>(im1,im2);
00170   //        else
00171   //          return computeTpl<CV_1U, bool,bool,0,1,true,true>(im1,im2,weightMatrix);
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   } /* correl */
00193 } /* jafar */
00194 
00195 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated on Wed Oct 15 2014 00:37:17 for Jafar by doxygen 1.7.6.1
LAAS-CNRS