IntegralImage.cxx
上传用户:lijia5631
上传日期:2008-11-10
资源大小:1214k
文件大小:11k
源码类别:

视频捕捉/采集

开发平台:

MultiPlatform

  1. /**
  2.   * cubicles
  3.   *
  4.   * This is an implementation of the Viola-Jones object detection 
  5.   * method and some extensions.  The code is mostly platform-
  6.   * independent and uses only standard C and C++ libraries.  It
  7.   * can make use of MPI for parallel training and a few Windows
  8.   * MFC functions for classifier display.
  9.   *
  10.   * Mathias Kolsch, matz@cs.ucsb.edu
  11.   *
  12.   * $Id: IntegralImage.cxx,v 1.29 2005/02/12 02:00:59 matz Exp $
  13. **/
  14. // IntegralImage is the basic data type for training and 
  15. // recognition: a simple accumulative matrix generated from a 
  16. // gray-level image, akin a "data cube" as known in the database
  17. // community.
  18. //
  19. // IntegralImage.cxx is the C++ template class implementation file, 
  20. // it is included from IntegralImage.h.
  21. //
  22. ////////////////////////////////////////////////////////////////////
  23. //
  24. // By downloading, copying, installing or using the software you 
  25. // agree to this license.  If you do not agree to this license, 
  26. // do not download, install, copy or use the software.
  27. //
  28. // Copyright (C) 2004, Mathias Kolsch, all rights reserved.
  29. // Third party copyrights are property of their respective owners.
  30. //
  31. // Redistribution and use in binary form, with or without 
  32. // modification, is permitted for non-commercial purposes only.
  33. // Redistribution in source, with or without modification, is 
  34. // prohibited without prior written permission.
  35. // If granted in writing in another document, personal use and 
  36. // modification are permitted provided that the following two
  37. // conditions are met:
  38. //
  39. // 1.Any modification of source code must retain the above 
  40. //   copyright notice, this list of conditions and the following 
  41. //   disclaimer.
  42. //
  43. // 2.Redistribution's in binary form must reproduce the above 
  44. //   copyright notice, this list of conditions and the following 
  45. //   disclaimer in the documentation and/or other materials provided
  46. //   with the distribution.
  47. //
  48. // This software is provided by the copyright holders and 
  49. // contributors "as is" and any express or implied warranties, 
  50. // including, but not limited to, the implied warranties of 
  51. // merchantability and fitness for a particular purpose are 
  52. // disclaimed.  In no event shall the copyright holder or 
  53. // contributors be liable for any direct, indirect, incidental, 
  54. // special, exemplary, or consequential damages (including, but not 
  55. // limited to, procurement of substitute goods or services; loss of 
  56. // use, data, or profits; or business interruption) however caused
  57. // and on any theory of liability, whether in contract, strict 
  58. // liability, or tort (including negligence or otherwise) arising 
  59. // in any way out of the use of this software, even if advised of 
  60. // the possibility of such damage.
  61. //
  62. ////////////////////////////////////////////////////////////////////
  63. #include <math.h>
  64. #include <ostream>
  65. #ifdef USE_MFC
  66. #ifdef _DEBUG
  67. #ifndef new
  68. #define new DEBUG_NEW
  69. #endif // new
  70. #endif // _DEBUG
  71. #endif // USE_MFC
  72. /////////////////////////////////////////////////////////////////////////////
  73. // CIntegralImageT
  74. /////////////////////////////////////////////////////////////////////////////
  75. template<class TYPE>
  76. CIntegralImageT<TYPE>::CIntegralImageT()
  77. : m_width(0),
  78.   m_height(0),
  79.   m_padded_width(0),
  80.   m_arraylen(0),
  81.   m_pData(NULL),
  82.   m_pPaddedData(NULL)
  83. {
  84. }
  85. template<class TYPE>
  86. CIntegralImageT<TYPE>::~CIntegralImageT()
  87. {
  88.   m_width = m_height = m_padded_width = m_arraylen = 0;
  89.   delete[] m_pPaddedData;
  90.   m_pPaddedData = NULL;
  91.   m_pData = NULL;
  92. }
  93. /* re/allocate and zero-initialize space
  94.  */
  95. template<class TYPE>
  96. void CIntegralImageT<TYPE>::SetSize(int width, int height)
  97. {
  98.   m_width = width;
  99.   m_padded_width = width+1;
  100.   m_height = height;
  101.   int data_len = m_width*m_height;
  102.   int padded_len = data_len+m_height+m_padded_width;
  103.   if (padded_len>m_arraylen) {
  104.     m_arraylen = padded_len;
  105.     delete[] m_pPaddedData;
  106.     ASSERT(m_arraylen>0);
  107.     m_pPaddedData = new TYPE[m_arraylen];
  108.     ASSERT(m_pPaddedData);
  109.   }
  110.   memset(m_pPaddedData, 0, padded_len*sizeof(TYPE));
  111.   m_pData = &m_pPaddedData[m_padded_width+1];
  112. }
  113. /* allocates data structures and generates the integral matrix from
  114.  * a gray image with TYPE-size elements.
  115.  */
  116. template<class TYPE>
  117. void CIntegralImageT<TYPE>::CreateFrom(const CByteImage& image, bool normalize)
  118. {
  119.   m_width = image.Width();
  120.   m_padded_width = m_width+1;
  121.   m_height = image.Height();
  122.   int data_len = m_width*m_height;
  123.   int padded_len = data_len+m_height+m_padded_width;
  124.   if (padded_len>m_arraylen) {
  125.     m_arraylen = padded_len;
  126.     delete[] m_pPaddedData;
  127.     ASSERT(m_arraylen>0);
  128.     m_pPaddedData = new TYPE[m_arraylen];
  129.     ASSERT(m_pPaddedData);
  130.   }
  131.   m_pData = &m_pPaddedData[m_padded_width+1];
  132.   memset(m_pPaddedData, 0, padded_len*sizeof(TYPE));
  133.   if (normalize) {
  134.     // find avg
  135.     int sum=0;
  136.     { for (int y=0; y<m_height; y++) {
  137.       for (int x=0; x<m_width; x++) {
  138.         sum += image.Pixel(x, y);
  139.       }
  140.     } }
  141.     double N = (double)(m_height*m_width);
  142.     ASSERT(N);
  143.     double avg = (double)sum/N;
  144.     // find stddev
  145.     double varsum=0;
  146.     { for (int y=0; y<m_height; y++) {
  147.       for (int x=0; x<m_width; x++) {
  148.         double val = (double)image.Pixel(x, y)-avg;
  149.         varsum += val*val;
  150.       }
  151.     } }
  152.     if (varsum==0) {
  153.       // zero variance - make integral all zero
  154.       for (int y=0; y<m_height; y++) {
  155.         for (int x=0; x<m_width; x++) {
  156.           SetElement(x, y, 0);
  157.         }
  158.       }
  159.       return;
  160.     }
  161.     double stddev = sqrt(varsum/N);
  162.     // normalization - folded into the integration computation
  163.     // fill integral image for the entire matrix
  164.     for (int y=0; y<m_height; y++) {
  165.       for (int x=0; x<m_width; x++) {
  166.         TYPE left = GetElement(x-1, y);
  167.         TYPE upper = GetElement(x, y-1);
  168.         TYPE diag = GetElement(x-1, y-1);
  169. #if defined(II_TYPE_FLOAT) || defined(II_TYPE_DOUBLE)
  170.         TYPE img = (TYPE) (((double)image.Pixel(x, y)-avg)/stddev);
  171. #elif defined(II_TYPE_INT) || defined(II_TYPE_UINT)
  172.         double newpix = ((double)image.Pixel(x, y)-avg)/stddev;
  173.         newpix *= 127.5;
  174.         newpix += 127.5;
  175.         TYPE img;
  176.         if (newpix<0) {
  177.           img = 0;
  178.         } else if (newpix>255) {
  179.           img = 255;
  180.         } else {
  181.           img = (TYPE) newpix;
  182.         }
  183. #else
  184. #error need to define functionality for this II_TYPE
  185. #endif // II_TYPE
  186.         TYPE val = left+upper-diag+img;
  187.         SetElement(x, y, val);
  188.       }
  189.     }
  190.     
  191.     
  192.   } else {
  193.     // don't normalize
  194.     // fill integral image for the entire matrix
  195.     for (int y=0; y<m_height; y++) {
  196.       for (int x=0; x<m_width; x++) {
  197.         TYPE left = GetElement(x-1, y);
  198.         TYPE upper = GetElement(x, y-1);
  199.         TYPE diag = GetElement(x-1, y-1);
  200.         TYPE img = image.Pixel(x, y);
  201.         TYPE val = left+upper-diag+img;
  202.         SetElement(x, y, val);
  203.       }
  204.     }
  205.   }
  206. }
  207. /* allocates data structures and generates the integral matrix from
  208.  * a gray image with TYPE-size elements.
  209.  */
  210. template<class TYPE>
  211. void CIntegralImageT<TYPE>::CreateSimpleNSquaredFrom(
  212.    const CByteImage& image,
  213.    CIntegralImageT<TYPE>& integral,
  214.    CIntegralImageT<TYPE>& squared_integral,
  215.    const CRect& roi)
  216. {
  217.   int width = integral.m_width = squared_integral.m_width = image.Width();
  218.   ASSERT(width);
  219.   int padded_width = integral.m_padded_width = squared_integral.m_padded_width =
  220.     width+1;
  221.   int height = integral.m_height = squared_integral.m_height = image.Height();
  222.   ASSERT(height);
  223.   // check sizes of internal data structures
  224.   int old_array_len_integral = integral.m_arraylen;
  225.   int old_array_len_squared_integral = squared_integral.m_arraylen;
  226.   int data_len = width*height;
  227.   int new_array_len = data_len+height+padded_width;
  228.   if (new_array_len!=old_array_len_integral) {
  229.     delete[] integral.m_pPaddedData;
  230.     ASSERT(new_array_len>0);
  231. #if defined(_MSC_VER) && _MSC_VER<1400
  232.     // Visual C++ doesn't understand the nothrow
  233.     integral.m_pPaddedData = new TYPE[new_array_len];
  234. #else
  235.     integral.m_pPaddedData = new (std::nothrow) TYPE[new_array_len];
  236. #endif
  237.     ASSERT(integral.m_pPaddedData);
  238.     if (integral.m_pPaddedData==NULL) {
  239.       throw ITException("CreateSimpleNSquaredFrom: out of memory (1)");
  240.     }
  241.     integral.m_arraylen = new_array_len;
  242.     integral.m_pData = &integral.m_pPaddedData[padded_width+1];
  243.   }
  244.   if (new_array_len!=old_array_len_squared_integral) {
  245.     delete[] squared_integral.m_pPaddedData;
  246. #if defined(_MSC_VER) && _MSC_VER<1400
  247.     // Visual C++ doesn't understand the nothrow
  248.     squared_integral.m_pPaddedData = new TYPE[new_array_len];
  249. #else
  250.     squared_integral.m_pPaddedData = new (std::nothrow) TYPE[new_array_len];
  251. #endif
  252.     ASSERT(squared_integral.m_pPaddedData);
  253.     if (squared_integral.m_pPaddedData==NULL) {
  254.       throw ITException("CreateSimpleNSquaredFrom: out of memory (2)");
  255.     }
  256.     squared_integral.m_arraylen = new_array_len;
  257.     squared_integral.m_pData = &squared_integral.m_pPaddedData[padded_width+1];
  258.   }
  259.   memset(integral.m_pPaddedData, 0, new_array_len*sizeof(TYPE));
  260.   memset(squared_integral.m_pPaddedData, 0, new_array_len*sizeof(TYPE));
  261.   // fill integral image for the ROI part of the image
  262.   int y_stop = min(height, roi.bottom);
  263.   int x_stop = min(width, roi.right);
  264.   for (int y=max(0,roi.top); y<y_stop; y++) {
  265.     for (int x=max(0,roi.left); x<x_stop; x++) {
  266.       TYPE img = image.Pixel(x, y);
  267.       { // regular integral
  268.         TYPE left = integral.GetElement(x-1, y);
  269.         TYPE upper = integral.GetElement(x, y-1);
  270.         TYPE diag = integral.GetElement(x-1, y-1);
  271.         TYPE val = left+upper-diag+img;
  272.         integral.SetElement(x, y, val);
  273.       }
  274.       { // integral of squared image
  275.         TYPE left = squared_integral.GetElement(x-1, y);
  276.         TYPE upper = squared_integral.GetElement(x, y-1);
  277.         TYPE diag = squared_integral.GetElement(x-1, y-1);
  278.         TYPE val = left+upper-diag+img*img;
  279.         squared_integral.SetElement(x, y, val);
  280.       }
  281.     }
  282.   }
  283. }
  284. #ifdef DEBUG
  285. /*
  286. template<class TYPE>
  287. TYPE CIntegralImageT<TYPE>::operator[](int i) const
  288. {
  289.   ASSERT(0<=i && i<m_data_len);
  290.   return m_pData[i];
  291. }
  292. */
  293. template<class TYPE>
  294. TYPE CIntegralImageT<TYPE>::GetElement(int col, int row) const
  295. {
  296.   //  if (!(-1<=row && row<m_height && -1<=col && col<m_width)) {
  297.   //    cout << row << " " << m_height << " " << col << " " << m_width << endl;
  298.   //  }
  299.   ASSERT(-1<=row && row<m_height && -1<=col && col<m_width);
  300.   return m_pData[row*m_padded_width+col]; 
  301. }
  302. template<class TYPE>
  303. void CIntegralImageT<TYPE>::SetElement(int col, int row, TYPE val)
  304.   ASSERT(0<=row && row<m_height && 0<=col && col<m_width);
  305.   m_pData[row*m_padded_width+col]=val; 
  306. }
  307. template<class TYPE>
  308. void CIntegralImageT<TYPE>::IncElement(int col, int row, TYPE inc)
  309. {
  310.   ASSERT(0<=row && row<m_height && 0<=col && col<m_width);
  311.   m_pData[row*m_padded_width+col]+=inc; 
  312. }
  313. #endif //DEBUG
  314. template<class TYPE>
  315. ostream& operator<<(ostream& os, const CIntegralImageT<TYPE>& integral)
  316. {
  317.   for (int y=0; y<integral.m_height; y++) {
  318.     for (int x=0; x<integral.m_width; x++) {
  319.       os << integral.GetElement(x, y) << " ";
  320.     }
  321.     os << endl;
  322.   }
  323.   return os;
  324. }