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

视频捕捉/采集

开发平台:

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: IntegralFeatures.cpp,v 1.61 2005/10/28 17:47:04 matz Exp $
  13. **/
  14. // IntegralFeatures describe the rectangular areas whose pixel
  15. // sums are compared to a weak classifier's threshold.  There
  16. // are many different types of IntegralFeatures.
  17. // Functions for reading from files are flex/bison generated from
  18. // CascadeFileScanner.lex and CascadeFileParser.yy.
  19. //
  20. ////////////////////////////////////////////////////////////////////
  21. //
  22. // By downloading, copying, installing or using the software you 
  23. // agree to this license.  If you do not agree to this license, 
  24. // do not download, install, copy or use the software.
  25. //
  26. // Copyright (C) 2004, Mathias Kolsch, all rights reserved.
  27. // Third party copyrights are property of their respective owners.
  28. //
  29. // Redistribution and use in binary form, with or without 
  30. // modification, is permitted for non-commercial purposes only.
  31. // Redistribution in source, with or without modification, is 
  32. // prohibited without prior written permission.
  33. // If granted in writing in another document, personal use and 
  34. // modification are permitted provided that the following two
  35. // conditions are met:
  36. //
  37. // 1.Any modification of source code must retain the above 
  38. //   copyright notice, this list of conditions and the following 
  39. //   disclaimer.
  40. //
  41. // 2.Redistribution's in binary form must reproduce the above 
  42. //   copyright notice, this list of conditions and the following 
  43. //   disclaimer in the documentation and/or other materials provided
  44. //   with the distribution.
  45. //
  46. // This software is provided by the copyright holders and 
  47. // contributors "as is" and any express or implied warranties, 
  48. // including, but not limited to, the implied warranties of 
  49. // merchantability and fitness for a particular purpose are 
  50. // disclaimed.  In no event shall the copyright holder or 
  51. // contributors be liable for any direct, indirect, incidental, 
  52. // special, exemplary, or consequential damages (including, but not 
  53. // limited to, procurement of substitute goods or services; loss of 
  54. // use, data, or profits; or business interruption) however caused
  55. // and on any theory of liability, whether in contract, strict 
  56. // liability, or tort (including negligence or otherwise) arising 
  57. // in any way out of the use of this software, even if advised of 
  58. // the possibility of such damage.
  59. //
  60. ////////////////////////////////////////////////////////////////////
  61. #include "cubicles.hpp"
  62. #include "IntegralFeatures.h"
  63. #include "Exceptions.h"
  64. #include <math.h>
  65. #include <iostream>
  66. #ifdef _DEBUG
  67. #ifdef USE_MFC
  68. #define new DEBUG_NEW
  69. #undef THIS_FILE
  70. static char THIS_FILE[] = __FILE__;
  71. #endif // USE_MFC
  72. #endif // _DEBUG
  73. #if defined(WIN32) && defined(DEBUG)
  74. #include <streams.h>
  75. #endif
  76. #ifdef USE_MFC
  77. CBrush* g_pBlackbrush = NULL;
  78. CBrush* g_pWhitebrush = NULL;
  79. #endif // USE_MFC
  80. int g_verbose = 0;
  81. FILE* g_ostream = stdout;
  82. #ifdef WIN32
  83. #include <malloc.h>
  84. #define alloca _alloca
  85. #endif
  86. /////////////////////////////////////////////////////////////////////////////
  87. //
  88. // CIntegralFeature implementation
  89. //
  90. /////////////////////////////////////////////////////////////////////////////
  91. const II_TYPE CIntegralFeature::SCALE_DIFFERENCE_EPSILON = .000000001;
  92. CIntegralFeature::CIntegralFeature(int templateWidth, int templateHeight,
  93.                                    featnum num_incarnations, bool is_partial,
  94.                                    int cost)
  95. : m_template_width(templateWidth),
  96. m_template_height(templateHeight),
  97. m_num_incarnations(num_incarnations),
  98. m_is_partial(is_partial),
  99.   m_cost(cost)
  100. {
  101. #ifdef USE_MFC
  102.   if (g_pBlackbrush==NULL) {
  103.     ASSERT(g_pWhitebrush==NULL);
  104.     g_pWhitebrush = new CBrush(RGB(255, 255, 255));
  105.     g_pBlackbrush = new CBrush(RGB(0, 0, 0));
  106.   }
  107. #endif // USE_MFC
  108. }
  109. ostream& operator<<(ostream& os, const CIntegralFeature& clsf)
  110. {
  111.   return clsf.output(os);
  112. }
  113. CIntegralFeature* CIntegralFeature::CreateFrom(istream& is,
  114.        int template_width, int template_height)
  115. {
  116.   CIntegralFeature* feature = NULL;
  117.   string subclass;
  118.   is >> subclass;
  119.   if (subclass=="LeftRight") {
  120.     feature = new CLeftRightIF(is, template_width, template_height);
  121.   } else if (subclass=="UpDown") {
  122.     feature = new CUpDownIF(is, template_width, template_height);
  123.   } else if (subclass=="LeftCenterRight") {
  124.     feature = new CLeftCenterRightIF(is, template_width, template_height);
  125.   } else if (subclass=="SevenColumns") {
  126.     feature = new CSevenColumnsIF(is, template_width, template_height);
  127.   } else if (subclass=="Diag") {
  128.     feature = new CDiagIF(is, template_width, template_height);
  129.   } else if (subclass=="LeftRightSame") {
  130.     feature = new CLeftRightSameIF(is, template_width, template_height);
  131.   } else if (subclass=="UpDownSame") {
  132.     feature = new CUpDownSameIF(is, template_width, template_height);
  133.   } else if (subclass=="LeftCenterRightSame") {
  134.     feature = new CLeftCenterRightSameIF(is, template_width, template_height);
  135.   } else if (subclass=="SevenColumnsSame") {
  136.     feature = new CSevenColumnsSameIF(is, template_width, template_height);
  137.   } else if (subclass=="SevenColumnsSimilar") {
  138.     feature = new CSevenColumnsSimilarIF(is, template_width, template_height);
  139.   } else if (subclass=="DiagSame") {
  140.     feature = new CDiagSameIF(is, template_width, template_height);
  141.   } else if (subclass=="DiagSimilar") {
  142.     feature = new CDiagSimilarIF(is, template_width, template_height);
  143.   } else if (subclass=="FourBoxes") {
  144.     feature = new CFourBoxesIF(is, template_width, template_height);
  145.   } else if (subclass=="FourBoxesSame") {
  146.     feature = new CFourBoxesSameIF(is, template_width, template_height);
  147.   } else {
  148.     // error
  149.     VERBOSE1(1, "can not create IntegralFeature from string '%s'.", 
  150.      subclass.c_str());
  151.     ASSERT(0);
  152.   }
  153.   return feature;
  154. }
  155. /* use ScaleEvenly to scale by non-integer values, otherwise use
  156. * Scale
  157. */
  158. void CIntegralFeature::ScaleEvenly(II_TYPE scale_x, II_TYPE scale_y, 
  159.                                    int scaled_template_width, int scaled_template_height)
  160. {
  161.   Scale(scale_x, scale_y);
  162.   EvenOutScales(&scale_x, &scale_y, scaled_template_width, scaled_template_height);
  163.   m_global_scale = scale_x*scale_y;
  164. }
  165. featnum CIntegralFeature::GetNumIncarnations() const
  166. {
  167.   if (m_num_incarnations==IT_INVALID_FEATURE) {
  168.     // count some other feature, we don't want to change
  169.     // this one at all.
  170.     CIntegralFeature* counter = this->Copy();
  171.     counter->SetToFirstIncarnation();
  172.     featnum cnt = 0;
  173.     bool has_more_incarnations = true;
  174.     do {
  175.       cnt++;
  176.       if (cnt==IT_MAX_VALID_FEATURE) {
  177.         throw ITException("int overflow in GetNumIncarnations()");
  178.       }
  179.       has_more_incarnations = counter->SetToNextIncarnation();
  180.     } while (has_more_incarnations);
  181.     ((CIntegralFeature*) this)->m_num_incarnations = cnt;
  182.     delete counter;
  183.   }
  184.   ASSERT(m_num_incarnations>=0 && 
  185.  m_num_incarnations!=IT_INVALID_FEATURE);
  186.   return m_num_incarnations;
  187. }
  188. /////////////////////////////////////////////////////////////////////////////
  189. //
  190. // CLeftRightIF classes implementation
  191. //
  192. /////////////////////////////////////////////////////////////////////////////
  193. CLeftRightIF::CLeftRightIF(int templateWidth, int templateHeight)
  194.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, 
  195.      false, 6*COST_GET+7*COST_ADD) 
  196. {
  197. }
  198. CLeftRightIF::CLeftRightIF(const CLeftRightIF& frm)
  199.   : CIntegralFeature(frm.m_template_width, frm.m_template_height,
  200.      frm.m_num_incarnations, frm.m_is_partial, 6*COST_GET+7*COST_ADD) 
  201. {
  202.   toprow = frm.toprow;
  203.   bottomrow = frm.bottomrow;
  204.   leftrect_leftcol = frm.leftrect_leftcol;
  205.   centercol = frm.centercol;
  206.   rightrect_rightcol = frm.rightrect_rightcol;
  207.   if (m_is_partial) {
  208.     start_toprow = frm.start_toprow;
  209.     start_bottomrow = frm.start_bottomrow;
  210.     start_leftrect_leftcol = frm.start_leftrect_leftcol;
  211.     start_centercol = frm.start_centercol;
  212.     start_rightrect_rightcol = frm.start_rightrect_rightcol;
  213.     m_remaining_incarnations = frm.m_remaining_incarnations;
  214.     m_stop_after_num_incarnations = frm.m_stop_after_num_incarnations;
  215.   }
  216.   SetNonOverlap();
  217. }
  218. CLeftRightIF::CLeftRightIF(int template_width, int template_height,
  219.                            int _toprow, int _bottomrow,
  220.                            int _leftrect_leftcol, int _centercol,
  221.                            int _rightrect_rightcol)
  222.   : CIntegralFeature(template_width, template_height, IT_INVALID_FEATURE, 0, 6*COST_GET+7*COST_ADD)
  223. {
  224.   toprow = _toprow;
  225.   bottomrow = _bottomrow;
  226.   leftrect_leftcol = _leftrect_leftcol;
  227.   centercol = _centercol;
  228.   rightrect_rightcol = _rightrect_rightcol;
  229.   SetNonOverlap();
  230. }
  231. CLeftRightIF::CLeftRightIF(istream& is, int template_width, int template_height)
  232.   : CIntegralFeature(template_width, template_height, IT_INVALID_FEATURE, 0, 6*COST_GET+7*COST_ADD)
  233. {
  234.   char a, b, c;
  235.   string str;
  236.   is >> toprow >> a >> bottomrow >> str
  237.      >> leftrect_leftcol >> b >> centercol >> c >> rightrect_rightcol;
  238.   if (a!=',' || b!=',' || c!=',' || str!="x") {
  239.     char* buf = (char*) alloca((256+str.length())*sizeof(char));
  240.     sprintf(buf, "error during construction of LeftRightIF (%c|%c|%c|%s)n",
  241.    a, b, c, str.c_str());
  242.     throw ITException(buf);
  243.   }
  244.   SetNonOverlap();
  245. }
  246. bool CLeftRightIF::Equals(const CLeftRightIF& frm) const
  247. {
  248.   bool equal = 
  249.     (toprow == frm.toprow &&
  250.      bottomrow == frm.bottomrow &&
  251.      leftrect_leftcol == frm.leftrect_leftcol &&
  252.      centercol == frm.centercol &&
  253.      rightrect_rightcol == frm.rightrect_rightcol);
  254.   return equal;
  255. }
  256. void CLeftRightIF::SetNonOverlap() {
  257.   m_non_overlap =
  258.     ((centercol-leftrect_leftcol) - (rightrect_rightcol-centercol))
  259.     * (bottomrow-toprow);
  260. }
  261. II_TYPE CLeftRightIF::Compute(const CIntegralImage& image) const
  262. {
  263. II_TYPE botcen = image.GetElement(centercol, bottomrow);
  264. ASSERT(!isnan(botcen));
  265. II_TYPE topcen = image.GetElement(centercol, toprow);
  266. ASSERT(!isnan(topcen));
  267. II_TYPE val_leftrect = 
  268. botcen
  269. - image.GetElement(leftrect_leftcol, bottomrow)
  270. - topcen
  271. + image.GetElement(leftrect_leftcol, toprow);
  272. ASSERT(!isnan(val_leftrect));
  273. II_TYPE val_rightrect = 
  274. image.GetElement(rightrect_rightcol, bottomrow)
  275. - botcen
  276. - image.GetElement(rightrect_rightcol, toprow)
  277. + topcen;
  278. ASSERT(!isnan(val_rightrect));
  279. ASSERT(!isnan(val_leftrect-val_rightrect));
  280. return val_leftrect-val_rightrect;
  281. }
  282. II_TYPE CLeftRightIF::ComputeScaled(const CIntegralImage& image, II_TYPE mean, int left, int top) const
  283. {
  284. int placed_toprow = top + scaled_toprow;
  285. int placed_bottomrow = top + scaled_bottomrow;
  286. int placed_leftrect_leftcol = left + scaled_leftrect_leftcol;
  287. int placed_centercol = left + scaled_centercol;
  288. int placed_rightrect_rightcol = left + scaled_rightrect_rightcol;
  289. II_TYPE botcen = image.GetElement(placed_centercol, placed_bottomrow);
  290. II_TYPE topcen = image.GetElement(placed_centercol, placed_toprow);
  291. II_TYPE val_leftrect = 
  292. botcen
  293. - image.GetElement(placed_leftrect_leftcol, placed_bottomrow)
  294. - topcen
  295. + image.GetElement(placed_leftrect_leftcol, placed_toprow);
  296. II_TYPE val_rightrect = 
  297. image.GetElement(placed_rightrect_rightcol, placed_bottomrow)
  298. - botcen
  299. - image.GetElement(placed_rightrect_rightcol, placed_toprow)
  300. + topcen;
  301. II_TYPE val = val_leftrect-val_rightrect;
  302. II_TYPE scaled_val = val/m_global_scale;
  303. II_TYPE mean_adjust = m_non_overlap*mean;
  304.   return scaled_val-mean_adjust;
  305. }
  306. void CLeftRightIF::Scale(II_TYPE scale_x, II_TYPE scale_y)
  307. {
  308.   if (toprow==-1) {
  309.     scaled_toprow = -1;
  310.     scaled_bottomrow = (int)((II_TYPE)(bottomrow+1)*scale_y) - 1;
  311.   } else {
  312.     scaled_toprow = (int)((II_TYPE)toprow*scale_y);
  313.     scaled_bottomrow = (int)((II_TYPE)bottomrow*scale_y);
  314.   }
  315.   if (leftrect_leftcol==-1) {
  316.     scaled_leftrect_leftcol = -1;
  317.     scaled_centercol = (int)((II_TYPE)(centercol+1)*scale_x) - 1;
  318.     scaled_rightrect_rightcol =
  319.       (int)((II_TYPE)(rightrect_rightcol-centercol)*scale_x) + scaled_centercol;
  320.   } else {
  321.     scaled_leftrect_leftcol = (int)((II_TYPE)leftrect_leftcol*scale_x);
  322.     scaled_centercol = (int)((II_TYPE)centercol*scale_x);
  323.     scaled_rightrect_rightcol = (int)((II_TYPE)rightrect_rightcol*scale_x);
  324.   }
  325.   m_global_scale = scale_x*scale_y;
  326. }
  327. void CLeftRightIF::EvenOutScales(II_TYPE* pScale_x, II_TYPE* pScale_y,
  328.         int scaled_template_width, int /*scaled_template_height*/)
  329. {
  330.   int leftrect = centercol-leftrect_leftcol;
  331.   int rightrect = rightrect_rightcol-centercol;
  332.   II_TYPE ratio = (II_TYPE)leftrect/(II_TYPE)rightrect;
  333.   int sleftrect = scaled_centercol-scaled_leftrect_leftcol;
  334.   int srightrect = scaled_rightrect_rightcol-scaled_centercol;
  335.   II_TYPE sratio = (II_TYPE)sleftrect/(II_TYPE)srightrect;
  336.   int scaled_width = scaled_rightrect_rightcol-scaled_leftrect_leftcol;
  337.   bool too_wide = scaled_width > scaled_template_width;
  338.   while (!too_wide && fabs(ratio-sratio)>=SCALE_DIFFERENCE_EPSILON) {
  339.     if (ratio<sratio) {
  340.       scaled_rightrect_rightcol++;
  341.       srightrect++;
  342.     } else {
  343.       scaled_centercol++;
  344.       scaled_rightrect_rightcol++;
  345.       sleftrect++;
  346.     }
  347.     scaled_width = scaled_rightrect_rightcol-scaled_leftrect_leftcol;
  348.     too_wide = scaled_width > scaled_template_width;
  349.     sratio = (II_TYPE)sleftrect/(II_TYPE)srightrect;
  350.   }
  351.   int overlap = scaled_rightrect_rightcol-scaled_template_width+1;
  352.   // overlap: by how much is rightmost too far to the right? 
  353.   // it must not be larger than scaled_template_width-1
  354.   if (overlap>0) {
  355.     // went outside template boundaries
  356.     if (too_wide) {
  357.       // feature too big, use int scale
  358.       *pScale_x = floor(*pScale_x);
  359.       Scale(*pScale_x, *pScale_y);
  360.     } else {
  361.       // shift feature by overlap
  362.       scaled_leftrect_leftcol -= overlap;
  363.       scaled_centercol -= overlap;
  364.       scaled_rightrect_rightcol -= overlap;
  365.       *pScale_x = sratio;
  366.     }
  367.   } else {
  368.     *pScale_x = sratio;
  369.   }
  370. }
  371. void CLeftRightIF::SetToFirstIncarnation()
  372. {
  373.   if (m_is_partial) {
  374.     toprow=start_toprow;
  375.     bottomrow=start_bottomrow;
  376.     leftrect_leftcol=start_leftrect_leftcol;
  377.     centercol=start_centercol;
  378.     rightrect_rightcol=start_rightrect_rightcol;
  379.     m_remaining_incarnations=m_stop_after_num_incarnations;
  380.   } else {
  381.     toprow=-1;
  382.     bottomrow=0;
  383.     leftrect_leftcol=-1;
  384.     centercol=0;
  385.     rightrect_rightcol=1;
  386.   }
  387.   SetNonOverlap();
  388. }
  389. bool CLeftRightIF::SetToNextIncarnation()
  390. {
  391.   if (m_is_partial) {
  392.     if (m_remaining_incarnations) {
  393.       m_remaining_incarnations--;
  394.     } else {
  395.       return false;
  396.     }
  397.   }
  398.   rightrect_rightcol++;
  399.   if (rightrect_rightcol>=m_template_width) {
  400.     centercol++;
  401.     if (centercol>=m_template_width-1) {
  402.       leftrect_leftcol++;
  403.       if (leftrect_leftcol==m_template_width-2) {
  404. bottomrow++;
  405. if (bottomrow==m_template_height) {
  406.   toprow++;
  407.   if (toprow==m_template_height-1) {
  408.     return false;
  409.   }
  410.   bottomrow=toprow+1;
  411. }
  412. leftrect_leftcol=-1;
  413.       }
  414.       centercol=leftrect_leftcol+1;
  415.     }
  416.     rightrect_rightcol=centercol+1;
  417.   }
  418.   SetNonOverlap();
  419.   return true;
  420. }
  421. CIntegralFeature* CLeftRightIF::Copy() const
  422. {
  423.   return new CLeftRightIF(*this);
  424. }
  425. void CLeftRightIF::MakePartialFromCurrentForNumIncarnations(
  426.   featnum num)
  427. {
  428.   m_is_partial=true;
  429.   m_num_incarnations=num+1;
  430.   start_toprow=toprow;
  431.   start_bottomrow=bottomrow;
  432.   start_leftrect_leftcol=leftrect_leftcol;
  433.   start_centercol=centercol;
  434.   start_rightrect_rightcol=rightrect_rightcol;
  435.   m_remaining_incarnations=m_stop_after_num_incarnations=num;
  436. }
  437. /*
  438. void CLeftRightIF::Transform(const CFeatureTransformer& transformer)
  439. {
  440.   ASSERT(!m_is_partial);
  441.   transformer.TransformWidthHeight(&m_template_width, &m_template_height);
  442.   transformer.TransformCoordinate();
  443.   transformer.FeatureDone();
  444.   toprow=start_toprow;
  445.   bottomrow=start_bottomrow;
  446.   leftrect_leftcol=start_leftrect_leftcol;
  447.   centercol=start_centercol;
  448.   rightrect_rightcol=start_rightrect_rightcol;
  449. }
  450. */
  451. #ifdef USE_MFC
  452. void CLeftRightIF::Draw(CDC* pDC, int x_off, int y_off, int zoomfactor) const
  453. {
  454.   int ll = x_off + zoomfactor + leftrect_leftcol*zoomfactor;
  455.   int tr = y_off + zoomfactor + toprow*zoomfactor;
  456.   int cl = x_off + zoomfactor + centercol*zoomfactor;
  457.   int br = y_off + zoomfactor + bottomrow*zoomfactor;
  458.   int rr = x_off + zoomfactor + rightrect_rightcol*zoomfactor;
  459.   pDC->FillRect(CRect(ll, tr, cl, br), g_pBlackbrush);
  460.   pDC->Rectangle(cl, tr, rr, br);
  461. }
  462. #endif // USE_MFC
  463. ostream& CLeftRightIF::output(ostream& os) const
  464. {
  465.   os << "LeftRight " << toprow << "," << bottomrow << " x "
  466.      << leftrect_leftcol << "," << centercol << "," << rightrect_rightcol;
  467.   return os;
  468. }
  469. /////////////////////////////////////////////////////////////////////////////
  470. //
  471. // CUpDownIF classes implementation
  472. //
  473. /////////////////////////////////////////////////////////////////////////////
  474. CUpDownIF::CUpDownIF(int templateWidth, int templateHeight)
  475.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 
  476.      6*COST_GET+7*COST_ADD) 
  477. {
  478. }
  479. CUpDownIF::CUpDownIF(int templateWidth, int templateHeight,
  480.                      int _toprect_toprow, int _centerrow,
  481.                      int _bottomrect_bottomrow,
  482.                      int _leftcol, int _rightcol)
  483.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false,
  484.      6*COST_GET+7*COST_ADD) 
  485. {
  486.   toprect_toprow = _toprect_toprow;
  487.   centerrow = _centerrow;
  488.   bottomrect_bottomrow = _bottomrect_bottomrow;
  489.   leftcol = _leftcol;
  490.   rightcol = _rightcol;
  491.   SetNonOverlap();
  492. }
  493. CUpDownIF::CUpDownIF(const CUpDownIF& frm)
  494.   : CIntegralFeature(frm.m_template_width, frm.m_template_height,
  495.      frm.m_num_incarnations, frm.m_is_partial, 
  496.      6*COST_GET+7*COST_ADD) 
  497. {
  498.   toprect_toprow=frm.toprect_toprow;
  499.   centerrow=frm.centerrow;
  500.   bottomrect_bottomrow=frm.bottomrect_bottomrow;
  501.   leftcol=frm.leftcol;
  502.   rightcol=frm.rightcol;
  503.   if (m_is_partial) {
  504.     start_toprect_toprow=frm.start_toprect_toprow;
  505.     start_centerrow=frm.start_centerrow;
  506.     start_bottomrect_bottomrow=frm.start_bottomrect_bottomrow;
  507.     start_leftcol=frm.start_leftcol;
  508.     start_rightcol=frm.start_rightcol;
  509.     m_remaining_incarnations = frm.m_remaining_incarnations;
  510.     m_stop_after_num_incarnations = frm.m_stop_after_num_incarnations;
  511.   }
  512.   SetNonOverlap();
  513. }
  514. CUpDownIF::CUpDownIF(istream& is, int templateWidth, int templateHeight)
  515.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 
  516.      6*COST_GET+7*COST_ADD) 
  517. {
  518.   char a, b, c;
  519.   string str;
  520.   is >> toprect_toprow >> a >> centerrow >> b
  521.      >> bottomrect_bottomrow >> str >> leftcol >> c >> rightcol;
  522.   if (a!=',' || b!=',' || c!=',' || str!="x") {
  523.     char* buf = (char*) alloca((256+str.length())*sizeof(char));
  524.     sprintf(buf, "error during construction of UpDownIF (%c|%c|%c|%s)n",
  525.    a, b, c, str.c_str());
  526.     throw ITException(buf);
  527.   }
  528.   SetNonOverlap();
  529. }
  530. bool CUpDownIF::Equals(const CUpDownIF& frm) const
  531. {
  532.   bool equal = 
  533.     (toprect_toprow == frm.toprect_toprow &&
  534.      centerrow == frm.centerrow &&
  535.      bottomrect_bottomrow == frm.bottomrect_bottomrow &&
  536.      leftcol == frm.leftcol &&
  537.      rightcol == frm.rightcol);
  538.   return equal;
  539. }
  540. void CUpDownIF::SetNonOverlap() {
  541.   m_non_overlap =
  542.     ((centerrow-toprect_toprow) - (bottomrect_bottomrow-centerrow))
  543.     * (rightcol-leftcol);
  544. }
  545. II_TYPE CUpDownIF::Compute(const CIntegralImage& image) const
  546. {
  547. II_TYPE ceri = image.GetElement(rightcol, centerrow);
  548. II_TYPE cele = image.GetElement(leftcol, centerrow);
  549. II_TYPE val_toprect = 
  550. ceri
  551. - cele
  552. - image.GetElement(rightcol, toprect_toprow)
  553. + image.GetElement(leftcol, toprect_toprow);
  554. II_TYPE val_bottomrect = 
  555. image.GetElement(rightcol, bottomrect_bottomrow)
  556. - image.GetElement(leftcol, bottomrect_bottomrow)
  557. - ceri
  558. + cele;
  559. return val_toprect-val_bottomrect;
  560. }
  561. II_TYPE CUpDownIF::ComputeScaled(const CIntegralImage& image, II_TYPE mean, int left, int top) const
  562. {
  563. int placed_leftcol = left + scaled_leftcol;
  564. int placed_rightcol = left + scaled_rightcol;
  565. int placed_toprect_toprow = top + scaled_toprect_toprow;
  566. int placed_centerrow = top + scaled_centerrow;
  567. int placed_bottomrect_bottomrow = top + scaled_bottomrect_bottomrow;
  568. II_TYPE ceri = image.GetElement(placed_rightcol, placed_centerrow);
  569. II_TYPE cele = image.GetElement(placed_leftcol, placed_centerrow);
  570. II_TYPE val_toprect = 
  571. ceri
  572. - cele
  573. - image.GetElement(placed_rightcol, placed_toprect_toprow)
  574. + image.GetElement(placed_leftcol, placed_toprect_toprow);
  575. II_TYPE val_bottomrect = 
  576. image.GetElement(placed_rightcol, placed_bottomrect_bottomrow)
  577. - image.GetElement(placed_leftcol, placed_bottomrect_bottomrow)
  578. - ceri
  579. + cele;
  580. II_TYPE val = val_toprect-val_bottomrect;
  581. II_TYPE scaled_val = val/m_global_scale;
  582. II_TYPE mean_adjust = m_non_overlap*mean;
  583. return scaled_val-mean_adjust;
  584. }
  585. void CUpDownIF::Scale(II_TYPE scale_x, II_TYPE scale_y)
  586. {
  587. if (leftcol==-1) {
  588. scaled_leftcol = -1;
  589. scaled_rightcol = (int)((II_TYPE)(rightcol+1)*scale_x) - 1;
  590. } else {
  591. scaled_leftcol = (int)((II_TYPE)leftcol*scale_x);
  592. scaled_rightcol = (int)((II_TYPE)rightcol*scale_x);
  593. }
  594. if (toprect_toprow==-1) {
  595. scaled_toprect_toprow = -1;
  596. scaled_centerrow = (int)((II_TYPE)(centerrow+1)*scale_y) - 1;
  597. scaled_bottomrect_bottomrow = (int)((II_TYPE)(bottomrect_bottomrow-centerrow)*scale_y) + scaled_centerrow;
  598. } else {
  599. scaled_toprect_toprow = (int)((II_TYPE)toprect_toprow*scale_y);
  600. scaled_centerrow = (int)((II_TYPE)centerrow*scale_y);
  601. scaled_bottomrect_bottomrow = (int)((II_TYPE)bottomrect_bottomrow*scale_y);
  602. }
  603.   m_global_scale = scale_x*scale_y;
  604. }
  605. void CUpDownIF::EvenOutScales(II_TYPE* pScale_x, II_TYPE* pScale_y,
  606.         int /*scaled_template_width*/, int scaled_template_height)
  607. {
  608.   int toprect = centerrow-toprect_toprow;
  609.   int bottomrect = bottomrect_bottomrow-centerrow;
  610.   II_TYPE ratio = (II_TYPE)toprect/(II_TYPE)bottomrect;
  611.   int stoprect = scaled_centerrow-scaled_toprect_toprow;
  612.   int sbottomrect = scaled_bottomrect_bottomrow-scaled_centerrow;
  613.   II_TYPE sratio = (II_TYPE)stoprect/(II_TYPE)sbottomrect;
  614.   int scaled_height = scaled_bottomrect_bottomrow-toprect_toprow;
  615.   bool too_high = scaled_height > scaled_template_height;
  616.   while (!too_high && fabs(ratio-sratio)>=SCALE_DIFFERENCE_EPSILON) {
  617.     if (ratio<sratio) {
  618.       scaled_bottomrect_bottomrow++;
  619.       sbottomrect++;
  620.     } else {
  621.       scaled_centerrow++;
  622.       scaled_bottomrect_bottomrow++;
  623.       stoprect++;
  624.     }
  625.     scaled_height = scaled_bottomrect_bottomrow-toprect_toprow;
  626.     too_high = scaled_height > scaled_template_height;
  627.     sratio = (II_TYPE)stoprect/(II_TYPE)sbottomrect;
  628.   }
  629.   int overlap = scaled_bottomrect_bottomrow-scaled_template_height+1;
  630.   // overlap: by how much is bottommost too far down? 
  631.   // it must not be larger than scaled_template_height-1
  632.   if (overlap>0) {
  633.     // went outside template boundaries
  634.     if (too_high) {
  635.       // feature too big, use int scale
  636.       *pScale_y = floor(*pScale_y);
  637.       Scale(*pScale_x, *pScale_y);
  638.     } else {
  639.       // shift feature by overlap
  640.       scaled_toprect_toprow -= overlap;
  641.       scaled_centerrow -= overlap;
  642.       scaled_bottomrect_bottomrow -= overlap;
  643.       *pScale_y = sratio;
  644.     }
  645.   } else {
  646.     *pScale_y = sratio;
  647.   }
  648. }
  649. void CUpDownIF::SetToFirstIncarnation()
  650. {
  651.   if (m_is_partial) {
  652.     toprect_toprow=start_toprect_toprow;
  653.     centerrow=start_centerrow;
  654.     bottomrect_bottomrow=start_bottomrect_bottomrow;
  655.     leftcol=start_leftcol;
  656.     rightcol=start_rightcol;
  657.     m_remaining_incarnations=m_stop_after_num_incarnations;
  658.   } else {
  659.     toprect_toprow=-1;
  660.     centerrow=0;
  661.     bottomrect_bottomrow=1;
  662.     leftcol=-1;
  663.     rightcol=0;
  664.   }
  665.   SetNonOverlap();
  666. }
  667. bool CUpDownIF::SetToNextIncarnation()
  668. {
  669. if (m_is_partial) {
  670. if (m_remaining_incarnations) {
  671. m_remaining_incarnations--;
  672. } else {
  673. return false;
  674. }
  675. }
  676. bottomrect_bottomrow++;
  677. if (bottomrect_bottomrow>=m_template_height) {
  678. centerrow++;
  679. if (centerrow>=m_template_height-1) {
  680. toprect_toprow++;
  681. if (toprect_toprow==m_template_height-2) {
  682. rightcol++;
  683. if (rightcol==m_template_width) {
  684. leftcol++;
  685. if (leftcol==m_template_width-1) {
  686. return false;
  687. }
  688. rightcol=leftcol+1;
  689. }
  690. toprect_toprow=-1;
  691. }
  692. centerrow=toprect_toprow+1;
  693. }
  694. bottomrect_bottomrow=centerrow+1;
  695. }
  696.     SetNonOverlap();
  697. return true;
  698. }
  699. CIntegralFeature* CUpDownIF::Copy() const
  700. {
  701. return new CUpDownIF(*this);
  702. }
  703. void CUpDownIF::MakePartialFromCurrentForNumIncarnations(
  704.   featnum num)
  705. {
  706.   m_is_partial=true;
  707.   m_num_incarnations=num+1;
  708.   start_toprect_toprow=toprect_toprow;
  709.   start_centerrow=centerrow;
  710.   start_bottomrect_bottomrow=bottomrect_bottomrow;
  711.   start_leftcol=leftcol;
  712.   start_rightcol=rightcol;
  713.   m_remaining_incarnations=m_stop_after_num_incarnations=num;
  714. }
  715. #ifdef USE_MFC
  716. void CUpDownIF::Draw(CDC* pDC, int x_off, int y_off, int zoomfactor) const
  717. {
  718. int lc = x_off + zoomfactor + leftcol*zoomfactor;
  719. int tt = y_off + zoomfactor + toprect_toprow*zoomfactor;
  720. int rc = x_off + zoomfactor + rightcol*zoomfactor;
  721. int cr = y_off + zoomfactor + centerrow*zoomfactor;
  722. int bb = y_off + zoomfactor + bottomrect_bottomrow*zoomfactor;
  723. pDC->FillRect(CRect(lc, tt, rc, cr), g_pBlackbrush);
  724. pDC->Rectangle(lc, cr, rc, bb);
  725. }
  726. #endif // USE_MFC
  727. ostream& CUpDownIF::output(ostream& os) const
  728. {
  729.   os << "UpDown " << toprect_toprow << "," << centerrow 
  730.      << "," << bottomrect_bottomrow << " x "
  731.      << leftcol << "," << rightcol;
  732.   return os;
  733. }
  734. /////////////////////////////////////////////////////////////////////////////
  735. //
  736. // CLeftCenterRightIF classes implementation
  737. //
  738. /////////////////////////////////////////////////////////////////////////////
  739. CLeftCenterRightIF::CLeftCenterRightIF(int templateWidth, int templateHeight)
  740.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 8*COST_GET+10*COST_ADD) 
  741. {
  742. }
  743. CLeftCenterRightIF::CLeftCenterRightIF(int templateWidth, int templateHeight,
  744.                                        int _toprow, int _bottomrow,
  745.                                        int _leftrect_leftcol, int _leftrect_rightcol,
  746.                                        int _rightrect_leftcol,
  747.                                        int _rightrect_rightcol)
  748.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 8*COST_GET+10*COST_ADD) 
  749. {
  750.   toprow = _toprow;
  751.   bottomrow = _bottomrow;
  752.   leftrect_leftcol = _leftrect_leftcol;
  753.   leftrect_rightcol = _leftrect_rightcol;
  754.   rightrect_leftcol = _rightrect_leftcol;
  755.   rightrect_rightcol = _rightrect_rightcol;
  756.   SetNonOverlap();
  757. }
  758. CLeftCenterRightIF::CLeftCenterRightIF(const CLeftCenterRightIF& frm)
  759.   : CIntegralFeature(frm.m_template_width, frm.m_template_height,
  760.      frm.m_num_incarnations, frm.m_is_partial, 8*COST_GET+10*COST_ADD) 
  761. {
  762.   toprow=frm.toprow;
  763.   bottomrow=frm.bottomrow;
  764.   leftrect_leftcol=frm.leftrect_leftcol;
  765.   leftrect_rightcol=frm.leftrect_rightcol;
  766.   rightrect_leftcol=frm.rightrect_leftcol;
  767.   rightrect_rightcol=frm.rightrect_rightcol;
  768.   if (m_is_partial) {
  769.     start_toprow=frm.start_toprow;
  770.     start_bottomrow=frm.start_bottomrow;
  771.     start_leftrect_leftcol=frm.start_leftrect_leftcol;
  772.     start_leftrect_rightcol=frm.start_leftrect_rightcol;
  773.     start_rightrect_leftcol=frm.start_rightrect_leftcol;
  774.     start_rightrect_rightcol=frm.start_rightrect_rightcol;
  775.     m_remaining_incarnations = frm.m_remaining_incarnations;
  776.     m_stop_after_num_incarnations = frm.m_stop_after_num_incarnations;
  777.   }
  778.   SetNonOverlap();
  779. }
  780. CLeftCenterRightIF::CLeftCenterRightIF(istream& is, int templateWidth, int templateHeight)
  781.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 8*COST_GET+10*COST_ADD) 
  782. {
  783.   char a, b, c;
  784.   string strx, strslash;
  785.   is >> toprow >> a >> bottomrow >> strx 
  786.      >> leftrect_leftcol >> b >> leftrect_rightcol >> strslash
  787.      >> rightrect_leftcol >> c >> rightrect_rightcol;
  788.   if (a!=',' || b!=',' || c!=',' || strx!="x" || strslash!="/") {
  789.     char* buf = (char*) alloca((256+strx.length()+strslash.length())*sizeof(char));
  790.     sprintf(buf, "error during construction of LeftCenterRightIF (%c|%c|%c|%s|%s)n",
  791.    a, b, c, strx.c_str(), strslash.c_str());
  792.     throw ITException(buf);
  793.   }
  794.   SetNonOverlap();
  795. }
  796. bool CLeftCenterRightIF::Equals(const CLeftCenterRightIF& frm) const
  797. {
  798.   bool equal = 
  799.     (toprow == frm.toprow &&
  800.      bottomrow == frm.bottomrow &&
  801.      leftrect_leftcol == frm.leftrect_leftcol &&
  802.      leftrect_rightcol == frm.leftrect_rightcol &&
  803.      rightrect_leftcol == frm.rightrect_leftcol &&
  804.      rightrect_rightcol == frm.rightrect_rightcol);
  805.   return equal;
  806. }
  807. void CLeftCenterRightIF::SetNonOverlap() {
  808.   m_non_overlap = 
  809.     ((leftrect_rightcol-leftrect_leftcol) 
  810.      - (rightrect_leftcol-leftrect_rightcol)
  811.      + (rightrect_rightcol-rightrect_leftcol)) * (bottomrow-toprow);
  812. }
  813. II_TYPE CLeftCenterRightIF::Compute(const CIntegralImage& image) const
  814. {
  815. II_TYPE botleri = image.GetElement(leftrect_rightcol, bottomrow);
  816. II_TYPE topleri = image.GetElement(leftrect_rightcol, toprow);
  817. II_TYPE botrile = image.GetElement(rightrect_leftcol, bottomrow);
  818. II_TYPE toprile = image.GetElement(rightrect_leftcol, toprow);
  819. II_TYPE val_leftrect = 
  820. botleri
  821. - image.GetElement(leftrect_leftcol, bottomrow)
  822. - topleri
  823. + image.GetElement(leftrect_leftcol, toprow);
  824. II_TYPE val_centerrect = 
  825. botrile
  826. - botleri
  827. - toprile
  828. + topleri;
  829. II_TYPE val_rightrect = 
  830. image.GetElement(rightrect_rightcol, bottomrow)
  831. - botrile
  832. - image.GetElement(rightrect_rightcol, toprow)
  833. + toprile;
  834. return val_leftrect-val_centerrect+val_rightrect;
  835. }
  836. II_TYPE CLeftCenterRightIF::ComputeScaled(const CIntegralImage& image, II_TYPE mean, int left, int top) const
  837. {
  838. int placed_leftrect_leftcol = left + scaled_leftrect_leftcol;
  839. int placed_leftrect_rightcol = left + scaled_leftrect_rightcol;
  840. int placed_rightrect_leftcol= left + scaled_rightrect_leftcol;
  841. int placed_rightrect_rightcol = left + scaled_rightrect_rightcol;
  842. int placed_toprow = top + scaled_toprow;
  843. int placed_bottomrow = top + scaled_bottomrow;
  844. II_TYPE botleri = image.GetElement(placed_leftrect_rightcol, placed_bottomrow);
  845. II_TYPE topleri = image.GetElement(placed_leftrect_rightcol, placed_toprow);
  846. II_TYPE botrile = image.GetElement(placed_rightrect_leftcol, placed_bottomrow);
  847. II_TYPE toprile = image.GetElement(placed_rightrect_leftcol, placed_toprow);
  848. II_TYPE val_leftrect = 
  849. botleri
  850. - image.GetElement(placed_leftrect_leftcol, placed_bottomrow)
  851. - topleri
  852. + image.GetElement(placed_leftrect_leftcol, placed_toprow);
  853. II_TYPE val_centerrect = 
  854. botrile
  855. - botleri
  856. - toprile
  857. + topleri;
  858. II_TYPE val_rightrect = 
  859. image.GetElement(placed_rightrect_rightcol, placed_bottomrow)
  860. - botrile
  861. - image.GetElement(placed_rightrect_rightcol, placed_toprow)
  862. + toprile;
  863. II_TYPE val = val_leftrect-val_centerrect+val_rightrect;
  864. II_TYPE scaled_val = val/m_global_scale;
  865. II_TYPE mean_adjust = m_non_overlap*mean;
  866. return scaled_val-mean_adjust;
  867. }
  868. void CLeftCenterRightIF::Scale(II_TYPE scale_x, II_TYPE scale_y)
  869. {
  870. if (leftrect_leftcol==-1) {
  871. scaled_leftrect_leftcol = -1;
  872. scaled_leftrect_rightcol = (int)((II_TYPE)(leftrect_rightcol+1)*scale_x) -1;
  873. scaled_rightrect_leftcol= (int)((II_TYPE)(rightrect_leftcol-leftrect_rightcol)*scale_x) + scaled_leftrect_rightcol;
  874. scaled_rightrect_rightcol = (int)((II_TYPE)(rightrect_rightcol-rightrect_leftcol)*scale_x) + scaled_rightrect_leftcol;
  875. } else {
  876. scaled_leftrect_leftcol = (int)((II_TYPE)leftrect_leftcol*scale_x);
  877. scaled_leftrect_rightcol = (int)((II_TYPE)leftrect_rightcol*scale_x);
  878. scaled_rightrect_leftcol= (int)((II_TYPE)rightrect_leftcol*scale_x);
  879. scaled_rightrect_rightcol = (int)((II_TYPE)rightrect_rightcol*scale_x);
  880. }
  881. if (toprow==-1) {
  882. scaled_toprow = (int)((II_TYPE)(toprow+1)*scale_y) -1;
  883. scaled_bottomrow = (int)((II_TYPE)(bottomrow-toprow)*scale_y) + scaled_toprow;
  884. } else {
  885. scaled_toprow = (int)((II_TYPE)toprow*scale_y);
  886. scaled_bottomrow = (int)((II_TYPE)bottomrow*scale_y);
  887. }
  888.   m_global_scale = scale_x*scale_y;
  889. }
  890. void CLeftCenterRightIF::EvenOutScales(II_TYPE* pScale_x, II_TYPE* pScale_y,
  891.         int scaled_template_width, int /*scaled_template_height*/)
  892. {
  893.   int leftrect = leftrect_rightcol-leftrect_leftcol;
  894.   int midrect = rightrect_leftcol-leftrect_rightcol;
  895.   int rightrect = rightrect_rightcol-rightrect_leftcol;
  896.   II_TYPE ratio1 = (II_TYPE)leftrect/(II_TYPE)midrect;
  897.   II_TYPE ratio2 = (II_TYPE)midrect/(II_TYPE)rightrect;
  898.   int sleftrect = scaled_leftrect_rightcol-scaled_leftrect_leftcol;
  899.   int smidrect = scaled_rightrect_leftcol-scaled_leftrect_rightcol;
  900.   int srightrect = scaled_rightrect_rightcol-scaled_rightrect_leftcol;
  901.   II_TYPE sratio1 = (II_TYPE)sleftrect/(II_TYPE)smidrect;
  902.   II_TYPE sratio2 = (II_TYPE)smidrect/(II_TYPE)srightrect;
  903.   int scaled_width = scaled_rightrect_rightcol-scaled_leftrect_leftcol;
  904.   bool too_wide = scaled_width > scaled_template_width;
  905.   while (!too_wide && 
  906.  (fabs(ratio1-sratio1)>=SCALE_DIFFERENCE_EPSILON
  907.   || fabs(ratio2-sratio2)>=SCALE_DIFFERENCE_EPSILON)) {
  908.     if (ratio1<sratio1) {
  909.       scaled_rightrect_leftcol++;
  910.       scaled_rightrect_rightcol++;
  911.       smidrect++;
  912.     } else if (ratio1>sratio1) {
  913.       scaled_leftrect_rightcol++;
  914.       scaled_rightrect_leftcol++;
  915.       scaled_rightrect_rightcol++;
  916.       sleftrect++;
  917.     } else if (ratio2<sratio2) {
  918.       scaled_rightrect_rightcol++;
  919.       srightrect++;
  920.     } else {
  921.       ASSERT(ratio2>sratio2);
  922.       scaled_rightrect_leftcol++;
  923.       scaled_rightrect_rightcol++;
  924.       smidrect++;
  925.     }
  926.     scaled_width = scaled_rightrect_rightcol-scaled_leftrect_leftcol;
  927.     too_wide = scaled_width > scaled_template_width;
  928.     sratio1 = (II_TYPE)sleftrect/(II_TYPE)smidrect;
  929.     sratio2 = (II_TYPE)smidrect/(II_TYPE)srightrect;
  930.   }
  931.   ASSERT(too_wide || fabs((II_TYPE)leftrect/(II_TYPE)rightrect
  932.               -(II_TYPE)sleftrect/(II_TYPE)srightrect)<SCALE_DIFFERENCE_EPSILON);
  933.   int overlap = scaled_rightrect_rightcol-scaled_template_width+1;
  934.   // overlap: by how much is rightmost too far to the right? 
  935.   // it must not be larger than scaled_template_width-1
  936.   if (overlap>0) {
  937.     // went outside template boundaries
  938.     if (too_wide) {
  939.       // feature too big, use int scale
  940.       *pScale_x = floor(*pScale_x);
  941.       Scale(*pScale_x, *pScale_y);
  942.     } else {
  943.       // shift feature by overlap
  944.       scaled_leftrect_leftcol -= overlap;
  945.       scaled_leftrect_rightcol -= overlap;
  946.       scaled_rightrect_leftcol -= overlap;
  947.       scaled_rightrect_rightcol -= overlap;
  948.       *pScale_x = sratio1;
  949.     }
  950.   } else {
  951.     *pScale_x = sratio1;
  952.   }
  953. }
  954. void CLeftCenterRightIF::SetToFirstIncarnation()
  955. {
  956.   if (m_is_partial) {
  957.     toprow=start_toprow;
  958.     bottomrow=start_bottomrow;
  959.     leftrect_leftcol=start_leftrect_leftcol;
  960.     leftrect_rightcol=start_leftrect_rightcol;
  961.     rightrect_leftcol=start_rightrect_leftcol;
  962.     rightrect_rightcol=start_rightrect_rightcol;
  963.     m_remaining_incarnations=m_stop_after_num_incarnations;
  964.   } else {
  965.     toprow=-1;
  966.     bottomrow=0;
  967.     leftrect_leftcol=-1;
  968.     leftrect_rightcol=0;
  969.     rightrect_leftcol=1;
  970.     rightrect_rightcol=2;
  971.   }
  972.   SetNonOverlap();
  973. }
  974. bool CLeftCenterRightIF::SetToNextIncarnation()
  975. {
  976. if (m_is_partial) {
  977. if (m_remaining_incarnations) {
  978. m_remaining_incarnations--;
  979. } else {
  980. return false;
  981. }
  982. }
  983. rightrect_rightcol++;
  984. if (rightrect_rightcol>=m_template_width) {
  985. rightrect_leftcol++;
  986. if (rightrect_leftcol>=m_template_width-1) {
  987. leftrect_rightcol++;
  988. if (leftrect_rightcol>=m_template_width-2) {
  989. leftrect_leftcol++;
  990. if (leftrect_leftcol==m_template_width-3) {
  991. bottomrow++;
  992. if (bottomrow==m_template_height) {
  993. toprow++;
  994. if (toprow==m_template_height-1) {
  995. return false;
  996. }
  997. bottomrow=toprow+1;
  998. }
  999. leftrect_leftcol=0;
  1000. }
  1001. leftrect_rightcol=leftrect_leftcol+1;
  1002. }
  1003. rightrect_leftcol=leftrect_rightcol+1;
  1004. }
  1005. rightrect_rightcol=rightrect_leftcol+1;
  1006. }
  1007.     SetNonOverlap();
  1008. return true;
  1009. }
  1010. void CLeftCenterRightIF::MakePartialFromCurrentForNumIncarnations(
  1011.   featnum num)
  1012. {
  1013.   m_is_partial=true;
  1014.   m_num_incarnations=num+1;
  1015.   start_toprow=toprow;
  1016.   start_bottomrow=bottomrow;
  1017.   start_leftrect_leftcol=leftrect_leftcol;
  1018.   start_leftrect_rightcol=leftrect_rightcol;
  1019.   start_rightrect_leftcol=rightrect_leftcol;
  1020.   start_rightrect_rightcol=rightrect_rightcol;
  1021.   m_remaining_incarnations=m_stop_after_num_incarnations=num;
  1022. }
  1023. CIntegralFeature* CLeftCenterRightIF::Copy() const 
  1024. {
  1025.   return new CLeftCenterRightIF(*this);
  1026. }
  1027. #ifdef USE_MFC
  1028. void CLeftCenterRightIF::Draw(CDC* pDC, int x_off, int y_off, int zoomfactor) const
  1029. {
  1030.   int tr = y_off + zoomfactor + toprow*zoomfactor;
  1031.   int br = y_off + zoomfactor + bottomrow*zoomfactor;
  1032.   int ll = x_off + zoomfactor + leftrect_leftcol*zoomfactor;
  1033.   int lr = x_off + zoomfactor + leftrect_rightcol*zoomfactor;
  1034.   int rl = x_off + zoomfactor + rightrect_leftcol*zoomfactor;
  1035.   int rr = x_off + zoomfactor + rightrect_rightcol*zoomfactor;
  1036. pDC->FillRect(CRect(ll, tr, lr, br), g_pBlackbrush);
  1037. pDC->Rectangle(lr, tr, rl, br);
  1038. pDC->FillRect(CRect(rl, tr, rr, br), g_pBlackbrush);
  1039. }
  1040. #endif // USE_MFC
  1041. ostream& CLeftCenterRightIF::output(ostream& os) const
  1042. {
  1043.   os << "LeftCenterRight " << toprow << "," << bottomrow << " x "
  1044.      << leftrect_leftcol << "," << leftrect_rightcol << " / "
  1045.      << rightrect_leftcol << "," << rightrect_rightcol;
  1046.   return os;
  1047. }
  1048. /////////////////////////////////////////////////////////////////////////////
  1049. //
  1050. // CSevenColumnsIF classes implementation
  1051. //
  1052. /////////////////////////////////////////////////////////////////////////////
  1053. CSevenColumnsIF::CSevenColumnsIF(int templateWidth, int templateHeight)
  1054.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 16*COST_GET+27*COST_ADD) 
  1055. {
  1056. }
  1057. CSevenColumnsIF::CSevenColumnsIF(int templateWidth, int templateHeight,
  1058.                                  int _toprow, int _bottomrow,
  1059.                                  int _1, int _2, int _3, int _4, int _5, int _6,
  1060.                                  int _7, int _8)
  1061.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 16*COST_GET+27*COST_ADD) 
  1062. {
  1063.   toprow = _toprow;
  1064.   bottomrow = _bottomrow;
  1065.   col1_left = _1;
  1066.   col2_left = _2;
  1067.   col3_left = _3;
  1068.   col4_left = _4;
  1069.   col5_left = _5;
  1070.   col6_left = _6;
  1071.   col7_left = _7;
  1072.   col7_right = _8;
  1073.   SetNonOverlap();
  1074. }
  1075. CSevenColumnsIF::CSevenColumnsIF(const CSevenColumnsIF& frm)
  1076.   : CIntegralFeature(frm.m_template_width, frm.m_template_height,
  1077.      frm.m_num_incarnations, frm.m_is_partial, 16*COST_GET+27*COST_ADD) 
  1078. {
  1079.   toprow = frm.toprow;
  1080.   bottomrow = frm.bottomrow;
  1081.   col1_left = frm.col1_left;
  1082.   col2_left = frm.col2_left;
  1083.   col3_left = frm.col3_left;
  1084.   col4_left = frm.col4_left;
  1085.   col5_left = frm.col5_left;
  1086.   col6_left = frm.col6_left;
  1087.   col7_left = frm.col7_left;
  1088.   col7_right = frm.col7_right;
  1089.   if (m_is_partial) {
  1090.     start_toprow = frm.start_toprow;
  1091.     start_bottomrow = frm.start_bottomrow;
  1092.     start_col1_left = frm.start_col1_left;
  1093.     start_col2_left = frm.start_col2_left;
  1094.     start_col3_left = frm.start_col3_left;
  1095.     start_col4_left = frm.start_col4_left;
  1096.     start_col5_left = frm.start_col5_left;
  1097.     start_col6_left = frm.start_col6_left;
  1098.     start_col7_left = frm.start_col7_left;
  1099.     start_col7_right = frm.start_col7_right;
  1100.     m_remaining_incarnations = frm.m_remaining_incarnations;
  1101.     m_stop_after_num_incarnations = frm.m_stop_after_num_incarnations;
  1102.   }
  1103.   SetNonOverlap();
  1104. }
  1105. CSevenColumnsIF::CSevenColumnsIF(istream& is, int template_width, int template_height)
  1106.   : CIntegralFeature(template_width, template_height, IT_INVALID_FEATURE, 0, 16*COST_GET+27*COST_ADD)
  1107. {
  1108.   char a, b, c, d, e, f, g, h;
  1109.   string str;
  1110.   is >> toprow >> a >> bottomrow >> str
  1111.      >> col1_left >> b >> col2_left >> c >> col3_left >> d >> col4_left >> e
  1112.      >> col5_left >> f >> col6_left >> g >> col7_left >> h >> col7_right; 
  1113.   if (a!=',' || b!=',' || c!=',' || d!=',' || e!=',' || f!=',' || g!=',' || h!=',' || str!="x") {
  1114.     char* buf = (char*) alloca((256+str.length())*sizeof(char));
  1115.     sprintf(buf, "error during construction of SevenColumnsIF (%c|%c|%c|%c|%c|%c|%c|%c|%s)n",
  1116.    a, b, c, d, e, f, g, h, str.c_str());
  1117.     throw ITException(buf);
  1118.   }
  1119.   SetNonOverlap();
  1120. }
  1121. bool CSevenColumnsIF::Equals(const CSevenColumnsIF& frm) const
  1122. {
  1123.   bool equal = 
  1124.     (toprow == frm.toprow &&
  1125.      bottomrow == frm.bottomrow &&
  1126.      col1_left == frm.col1_left &&
  1127.      col2_left == frm.col2_left &&
  1128.      col3_left == frm.col3_left &&
  1129.      col4_left == frm.col4_left &&
  1130.      col5_left == frm.col5_left &&
  1131.      col6_left == frm.col6_left &&
  1132.      col7_left == frm.col7_left &&
  1133.      col7_right == frm.col7_right);
  1134.   return equal;
  1135. }
  1136. void CSevenColumnsIF::SetNonOverlap() {
  1137.   m_non_overlap =
  1138.     ((col2_left-col1_left) - (col3_left-col2_left) 
  1139.      + (col4_left-col3_left) - (col5_left-col4_left)
  1140.      + (col6_left-col5_left) - (col7_left-col6_left)
  1141.      + (col7_right-col7_left)
  1142.      )
  1143.     * (bottomrow-toprow);
  1144. }
  1145. II_TYPE CSevenColumnsIF::Compute(const CIntegralImage& image) const
  1146. {
  1147. II_TYPE bot_col1_left = image.GetElement(col1_left, bottomrow);
  1148. II_TYPE top_col1_left = image.GetElement(col1_left, toprow);
  1149. II_TYPE bot_col2_left = image.GetElement(col2_left, bottomrow);
  1150. II_TYPE top_col2_left = image.GetElement(col2_left, toprow);
  1151. II_TYPE bot_col3_left = image.GetElement(col3_left, bottomrow);
  1152. II_TYPE top_col3_left = image.GetElement(col3_left, toprow);
  1153. II_TYPE bot_col4_left = image.GetElement(col4_left, bottomrow);
  1154. II_TYPE top_col4_left = image.GetElement(col4_left, toprow);
  1155. II_TYPE bot_col5_left = image.GetElement(col5_left, bottomrow);
  1156. II_TYPE top_col5_left = image.GetElement(col5_left, toprow);
  1157. II_TYPE bot_col6_left = image.GetElement(col6_left, bottomrow);
  1158. II_TYPE top_col6_left = image.GetElement(col6_left, toprow);
  1159. II_TYPE bot_col7_left = image.GetElement(col7_left, bottomrow);
  1160. II_TYPE top_col7_left = image.GetElement(col7_left, toprow);
  1161. II_TYPE bot_col7_right= image.GetElement(col7_right,bottomrow);
  1162. II_TYPE top_col7_right= image.GetElement(col7_right,toprow);
  1163. II_TYPE val_col1 = bot_col2_left - bot_col1_left - top_col2_left + top_col1_left;
  1164. II_TYPE val_col2 = bot_col3_left - bot_col2_left - top_col3_left + top_col2_left;
  1165. II_TYPE val_col3 = bot_col4_left - bot_col3_left - top_col4_left + top_col3_left;
  1166. II_TYPE val_col4 = bot_col5_left - bot_col4_left - top_col5_left + top_col4_left;
  1167. II_TYPE val_col5 = bot_col6_left - bot_col5_left - top_col6_left + top_col5_left;
  1168. II_TYPE val_col6 = bot_col7_left - bot_col6_left - top_col7_left + top_col6_left;
  1169. II_TYPE val_col7 = bot_col7_right- bot_col7_left - top_col7_right+ top_col7_left;
  1170. return val_col1-val_col2+val_col3-val_col4+val_col5-val_col6+val_col7;
  1171. }
  1172. II_TYPE CSevenColumnsIF::ComputeScaled(const CIntegralImage& image, II_TYPE mean, int left, int top) const
  1173. {
  1174. int placed_toprow = top + scaled_toprow;
  1175. int placed_bottomrow = top + scaled_bottomrow;
  1176. int placed_col1_left = left + scaled_col1_left;
  1177. int placed_col2_left = left + scaled_col2_left;
  1178. int placed_col3_left = left + scaled_col3_left;
  1179. int placed_col4_left = left + scaled_col4_left;
  1180. int placed_col5_left = left + scaled_col5_left;
  1181. int placed_col6_left = left + scaled_col6_left;
  1182. int placed_col7_left = left + scaled_col7_left;
  1183. int placed_col7_right= left + scaled_col7_right;
  1184. II_TYPE bot_col1_left = image.GetElement(placed_col1_left, placed_bottomrow);
  1185. II_TYPE top_col1_left = image.GetElement(placed_col1_left, placed_toprow);
  1186. II_TYPE bot_col2_left = image.GetElement(placed_col2_left, placed_bottomrow);
  1187. II_TYPE top_col2_left = image.GetElement(placed_col2_left, placed_toprow);
  1188. II_TYPE bot_col3_left = image.GetElement(placed_col3_left, placed_bottomrow);
  1189. II_TYPE top_col3_left = image.GetElement(placed_col3_left, placed_toprow);
  1190. II_TYPE bot_col4_left = image.GetElement(placed_col4_left, placed_bottomrow);
  1191. II_TYPE top_col4_left = image.GetElement(placed_col4_left, placed_toprow);
  1192. II_TYPE bot_col5_left = image.GetElement(placed_col5_left, placed_bottomrow);
  1193. II_TYPE top_col5_left = image.GetElement(placed_col5_left, placed_toprow);
  1194. II_TYPE bot_col6_left = image.GetElement(placed_col6_left, placed_bottomrow);
  1195. II_TYPE top_col6_left = image.GetElement(placed_col6_left, placed_toprow);
  1196. II_TYPE bot_col7_left = image.GetElement(placed_col7_left, placed_bottomrow);
  1197. II_TYPE top_col7_left = image.GetElement(placed_col7_left, placed_toprow);
  1198. II_TYPE bot_col7_right= image.GetElement(placed_col7_right,placed_bottomrow);
  1199. II_TYPE top_col7_right= image.GetElement(placed_col7_right,placed_toprow);
  1200. II_TYPE val_col1 = bot_col2_left - bot_col1_left - top_col2_left + top_col1_left;
  1201. II_TYPE val_col2 = bot_col3_left - bot_col2_left - top_col3_left + top_col2_left;
  1202. II_TYPE val_col3 = bot_col4_left - bot_col3_left - top_col4_left + top_col3_left;
  1203. II_TYPE val_col4 = bot_col5_left - bot_col4_left - top_col5_left + top_col4_left;
  1204. II_TYPE val_col5 = bot_col6_left - bot_col5_left - top_col6_left + top_col5_left;
  1205. II_TYPE val_col6 = bot_col7_left - bot_col6_left - top_col7_left + top_col6_left;
  1206. II_TYPE val_col7 = bot_col7_right- bot_col7_left - top_col7_right+ top_col7_left;
  1207. II_TYPE val = val_col1-val_col2+val_col3-val_col4+val_col5-val_col6+val_col7;
  1208. II_TYPE scaled_val = val/m_global_scale;
  1209. II_TYPE mean_adjust = m_non_overlap*mean;
  1210. return scaled_val-mean_adjust;
  1211. }
  1212. void CSevenColumnsIF::Scale(II_TYPE scale_x, II_TYPE scale_y)
  1213. {
  1214. if (toprow==-1) {
  1215. scaled_toprow = -1;
  1216. scaled_bottomrow = (int)((II_TYPE)(bottomrow+1)*scale_y) - 1;
  1217. } else {
  1218. scaled_toprow = (int)((II_TYPE)toprow*scale_y);
  1219. scaled_bottomrow = (int)((II_TYPE)bottomrow*scale_y);
  1220. }
  1221. if (col1_left==-1) {
  1222. scaled_col1_left = -1;
  1223. scaled_col2_left = (int)((II_TYPE)(col2_left+1)*scale_x) - 1;
  1224. scaled_col3_left = (int)((II_TYPE)(col3_left-col2_left)*scale_x) + scaled_col2_left;
  1225. scaled_col4_left = (int)((II_TYPE)(col4_left-col3_left)*scale_x) + scaled_col3_left;
  1226. scaled_col5_left = (int)((II_TYPE)(col5_left-col4_left)*scale_x) + scaled_col4_left;
  1227. scaled_col6_left = (int)((II_TYPE)(col6_left-col5_left)*scale_x) + scaled_col5_left;
  1228. scaled_col7_left = (int)((II_TYPE)(col7_left-col6_left)*scale_x) + scaled_col6_left;
  1229. scaled_col7_right= (int)((II_TYPE)(col7_right-col7_left)*scale_x) + scaled_col7_left;
  1230. } else {
  1231. scaled_col1_left = (int)((II_TYPE)col1_left*scale_x);
  1232. scaled_col2_left = (int)((II_TYPE)col2_left*scale_x);
  1233. scaled_col3_left = (int)((II_TYPE)col3_left*scale_x);
  1234. scaled_col4_left = (int)((II_TYPE)col4_left*scale_x);
  1235. scaled_col5_left = (int)((II_TYPE)col5_left*scale_x);
  1236. scaled_col6_left = (int)((II_TYPE)col6_left*scale_x);
  1237. scaled_col7_left = (int)((II_TYPE)col7_left*scale_x);
  1238. scaled_col7_right= (int)((II_TYPE)col7_right*scale_x);
  1239. }
  1240.   m_global_scale = scale_x*scale_y;
  1241. }
  1242. void CSevenColumnsIF::EvenOutScales(II_TYPE* pScale_x, II_TYPE* pScale_y,
  1243.         int scaled_template_width, int /*scaled_template_height*/)
  1244. {
  1245.   int rect1 = col2_left-col1_left;
  1246.   int rect2 = col3_left-col2_left;
  1247.   int rect3 = col4_left-col3_left;
  1248.   int rect4 = col5_left-col4_left;
  1249.   int rect5 = col6_left-col5_left;
  1250.   int rect6 = col7_left-col6_left;
  1251.   int rect7 = col7_right-col7_left;
  1252.   II_TYPE ratio1 = (II_TYPE)rect1/(II_TYPE)rect2;
  1253.   II_TYPE ratio2 = (II_TYPE)rect2/(II_TYPE)rect3;
  1254.   II_TYPE ratio3 = (II_TYPE)rect3/(II_TYPE)rect4;
  1255.   II_TYPE ratio4 = (II_TYPE)rect4/(II_TYPE)rect5;
  1256.   II_TYPE ratio5 = (II_TYPE)rect5/(II_TYPE)rect6;
  1257.   II_TYPE ratio6 = (II_TYPE)rect6/(II_TYPE)rect7;
  1258.   int srect1 = scaled_col2_left-scaled_col1_left;
  1259.   int srect2 = scaled_col3_left-scaled_col2_left;
  1260.   int srect3 = scaled_col4_left-scaled_col3_left;
  1261.   int srect4 = scaled_col5_left-scaled_col4_left;
  1262.   int srect5 = scaled_col6_left-scaled_col5_left;
  1263.   int srect6 = scaled_col7_left-scaled_col6_left;
  1264.   int srect7 = scaled_col7_right-scaled_col7_left;
  1265.   II_TYPE sratio1 = (II_TYPE)srect1/(II_TYPE)srect2;
  1266.   II_TYPE sratio2 = (II_TYPE)srect2/(II_TYPE)srect3;
  1267.   II_TYPE sratio3 = (II_TYPE)srect3/(II_TYPE)srect4;
  1268.   II_TYPE sratio4 = (II_TYPE)srect4/(II_TYPE)srect5;
  1269.   II_TYPE sratio5 = (II_TYPE)srect5/(II_TYPE)srect6;
  1270.   II_TYPE sratio6 = (II_TYPE)srect6/(II_TYPE)srect7;
  1271.   int scaled_width = scaled_col7_right-scaled_col1_left;
  1272.   bool too_wide = scaled_width > scaled_template_width;
  1273.   while (!too_wide && 
  1274.  (fabs(ratio1-sratio1)>=SCALE_DIFFERENCE_EPSILON
  1275.   || fabs(ratio2-sratio2)>=SCALE_DIFFERENCE_EPSILON
  1276.   || fabs(ratio3-sratio3)>=SCALE_DIFFERENCE_EPSILON
  1277.   || fabs(ratio4-sratio4)>=SCALE_DIFFERENCE_EPSILON
  1278.   || fabs(ratio5-sratio5)>=SCALE_DIFFERENCE_EPSILON
  1279.   || fabs(ratio6-sratio6)>=SCALE_DIFFERENCE_EPSILON)) {
  1280.     if (ratio1>sratio1) {
  1281.       scaled_col2_left++;
  1282.       scaled_col3_left++;
  1283.       scaled_col4_left++;
  1284.       scaled_col5_left++;
  1285.       scaled_col6_left++;
  1286.       scaled_col7_left++;
  1287.       scaled_col7_right++;
  1288.       srect1++;
  1289.     } else if (ratio1<sratio1 || ratio2>sratio2) {
  1290.       scaled_col3_left++;
  1291.       scaled_col4_left++;
  1292.       scaled_col5_left++;
  1293.       scaled_col6_left++;
  1294.       scaled_col7_left++;
  1295.       scaled_col7_right++;
  1296.       srect2++;
  1297.     } else if (ratio2<sratio2 || ratio3>sratio3) {
  1298.       scaled_col4_left++;
  1299.       scaled_col5_left++;
  1300.       scaled_col6_left++;
  1301.       scaled_col7_left++;
  1302.       scaled_col7_right++;
  1303.       srect3++;
  1304.     } else if (ratio3<sratio3 || ratio4>sratio4) {
  1305.       scaled_col5_left++;
  1306.       scaled_col6_left++;
  1307.       scaled_col7_left++;
  1308.       scaled_col7_right++;
  1309.       srect4++;
  1310.     } else if (ratio4<sratio4 || ratio5>sratio5) {
  1311.       scaled_col6_left++;
  1312.       scaled_col7_left++;
  1313.       scaled_col7_right++;
  1314.       srect5++;
  1315.     } else if (ratio5<sratio5 || ratio6>sratio6) {
  1316.       scaled_col7_left++;
  1317.       scaled_col7_right++;
  1318.       srect6++;
  1319.     } else if (ratio6<sratio6) {
  1320.       scaled_col7_right++;
  1321.       srect7++;
  1322.     } else {
  1323.       throw ITException("error during CSevenColumnsIF scaling - e too small?");
  1324.     }
  1325.     scaled_width = scaled_col7_right-scaled_col1_left;
  1326.     too_wide = scaled_width > scaled_template_width;
  1327.     sratio1 = (II_TYPE)srect1/(II_TYPE)srect2;
  1328.     sratio2 = (II_TYPE)srect2/(II_TYPE)srect3;
  1329.     sratio3 = (II_TYPE)srect3/(II_TYPE)srect4;
  1330.     sratio4 = (II_TYPE)srect4/(II_TYPE)srect5;
  1331.     sratio5 = (II_TYPE)srect5/(II_TYPE)srect6;
  1332.     sratio6 = (II_TYPE)srect6/(II_TYPE)srect7;
  1333.   }
  1334.   ASSERT(too_wide || fabs((II_TYPE)rect1/(II_TYPE)rect3
  1335.               -(II_TYPE)srect1/(II_TYPE)srect3)<SCALE_DIFFERENCE_EPSILON);
  1336.   ASSERT(too_wide || fabs((II_TYPE)rect1/(II_TYPE)rect4
  1337.               -(II_TYPE)srect1/(II_TYPE)srect4)<SCALE_DIFFERENCE_EPSILON);
  1338.   ASSERT(too_wide || fabs((II_TYPE)rect1/(II_TYPE)rect5
  1339.               -(II_TYPE)srect1/(II_TYPE)srect5)<SCALE_DIFFERENCE_EPSILON);
  1340.   ASSERT(too_wide || fabs((II_TYPE)rect1/(II_TYPE)rect6
  1341.               -(II_TYPE)srect1/(II_TYPE)srect6)<SCALE_DIFFERENCE_EPSILON);
  1342.   ASSERT(too_wide || fabs((II_TYPE)rect1/(II_TYPE)rect7
  1343.               -(II_TYPE)srect1/(II_TYPE)srect7)<SCALE_DIFFERENCE_EPSILON);
  1344.   int overlap = scaled_col7_right-scaled_template_width+1;
  1345.   // overlap: by how much is rightmost too far to the right? 
  1346.   // it must not be larger than scaled_template_width-1
  1347.   if (overlap>0) {
  1348.     // went outside template boundaries
  1349.     if (too_wide) {
  1350.       // feature too big, use int scale
  1351.       *pScale_x = floor(*pScale_x);
  1352.       Scale(*pScale_x, *pScale_y);
  1353.     } else {
  1354.       // shift feature by overlap
  1355.       scaled_col1_left -= overlap;
  1356.       scaled_col2_left -= overlap;
  1357.       scaled_col3_left -= overlap;
  1358.       scaled_col4_left -= overlap;
  1359.       scaled_col5_left -= overlap;
  1360.       scaled_col6_left -= overlap;
  1361.       scaled_col7_left -= overlap;
  1362.       scaled_col7_right -= overlap;
  1363.       *pScale_x = sratio1;
  1364.     }
  1365.   } else {
  1366.     *pScale_x = sratio1;
  1367.   }
  1368. }
  1369. void CSevenColumnsIF::SetToFirstIncarnation()
  1370. {
  1371.   if (m_is_partial) {
  1372.     toprow=start_toprow;
  1373.     bottomrow=start_bottomrow;
  1374.     col1_left = start_col1_left;
  1375.     col2_left = start_col2_left;
  1376.     col3_left = start_col3_left;
  1377.     col4_left = start_col4_left;
  1378.     col5_left = start_col5_left;
  1379.     col6_left = start_col6_left;
  1380.     col7_left = start_col7_left;
  1381.     col7_right= start_col7_right;
  1382.     m_remaining_incarnations=m_stop_after_num_incarnations;
  1383.   } else {
  1384.     toprow=-1;
  1385.     bottomrow=0;
  1386.     col1_left = -1;
  1387.     col2_left = 0;
  1388.     col3_left = 1;
  1389.     col4_left = 2;
  1390.     col5_left = 3;
  1391.     col6_left = 4;
  1392.     col7_left = 5;
  1393.     col7_right= 6;
  1394.   }
  1395.   SetNonOverlap();
  1396. }
  1397. bool CSevenColumnsIF::SetToNextIncarnation()
  1398. {
  1399. if (m_is_partial) {
  1400. if (m_remaining_incarnations) {
  1401. m_remaining_incarnations--;
  1402. } else {
  1403. return false;
  1404. }
  1405. }
  1406.   col7_right++;
  1407.   if (col7_right>=m_template_width) {
  1408.     col7_left++;
  1409.     if (col7_left>=m_template_width-1) {
  1410.       col6_left++;
  1411.       if (col6_left>=m_template_width-2) {
  1412.         col5_left++;
  1413.       if (col5_left>=m_template_width-3) {
  1414.             col4_left++;
  1415.             if (col4_left>=m_template_width-4) {
  1416.             col3_left++;
  1417.                 if (col3_left>=m_template_width-5) {
  1418.                   col2_left++;
  1419.                   if (col2_left>=m_template_width-6) {
  1420.                     col1_left++;
  1421.                     if (col1_left>=m_template_width-7) {
  1422.                       bottomrow++;
  1423.                       if (bottomrow==m_template_height) {
  1424.                         toprow++;
  1425.                         if (toprow==m_template_height-1) {
  1426.                           return false;
  1427.                         }
  1428.                         bottomrow = toprow+1;
  1429.                       }
  1430.                       col1_left = -1;
  1431.                     }
  1432.                     col2_left = col1_left+1;
  1433.                   }
  1434.                   col3_left = col2_left+1;
  1435.                 }
  1436.                 col4_left = col3_left+1;
  1437.             }
  1438.             col5_left = col4_left+1;
  1439.           }
  1440.           col6_left = col5_left+1;
  1441.       }
  1442.       col7_left = col6_left+1;
  1443.     }
  1444.     col7_right = col7_left+1;
  1445.   }
  1446.   SetNonOverlap();
  1447. return true;
  1448. }
  1449. CIntegralFeature* CSevenColumnsIF::Copy() const
  1450. {
  1451. return new CSevenColumnsIF(*this);
  1452. }
  1453. void CSevenColumnsIF::MakePartialFromCurrentForNumIncarnations(
  1454.   featnum num)
  1455. {
  1456.   m_is_partial = true;
  1457.   m_num_incarnations=num+1;
  1458.   start_toprow = toprow;
  1459.   start_bottomrow = bottomrow;
  1460.   start_col1_left = col1_left;
  1461.   start_col2_left = col2_left;
  1462.   start_col3_left = col3_left;
  1463.   start_col4_left = col4_left;
  1464.   start_col5_left = col5_left;
  1465.   start_col6_left = col6_left;
  1466.   start_col7_left = col7_left;
  1467.   start_col7_right= col7_right;
  1468.   m_remaining_incarnations = m_stop_after_num_incarnations=num;
  1469. }
  1470. #ifdef USE_MFC
  1471. void CSevenColumnsIF::Draw(CDC* pDC, int x_off, int y_off, int zoomfactor) const
  1472. {
  1473. int tr = y_off + zoomfactor + toprow*zoomfactor;
  1474. int br = y_off + zoomfactor + bottomrow*zoomfactor;
  1475. int c1 = x_off + zoomfactor + col1_left*zoomfactor;
  1476. int c2 = x_off + zoomfactor + col2_left*zoomfactor;
  1477. int c3 = x_off + zoomfactor + col3_left*zoomfactor;
  1478. int c4 = x_off + zoomfactor + col4_left*zoomfactor;
  1479. int c5 = x_off + zoomfactor + col5_left*zoomfactor;
  1480. int c6 = x_off + zoomfactor + col6_left*zoomfactor;
  1481. int c7 = x_off + zoomfactor + col7_left*zoomfactor;
  1482. int cr = x_off + zoomfactor + col7_right*zoomfactor;
  1483. pDC->FillRect(CRect(c1, tr, c2, br), g_pBlackbrush);
  1484. pDC->Rectangle(c2, tr, c3, br);
  1485. pDC->FillRect(CRect(c3, tr, c4, br), g_pBlackbrush);
  1486. pDC->Rectangle(c4, tr, c5, br);
  1487. pDC->FillRect(CRect(c5, tr, c6, br), g_pBlackbrush);
  1488. pDC->Rectangle(c6, tr, c7, br);
  1489. pDC->FillRect(CRect(c7, tr, cr, br), g_pBlackbrush);
  1490. }
  1491. #endif // USE_MFC
  1492. ostream& CSevenColumnsIF::output(ostream& os) const
  1493. {
  1494.   os << "SevenColumns " << toprow << "," << bottomrow << " x "
  1495.      << col1_left << "," << col2_left << "," << col3_left << "," << col4_left << ","
  1496.      << col5_left << "," << col6_left << "," << col7_left << "," << col7_right;
  1497.   return os;
  1498. }
  1499. /////////////////////////////////////////////////////////////////////////////
  1500. //
  1501. // CDiagIF classes implementation
  1502. //
  1503. /////////////////////////////////////////////////////////////////////////////
  1504. CDiagIF::CDiagIF(int templateWidth, int templateHeight)
  1505.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 9*COST_GET+15*COST_ADD) 
  1506. {
  1507. }
  1508. CDiagIF::CDiagIF(int templateWidth, int templateHeight,
  1509.         int _toprect_toprow, int _centerrow,
  1510.         int _bottomrect_bottomrow,
  1511.         int _leftrect_leftcol, int _centercol,
  1512.         int _rightrect_rightcol)
  1513.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 9*COST_GET+15*COST_ADD) 
  1514. {
  1515.   toprect_toprow = _toprect_toprow;
  1516.   centerrow = _centerrow;
  1517.   bottomrect_bottomrow = _bottomrect_bottomrow;
  1518.   leftrect_leftcol = _leftrect_leftcol;
  1519.   centercol = _centercol;
  1520.   rightrect_rightcol = _rightrect_rightcol;
  1521.   SetNonOverlap();
  1522. }
  1523. CDiagIF::CDiagIF(const CDiagIF& frm)
  1524.   : CIntegralFeature(frm.m_template_width, frm.m_template_height,
  1525.      frm.m_num_incarnations, frm.m_is_partial, 9*COST_GET+15*COST_ADD) 
  1526. {
  1527.   toprect_toprow=frm.toprect_toprow;
  1528.   centerrow=frm.centerrow;
  1529.   bottomrect_bottomrow=frm.bottomrect_bottomrow;
  1530.   leftrect_leftcol = frm.leftrect_leftcol;
  1531.   centercol = frm.centercol;
  1532.   rightrect_rightcol = frm.rightrect_rightcol;
  1533.   if (m_is_partial) {
  1534.     start_toprect_toprow=frm.start_toprect_toprow;
  1535.     start_centerrow=frm.start_centerrow;
  1536.     start_bottomrect_bottomrow=frm.start_bottomrect_bottomrow;
  1537.     start_leftrect_leftcol = frm.start_leftrect_leftcol;
  1538.     start_centercol = frm.start_centercol;
  1539.     start_rightrect_rightcol = frm.start_rightrect_rightcol;
  1540.     m_remaining_incarnations = frm.m_remaining_incarnations;
  1541.     m_stop_after_num_incarnations = frm.m_stop_after_num_incarnations;
  1542.   }
  1543.   SetNonOverlap();
  1544. }
  1545. CDiagIF::CDiagIF(istream& is, int templateWidth, int templateHeight)
  1546.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 9*COST_GET+15*COST_ADD) 
  1547. {
  1548.   char a, b, c, d;
  1549.   string str;
  1550.   is >> toprect_toprow >> a >> centerrow >> b
  1551.      >> bottomrect_bottomrow >> str
  1552.      >> leftrect_leftcol >> c >> centercol >> d
  1553.      >> rightrect_rightcol;
  1554.   if (a!=',' || b!=',' || str!="x" || c!=',' || d!=',') {
  1555.     char* buf = (char*) alloca((256+str.length())*sizeof(char));
  1556.     sprintf(buf, "error during construction of DiagIF (%c|%c|%s|%c|%c)n",
  1557.    a, b, str.c_str(), c, d);
  1558.     throw ITException(buf);
  1559.   }
  1560.   SetNonOverlap();
  1561. }
  1562. bool CDiagIF::Equals(const CDiagIF& frm) const
  1563. {
  1564.   bool equal = 
  1565.     (toprect_toprow == frm.toprect_toprow &&
  1566.      centerrow == frm.centerrow &&
  1567.      bottomrect_bottomrow == frm.bottomrect_bottomrow &&
  1568.      leftrect_leftcol  ==  frm.leftrect_leftcol &&
  1569.      centercol  ==  frm.centercol &&
  1570.      rightrect_rightcol  ==  frm.rightrect_rightcol);
  1571.   return equal;
  1572. }
  1573. void CDiagIF::SetNonOverlap() {
  1574.   // left_upper - right_upper - left_lower + right_lower
  1575.   m_non_overlap =
  1576.     (centercol-leftrect_leftcol)*(centerrow-toprect_toprow)
  1577.     - (rightrect_rightcol-centercol)*(centerrow-toprect_toprow)
  1578.     - (centercol-leftrect_leftcol)*(bottomrect_bottomrow-centerrow)
  1579.     + (rightrect_rightcol-centercol)*(bottomrect_bottomrow-centerrow);
  1580. }
  1581. II_TYPE CDiagIF::Compute(const CIntegralImage& image) const
  1582. {
  1583.   II_TYPE ceri = image.GetElement(rightrect_rightcol, centerrow);
  1584.   II_TYPE cele = image.GetElement(leftrect_leftcol, centerrow);
  1585.   II_TYPE cecen = image.GetElement(centercol, centerrow);
  1586.   II_TYPE topcen = image.GetElement(centercol, toprect_toprow);
  1587.   II_TYPE botcen = image.GetElement(centercol, bottomrect_bottomrow);
  1588.   
  1589.   II_TYPE val_topleft = 
  1590.     cecen
  1591.     - cele
  1592.     - topcen
  1593.     + image.GetElement(leftrect_leftcol, toprect_toprow);
  1594.   
  1595.   II_TYPE val_topright = 
  1596.     ceri
  1597.     - cecen
  1598.     - image.GetElement(rightrect_rightcol, toprect_toprow)
  1599.     + topcen;
  1600.   
  1601.   II_TYPE val_bottomleft = 
  1602.     botcen
  1603.     - image.GetElement(leftrect_leftcol, bottomrect_bottomrow)
  1604.     - cecen
  1605.     + cele;
  1606.   
  1607.   II_TYPE val_bottomright = 
  1608.     image.GetElement(rightrect_rightcol, bottomrect_bottomrow)
  1609.     - botcen
  1610.     - ceri
  1611.     + cecen;
  1612.   
  1613.   return val_topleft-val_topright-val_bottomleft+val_bottomright;
  1614. }
  1615. II_TYPE CDiagIF::ComputeScaled(const CIntegralImage& image, II_TYPE mean, int left, int top) const
  1616. {
  1617.   int placed_leftrect_leftcol = left + scaled_leftrect_leftcol;
  1618.   int placed_centercol = left + scaled_centercol;
  1619.   int placed_rightrect_rightcol = left + scaled_rightrect_rightcol;
  1620.   int placed_toprect_toprow = top + scaled_toprect_toprow;
  1621.   int placed_centerrow = top + scaled_centerrow;
  1622.   int placed_bottomrect_bottomrow = top + scaled_bottomrect_bottomrow;
  1623.   
  1624.   II_TYPE ceri = image.GetElement(placed_rightrect_rightcol, placed_centerrow);
  1625.   II_TYPE cele = image.GetElement(placed_leftrect_leftcol, placed_centerrow);
  1626.   II_TYPE cecen = image.GetElement(placed_centercol, placed_centerrow);
  1627.   II_TYPE topcen = image.GetElement(placed_centercol, placed_toprect_toprow);
  1628.   II_TYPE botcen = image.GetElement(placed_centercol, placed_bottomrect_bottomrow);
  1629.   
  1630.   II_TYPE val_topleft = 
  1631.     cecen
  1632.     - cele
  1633.     - topcen
  1634.     + image.GetElement(placed_leftrect_leftcol, placed_toprect_toprow);
  1635.   
  1636.   II_TYPE val_topright = 
  1637.     ceri
  1638.     - cecen
  1639.     - image.GetElement(placed_rightrect_rightcol, placed_toprect_toprow)
  1640.     + topcen;
  1641.   
  1642.   II_TYPE val_bottomleft = 
  1643.     botcen
  1644.     - image.GetElement(placed_leftrect_leftcol, placed_bottomrect_bottomrow)
  1645.     - cecen
  1646.     + cele;
  1647.   
  1648.   II_TYPE val_bottomright = 
  1649.     image.GetElement(placed_rightrect_rightcol, placed_bottomrect_bottomrow)
  1650.     - botcen
  1651.     - ceri
  1652.     + cecen;
  1653.   
  1654.   II_TYPE val = val_topleft-val_topright-val_bottomleft+val_bottomright;
  1655.   II_TYPE scaled_val = val/m_global_scale;
  1656.   II_TYPE mean_adjust = m_non_overlap*mean;
  1657.   return scaled_val-mean_adjust;
  1658. }
  1659. void CDiagIF::ScaleX(II_TYPE scale_x)
  1660. {
  1661.   if (leftrect_leftcol==-1) {
  1662.     scaled_leftrect_leftcol = -1;
  1663.     scaled_centercol = (int)((II_TYPE)(centercol+1)*scale_x) - 1;
  1664.     scaled_rightrect_rightcol =
  1665.       (int)((II_TYPE)(rightrect_rightcol-centercol)*scale_x) + scaled_centercol;
  1666.   } else {
  1667.     scaled_leftrect_leftcol = (int)((II_TYPE)leftrect_leftcol*scale_x);
  1668.     scaled_centercol = (int)((II_TYPE)centercol*scale_x);
  1669.     scaled_rightrect_rightcol = (int)((II_TYPE)rightrect_rightcol*scale_x);
  1670.   }
  1671. }
  1672. void CDiagIF::ScaleY(II_TYPE scale_y)
  1673. {
  1674.   if (toprect_toprow==-1) {
  1675.     scaled_toprect_toprow = -1;
  1676.     scaled_centerrow = (int)((II_TYPE)(centerrow+1)*scale_y) - 1;
  1677.     scaled_bottomrect_bottomrow =
  1678.       (int)((II_TYPE)(bottomrect_bottomrow-centerrow)*scale_y)
  1679.       + scaled_centerrow;
  1680.   } else {
  1681.     scaled_toprect_toprow = (int)((II_TYPE)toprect_toprow*scale_y);
  1682.     scaled_centerrow = (int)((II_TYPE)centerrow*scale_y);
  1683.     scaled_bottomrect_bottomrow = (int)((II_TYPE)bottomrect_bottomrow*scale_y);
  1684.   }
  1685. }
  1686. void CDiagIF::Scale(II_TYPE scale_x, II_TYPE scale_y)
  1687. {
  1688.   ScaleX(scale_x);
  1689.   ScaleY(scale_y);
  1690.   m_global_scale = scale_x*scale_y;
  1691. }
  1692. void CDiagIF::EvenOutScales(II_TYPE* pScale_x, II_TYPE* pScale_y,
  1693.         int scaled_template_width, int scaled_template_height)
  1694. {
  1695.   int leftrect = centercol-leftrect_leftcol;
  1696.   int rightrect = rightrect_rightcol-centercol;
  1697.   II_TYPE ratio = (II_TYPE)leftrect/(II_TYPE)rightrect;
  1698.   int sleftrect = scaled_centercol-scaled_leftrect_leftcol;
  1699.   int srightrect = scaled_rightrect_rightcol-scaled_centercol;
  1700.   II_TYPE sratio = (II_TYPE)sleftrect/(II_TYPE)srightrect;
  1701.   int scaled_width = scaled_rightrect_rightcol-scaled_leftrect_leftcol;
  1702.   bool too_wide = scaled_width > scaled_template_width;
  1703.   while (!too_wide && fabs(ratio-sratio)>=SCALE_DIFFERENCE_EPSILON) {
  1704.     if (ratio<sratio) {
  1705.       scaled_rightrect_rightcol++;
  1706.       srightrect++;
  1707.     } else {
  1708.       scaled_centercol++;
  1709.       scaled_rightrect_rightcol++;
  1710.       sleftrect++;
  1711.     }
  1712.     scaled_width = scaled_rightrect_rightcol-scaled_leftrect_leftcol;
  1713.     too_wide = scaled_width > scaled_template_width;
  1714.     sratio = (II_TYPE)sleftrect/(II_TYPE)srightrect;
  1715.   }
  1716.   int overlap = scaled_rightrect_rightcol-scaled_template_width+1;
  1717.   // overlap: by how much is rightmost too far to the right? 
  1718.   // it must not be larger than scaled_template_width-1
  1719.   if (overlap>0) {
  1720.     // went outside template boundaries
  1721.     if (too_wide) {
  1722.       // feature too big, use int scale
  1723.       *pScale_x = floor(*pScale_x);
  1724.       ScaleX(*pScale_x);
  1725.     } else {
  1726.       // shift feature by overlap
  1727.       scaled_leftrect_leftcol -= overlap;
  1728.       scaled_centercol -= overlap;
  1729.       scaled_rightrect_rightcol -= overlap;
  1730.       *pScale_x = sratio;
  1731.     }
  1732.   } else {
  1733.     *pScale_x = sratio;
  1734.   }
  1735.   int toprect = centerrow-toprect_toprow;
  1736.   int bottomrect = bottomrect_bottomrow-centerrow;
  1737.   ratio = (II_TYPE)toprect/(II_TYPE)bottomrect;
  1738.   int stoprect = scaled_centerrow-scaled_toprect_toprow;
  1739.   int sbottomrect = scaled_bottomrect_bottomrow-scaled_centerrow;
  1740.   sratio = (II_TYPE)stoprect/(II_TYPE)sbottomrect;
  1741.   int scaled_height = scaled_bottomrect_bottomrow-toprect_toprow;
  1742.   bool too_high = scaled_height > scaled_template_height;
  1743.   while (!too_high && fabs(ratio-sratio)>=SCALE_DIFFERENCE_EPSILON) {
  1744.     if (ratio<sratio) {
  1745.       scaled_bottomrect_bottomrow++;
  1746.       sbottomrect++;
  1747.     } else {
  1748.       scaled_centerrow++;
  1749.       scaled_bottomrect_bottomrow++;
  1750.       stoprect++;
  1751.     }
  1752.     scaled_height = scaled_bottomrect_bottomrow-toprect_toprow;
  1753.     too_high = scaled_height > scaled_template_height;
  1754.     sratio = (II_TYPE)stoprect/(II_TYPE)sbottomrect;
  1755.   }
  1756.   overlap = scaled_bottomrect_bottomrow-scaled_template_height+1;
  1757.   // overlap: by how much is bottommost too far down? 
  1758.   // it must not be larger than scaled_template_height-1
  1759.   if (overlap>0) {
  1760.     // went outside template boundaries
  1761.     if (too_high) {
  1762.       // feature too big, use int scale
  1763.       *pScale_y = floor(*pScale_y);
  1764.       ScaleY(*pScale_y);
  1765.     } else {
  1766.       // shift feature by overlap
  1767.       scaled_toprect_toprow -= overlap;
  1768.       scaled_centerrow -= overlap;
  1769.       scaled_bottomrect_bottomrow -= overlap;
  1770.       *pScale_y = sratio;
  1771.     }
  1772.   } else {
  1773.     *pScale_y = sratio;
  1774.   }
  1775. }
  1776. void CDiagIF::SetToFirstIncarnation()
  1777. {
  1778.   if (m_is_partial) {
  1779.     toprect_toprow=start_toprect_toprow;
  1780.     centerrow=start_centerrow;
  1781.     bottomrect_bottomrow=start_bottomrect_bottomrow;
  1782.     leftrect_leftcol=start_leftrect_leftcol;
  1783.     centercol=start_centercol;
  1784.     rightrect_rightcol=start_rightrect_rightcol;
  1785.     m_remaining_incarnations=m_stop_after_num_incarnations;
  1786.   } else {
  1787.     toprect_toprow=-1;
  1788.     centerrow=0;
  1789.     bottomrect_bottomrow=1;
  1790.     leftrect_leftcol=-1;
  1791.     centercol=0;
  1792.     rightrect_rightcol=1;
  1793.   }
  1794.   SetNonOverlap();
  1795. }
  1796. bool CDiagIF::SetToNextIncarnation()
  1797. {
  1798.   if (m_is_partial) {
  1799.     if (m_remaining_incarnations) {
  1800.       m_remaining_incarnations--;
  1801.     } else {
  1802.       return false;
  1803.     }
  1804.   }
  1805.   bottomrect_bottomrow++;
  1806.   if (bottomrect_bottomrow>=m_template_height) {
  1807.     centerrow++;
  1808.     if (centerrow>=m_template_height-1) {
  1809.       toprect_toprow++;
  1810.       if (toprect_toprow==m_template_height-2) {
  1811. rightrect_rightcol++;
  1812. if (rightrect_rightcol==m_template_width) {
  1813.   centercol++;
  1814.   if (centercol==m_template_width-1) {
  1815.     leftrect_leftcol++;
  1816.     if (leftrect_leftcol==m_template_width-2) {
  1817.       return false;
  1818.     }
  1819.     centercol=leftrect_leftcol+1;
  1820.   }
  1821.   rightrect_rightcol=centercol+1;
  1822. }
  1823. toprect_toprow=-1;
  1824.       }
  1825.       centerrow=toprect_toprow+1;
  1826.     }
  1827.     bottomrect_bottomrow=centerrow+1;
  1828.   }
  1829.   SetNonOverlap();
  1830.   return true;
  1831. }
  1832. CIntegralFeature* CDiagIF::Copy() const
  1833. {
  1834. return new CDiagIF(*this);
  1835. }
  1836. void CDiagIF::MakePartialFromCurrentForNumIncarnations(
  1837.   featnum num)
  1838. {
  1839.   m_is_partial=true;
  1840.   m_num_incarnations=num+1;
  1841.   start_toprect_toprow=toprect_toprow;
  1842.   start_centerrow=centerrow;
  1843.   start_bottomrect_bottomrow=bottomrect_bottomrow;
  1844.   start_leftrect_leftcol=leftrect_leftcol;
  1845.   start_centercol=centercol;
  1846.   start_rightrect_rightcol=rightrect_rightcol;
  1847.   m_remaining_incarnations=m_stop_after_num_incarnations=num;
  1848. }
  1849. #ifdef USE_MFC
  1850. void CDiagIF::Draw(CDC* pDC, int x_off, int y_off, int zoomfactor) const
  1851. {
  1852.   int lc = x_off + zoomfactor + leftrect_leftcol*zoomfactor;
  1853.   int cc = x_off + zoomfactor + centercol*zoomfactor;
  1854.   int rc = x_off + zoomfactor + rightrect_rightcol*zoomfactor;
  1855.   int tr = y_off + zoomfactor + toprect_toprow*zoomfactor;
  1856.   int cr = y_off + zoomfactor + centerrow*zoomfactor;
  1857.   int br = y_off + zoomfactor + bottomrect_bottomrow*zoomfactor;
  1858.   pDC->FillRect(CRect(lc, tr, cc, cr), g_pBlackbrush);
  1859.   pDC->Rectangle(cc, tr, rc, cr);
  1860.   pDC->Rectangle(lc, cr, cc, br);
  1861.   pDC->FillRect(CRect(cc, cr, rc, br), g_pBlackbrush);
  1862. }
  1863. #endif // USE_MFC
  1864. ostream& CDiagIF::output(ostream& os) const
  1865. {
  1866.   os << "Diag " << toprect_toprow << "," << centerrow 
  1867.      << "," << bottomrect_bottomrow << " x "
  1868.      << leftrect_leftcol << "," << centerrow
  1869.      << "," << rightrect_rightcol;
  1870.   return os;
  1871. }
  1872. /////////////////////////////////////////////////////////////////////////////
  1873. //
  1874. // CFourBoxesIF classes implementation
  1875. //
  1876. /////////////////////////////////////////////////////////////////////////////
  1877. /* they look like this:
  1878. *   b3
  1879. * b1  b4
  1880. *   b2
  1881. * b1,b4 can't overlap,
  1882. * b2,b3 can't overlap,
  1883. * b1_left must be left of b2_left and b3_left
  1884. * b1_right must be right of b2_left and b3_left
  1885. * ... and so on, see SetToNextIncarnation
  1886. */
  1887. CFourBoxesIF::CFourBoxesIF(int templateWidth, int templateHeight)
  1888.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 16*COST_GET+15*COST_ADD) 
  1889. {
  1890. }
  1891. CFourBoxesIF::CFourBoxesIF(int templateWidth, int templateHeight,
  1892.              const CRect* pB1, const CRect* pB2,
  1893.              const CRect* pB3, const CRect* pB4)
  1894.   : CIntegralFeature(templateWidth, templateHeight, IT_INVALID_FEATURE, false, 16*COST_GET+15*COST_ADD) 
  1895. {
  1896.   b1_left = pB1->left;  b1_top = pB1->top;
  1897.   b1_right = pB1->right;  b1_bottom = pB1->bottom;
  1898.   b2_left = pB2->left;  b2_top = pB2->top;
  1899.   b2_right = pB2->right;  b2_bottom = pB2->bottom;
  1900.   b3_left = pB3->left;  b3_top = pB3->top;
  1901.   b3_right = pB3->right;  b3_bottom = pB3->bottom;
  1902.   b4_left = pB4->left;  b4_top = pB4->top;
  1903.   b4_right = pB4->right;  b4_bottom = pB4->bottom;
  1904.   SetNonOverlap();
  1905. }
  1906. CFourBoxesIF::CFourBoxesIF(const CFourBoxesIF& frm)
  1907.   : CIntegralFeature(frm.m_template_width, frm.m_template_height,
  1908.      frm.m_num_incarnations, frm.m_is_partial, 16*COST_GET+15*COST_ADD) 
  1909. {
  1910.   b1_left = frm.b1_left;  b1_top = frm.b1_top;
  1911.   b1_right = frm.b1_right;  b1_bottom = frm.b1_bottom;
  1912.   b2_left = frm.b2_left;  b2_top = frm.b2_top;
  1913.   b2_right = frm.b2_right;  b2_bottom = frm.b2_bottom;
  1914.   b3_left = frm.b3_left;  b3_top = frm.b3_top;
  1915.   b3_right = frm.b3_right;  b3_bottom = frm.b3_bottom;
  1916.   b4_left = frm.b4_left;  b4_top = frm.b4_top;
  1917.   b4_right = frm.b4_right;  b4_bottom = frm.b4_bottom;
  1918.   if (m_is_partial) {
  1919.     start_b1_left = frm.start_b1_left;  start_b1_top = frm.start_b1_top;
  1920.     start_b1_right = frm.start_b1_right;  start_b1_bottom = frm.start_b1_bottom;
  1921.     start_b2_left = frm.start_b2_left;  start_b2_top = frm.start_b2_top;
  1922.     start_b2_right = frm.start_b2_right;  start_b2_bottom = frm.start_b2_bottom;
  1923.     start_b3_left = frm.start_b3_left;  start_b3_top = frm.start_b3_top;
  1924.     start_b3_right = frm.start_b3_right;  start_b3_bottom = frm.start_b3_bottom;
  1925.     start_b4_left = frm.start_b4_left;  start_b4_top = frm.start_b4_top;
  1926.     start_b4_right = frm.start_b4_right;  start_b4_bottom = frm.start_b4_bottom;
  1927.     m_remaining_incarnations = frm.m_remaining_incarnations;
  1928.     m_stop_after_num_incarnations = frm.m_stop_after_num_incarnations;
  1929.   }
  1930.   SetNonOverlap();
  1931. }
  1932. CFourBoxesIF::CFourBoxesIF(istream& is, int template_width, int template_height)
  1933.   : CIntegralFeature(template_width, template_height, IT_INVALID_FEATURE, 0, 16*COST_GET+15*COST_ADD)
  1934. {
  1935.   char a, b, c, d, e, f;
  1936.   is >> e >> b1_left >> a >> b1_top >> b >> b1_right >> c >> b1_bottom >> f >> d;
  1937.   if (a!=',' || b!=',' || c!=',' || d!=',' || e!='(' || f!=')') {
  1938.     char* buf = (char*) alloca(256*sizeof(char));
  1939.     sprintf(buf, "error during construction of FourBoxesIF (%c|%c|%c|%c|%c)n",
  1940.    e, a, b, c, f);
  1941.     throw ITException(buf);
  1942.   }
  1943.   is >> e >> b2_left >> a >> b2_top >> b >> b2_right >> c >> b2_bottom >> f >> d;
  1944.   if (a!=',' || b!=',' || c!=',' || d!=',' || e!='(' || f!=')') {
  1945.     char* buf = (char*) alloca(256*sizeof(char));
  1946.     sprintf(buf, "error during construction of FourBoxesIF (%c|%c|%c|%c|%c)n",
  1947.    e, a, b, c, f);
  1948.     throw ITException(buf);
  1949.   }
  1950.   is >> e >> b3_left >> a >> b3_top >> b >> b3_right >> c >> b3_bottom >> f >> d;
  1951.   if (a!=',' || b!=',' || c!=',' || d!=',' || e!='(' || f!=')') {
  1952.     char* buf = (char*) alloca(256*sizeof(char));
  1953.     sprintf(buf, "error during construction of FourBoxesIF (%c|%c|%c|%c|%c)n",
  1954.    e, a, b, c, f);
  1955.     throw ITException(buf);
  1956.   }
  1957.   is >> e >> b4_left >> a >> b4_top >> b >> b4_right >> c >> b4_bottom >> f;
  1958.   if (a!=',' || b!=',' || c!=',' || d!=',' || e!='(' || f!=')') {
  1959.     char* buf = (char*) alloca(256*sizeof(char));
  1960.     sprintf(buf, "error during construction of FourBoxesIF (%c|%c|%c|%c|%c)n",
  1961.    e, a, b, c, f);
  1962.     throw ITException(buf);
  1963.   }
  1964.   SetNonOverlap();
  1965. }
  1966. bool CFourBoxesIF::Equals(const CFourBoxesIF& frm) const
  1967. {
  1968.   bool equal =
  1969.     (b1_left == frm.b1_left &&  b1_top == frm.b1_top &&
  1970.      b1_right == frm.b1_right &&  b1_bottom == frm.b1_bottom &&
  1971.      b2_left == frm.b2_left &&  b2_top == frm.b2_top &&
  1972.      b2_right == frm.b2_right &&  b2_bottom == frm.b2_bottom &&
  1973.      b3_left == frm.b3_left &&  b3_top == frm.b3_top &&
  1974.      b3_right == frm.b3_right &&  b3_bottom == frm.b3_bottom &&
  1975.      b4_left == frm.b4_left &&  b4_top == frm.b4_top &&
  1976.      b4_right == frm.b4_right &&  b4_bottom == frm.b4_bottom);
  1977.   return equal;
  1978. }
  1979.     
  1980. void CFourBoxesIF::SetNonOverlap() {
  1981.   m_non_overlap =
  1982.     (b1_right-b1_left) * (b1_bottom-b1_top) 
  1983.     + (b2_right-b2_left) * (b2_bottom-b2_top)
  1984.     - (b3_right-b3_left) * (b3_bottom-b3_top)
  1985.     - (b4_right-b4_left) * (b4_bottom-b4_top);
  1986. }
  1987. II_TYPE CFourBoxesIF::Compute(const CIntegralImage& image) const
  1988. {
  1989.   // b1 is the left-top positive box, b2 is the right-bottom positive box,
  1990.   // b3 is the left-top negative box, b4 is the right-bottom positive box 
  1991. II_TYPE val_b1 = 
  1992.     image.GetElement(b1_right, b1_bottom)
  1993.     - image.GetElement(b1_left, b1_bottom)
  1994.     - image.GetElement(b1_right, b1_top)
  1995.     + image.GetElement(b1_left, b1_top);
  1996. II_TYPE val_b2 = 
  1997.     image.GetElement(b2_right, b2_bottom)
  1998.     - image.GetElement(b2_left, b2_bottom)
  1999.     - image.GetElement(b2_right, b2_top)
  2000.     + image.GetElement(b2_left, b2_top);
  2001. II_TYPE val_b3 = 
  2002.     image.GetElement(b3_right, b3_bottom)
  2003.     - image.GetElement(b3_left, b3_bottom)
  2004.     - image.GetElement(b3_right, b3_top)
  2005.     + image.GetElement(b3_left, b3_top);
  2006. II_TYPE val_b4 = 
  2007.     image.GetElement(b4_right, b4_bottom)
  2008.     - image.GetElement(b4_left, b4_bottom)
  2009.     - image.GetElement(b4_right, b4_top)
  2010.     + image.GetElement(b4_left, b4_top);
  2011. return val_b1+val_b2-val_b3-val_b4;
  2012. }
  2013. II_TYPE CFourBoxesIF::ComputeScaled(const CIntegralImage& image, II_TYPE mean, int left, int top) const
  2014. {
  2015. int placed_b1_left   = left + scaled_b1_left;
  2016. int placed_b1_right  = left + scaled_b1_right;
  2017. int placed_b1_top    = top  + scaled_b1_top;
  2018. int placed_b1_bottom = top  + scaled_b1_bottom;
  2019. int placed_b2_left   = left + scaled_b2_left;
  2020. int placed_b2_right  = left + scaled_b2_right;
  2021. int placed_b2_top    = top  + scaled_b2_top;
  2022. int placed_b2_bottom = top  + scaled_b2_bottom;
  2023. int placed_b3_left   = left + scaled_b3_left;
  2024. int placed_b3_right  = left + scaled_b3_right;
  2025. int placed_b3_top    = top  + scaled_b3_top;
  2026. int placed_b3_bottom = top  + scaled_b3_bottom;
  2027. int placed_b4_left   = left + scaled_b4_left;
  2028. int placed_b4_right  = left + scaled_b4_right;
  2029. int placed_b4_top    = top  + scaled_b4_top;
  2030. int placed_b4_bottom = top  + scaled_b4_bottom;
  2031.   // b1 is the left-top positive box, b2 is the right-bottom positive box,
  2032.   // b3 is the left-top negative box, b4 is the right-bottom positive box 
  2033. II_TYPE val_b1 = 
  2034.     image.GetElement(placed_b1_right, placed_b1_bottom)
  2035.     - image.GetElement(placed_b1_left, placed_b1_bottom)
  2036.     - image.GetElement(placed_b1_right, placed_b1_top)
  2037.     + image.GetElement(placed_b1_left, placed_b1_top);
  2038. II_TYPE val_b2 = 
  2039.     image.GetElement(placed_b2_right, placed_b2_bottom)
  2040.     - image.GetElement(placed_b2_left, placed_b2_bottom)
  2041.     - image.GetElement(placed_b2_right, placed_b2_top)
  2042.     + image.GetElement(placed_b2_left, placed_b2_top);
  2043. II_TYPE val_b3 = 
  2044.     image.GetElement(placed_b3_right, placed_b3_bottom)
  2045.     - image.GetElement(placed_b3_left, placed_b3_bottom)
  2046.     - image.GetElement(placed_b3_right, placed_b3_top)
  2047.     + image.GetElement(placed_b3_left, placed_b3_top);
  2048. II_TYPE val_b4 = 
  2049.     image.GetElement(placed_b4_right, placed_b4_bottom)
  2050.     - image.GetElement(placed_b4_left, placed_b4_bottom)
  2051.     - image.GetElement(placed_b4_right, placed_b4_top)
  2052.     + image.GetElement(placed_b4_left, placed_b4_top);
  2053. II_TYPE val = val_b1+val_b2-val_b3-val_b4;
  2054. II_TYPE scaled_val = val/m_global_scale;
  2055. II_TYPE mean_adjust = m_non_overlap*mean;
  2056. #ifdef DEBUG
  2057. if (g_printlots) {
  2058.   VERBOSE4(1, "val_b1 %f, val_b2 %f, val_b3 %f, val_b4 %f",
  2059.             val_b1, val_b1, val_b1, val_b1);
  2060.   VERBOSE2(1, "scaled_val %f, mean_adjust %f", 
  2061.             scaled_val, mean_adjust);
  2062.   VERBOSE4(1, "b1 scaled: left %f, top %f, right %f, bottom %f",
  2063.             scaled_b1_left, scaled_b1_top, scaled_b1_right, scaled_b1_bottom);
  2064.   VERBOSE4(1, "b2 scaled: left %f, top %f, right %f, bottom %f",
  2065.             scaled_b2_left, scaled_b2_top, scaled_b2_right, scaled_b2_bottom);
  2066.   VERBOSE4(1, "b3 scaled: left %f, top %f, right %f, bottom %f",
  2067.             scaled_b3_left, scaled_b3_top, scaled_b3_right, scaled_b3_bottom);
  2068.   VERBOSE4(1, "b4 scaled: left %f, top %f, right %f, bottom %f",
  2069.             scaled_b4_left, scaled_b4_top, scaled_b4_right, scaled_b4_bottom);
  2070. }
  2071. #endif // DEBUG
  2072. return scaled_val-mean_adjust;
  2073. }
  2074. void CFourBoxesIF::ScaleX(II_TYPE scale_x)
  2075. {
  2076.   if (b1_left==-1) {
  2077.     scaled_b1_left = -1;
  2078.     scaled_b1_right = (int)((II_TYPE)(b1_right+1)*scale_x) - 1;
  2079.   } else {
  2080.     scaled_b1_left = (int)((II_TYPE)b1_left*scale_x);
  2081.     scaled_b1_right = (int)((II_TYPE)b1_right*scale_x);
  2082.   }
  2083.   if (b2_left==-1) {
  2084.     scaled_b2_left = -1;
  2085.     scaled_b2_right = (int)((II_TYPE)(b2_right+1)*scale_x) - 1;
  2086.   } else {
  2087.     scaled_b2_left = (int)((II_TYPE)b2_left*scale_x);
  2088.     scaled_b2_right = (int)((II_TYPE)b2_right*scale_x);
  2089.   }
  2090.   if (b3_left==-1) {
  2091.     scaled_b3_left = -1;
  2092.     scaled_b3_right = (int)((II_TYPE)(b3_right+1)*scale_x) - 1;
  2093.   } else {
  2094.     scaled_b3_left = (int)((II_TYPE)b3_left*scale_x);
  2095.     scaled_b3_right = (int)((II_TYPE)b3_right*scale_x);
  2096.   }
  2097.   if (b4_left==-1) {
  2098.     scaled_b4_left = -1;
  2099.     scaled_b4_right = (int)((II_TYPE)(b4_right+1)*scale_x) - 1;
  2100.   } else {
  2101.     scaled_b4_left = (int)((II_TYPE)b4_left*scale_x);
  2102.     scaled_b4_right = (int)((II_TYPE)b4_right*scale_x);
  2103.   }
  2104.   ASSERT(-1<=scaled_b1_left);
  2105.   ASSERT(scaled_b1_right<(int)((II_TYPE)m_template_width*scale_x));
  2106.   ASSERT(-1<=scaled_b2_left);
  2107.   ASSERT(scaled_b2_right<(int)((II_TYPE)m_template_width*scale_x));
  2108.   ASSERT(-1<=scaled_b3_left);
  2109.   ASSERT(scaled_b3_right<(int)((II_TYPE)m_template_width*scale_x));
  2110.   ASSERT(-1<=scaled_b4_left);
  2111.   ASSERT(scaled_b4_right<(int)((II_TYPE)m_template_width*scale_x));
  2112. }
  2113. void CFourBoxesIF::ScaleY(II_TYPE scale_y)
  2114. {
  2115.   if (b1_top==-1) {
  2116.     scaled_b1_top = -1;
  2117.     scaled_b1_bottom = (int)((II_TYPE)(b1_bottom+1)*scale_y) - 1;
  2118.   } else {
  2119.     scaled_b1_top = (int)((II_TYPE)b1_top*scale_y);
  2120.     scaled_b1_bottom = (int)((II_TYPE)b1_bottom*scale_y);
  2121.   }
  2122.   if (b2_top==-1) {
  2123.     scaled_b2_top = -1;
  2124.     scaled_b2_bottom = (int)((II_TYPE)(b2_bottom+1)*scale_y) - 1;
  2125.   } else {
  2126.     scaled_b2_top = (int)((II_TYPE)b2_top*scale_y);
  2127.     scaled_b2_bottom = (int)((II_TYPE)b2_bottom*scale_y);
  2128.   }
  2129.   if (b3_top==-1) {
  2130.     scaled_b3_top = -1;
  2131.     scaled_b3_bottom = (int)((II_TYPE)(b3_bottom+1)*scale_y) - 1;
  2132.   } else {
  2133.     scaled_b3_top = (int)((II_TYPE)b3_top*scale_y);
  2134.     scaled_b3_bottom = (int)((II_TYPE)b3_bottom*scale_y);
  2135.   }
  2136.   if (b4_top==-1) {
  2137.     scaled_b4_top = -1;
  2138.     scaled_b4_bottom = (int)((II_TYPE)(b4_bottom+1)*scale_y) - 1;
  2139.   } else {
  2140.     scaled_b4_top = (int)((II_TYPE)b4_top*scale_y);
  2141.     scaled_b4_bottom = (int)((II_TYPE)b4_bottom*scale_y);
  2142.   }
  2143.   ASSERT(-1<=scaled_b1_top);
  2144.   ASSERT(scaled_b1_bottom<(int)((II_TYPE)m_template_height*scale_y));
  2145.   ASSERT(-1<=scaled_b2_top);
  2146.   ASSERT(scaled_b2_bottom<(int)((II_TYPE)m_template_height*scale_y));
  2147.   ASSERT(-1<=scaled_b3_top);
  2148.   ASSERT(scaled_b3_bottom<(int)((II_TYPE)m_template_height*scale_y));
  2149.   ASSERT(-1<=scaled_b4_top);
  2150.   ASSERT(scaled_b4_bottom<(int)((II_TYPE)m_template_height*scale_y));
  2151. }
  2152. void CFourBoxesIF::Scale(II_TYPE scale_x, II_TYPE scale_y)
  2153. {
  2154.   ScaleX(scale_x);
  2155.   ScaleY(scale_y);
  2156.   m_global_scale = scale_x*scale_y;
  2157. }
  2158. void CFourBoxesIF::EvenOutScales(II_TYPE* pScale_x, II_TYPE* pScale_y,
  2159.         int scaled_template_width, int scaled_template_height)
  2160. {
  2161.   int rect1 = b1_right-b1_left;
  2162.   int rect2 = b2_right-b2_left;
  2163.   int rect3 = b3_right-b3_left;
  2164.   int rect4 = b4_right-b4_left;
  2165.   II_TYPE xratio1 = (II_TYPE)rect1/(II_TYPE)rect2;
  2166.   II_TYPE xratio2 = (II_TYPE)rect2/(II_TYPE)rect3;
  2167.   II_TYPE xratio3 = (II_TYPE)rect3/(II_TYPE)rect4;
  2168.   int srect1 = scaled_b1_right-scaled_b1_left;
  2169.   int srect2 = scaled_b2_right-scaled_b2_left;
  2170.   int srect3 = scaled_b3_right-scaled_b3_left;
  2171.   int srect4 = scaled_b4_right-scaled_b4_left;
  2172.   II_TYPE xsratio1 = (II_TYPE)srect1/(II_TYPE)srect2;
  2173.   II_TYPE xsratio2 = (II_TYPE)srect2/(II_TYPE)srect3;
  2174.   II_TYPE xsratio3 = (II_TYPE)srect3/(II_TYPE)srect4;
  2175.   int rightmost = max(scaled_b2_right, scaled_b4_right);
  2176.   int leftmost = min(scaled_b1_left, scaled_b3_left);
  2177.   bool too_wide = rightmost-leftmost > scaled_template_width;
  2178.   while (!too_wide && 
  2179.  (fabs(xratio1-xsratio1)>=SCALE_DIFFERENCE_EPSILON
  2180.   || fabs(xratio2-xsratio2)>=SCALE_DIFFERENCE_EPSILON
  2181.   || fabs(xratio3-xsratio3)>=SCALE_DIFFERENCE_EPSILON)) {
  2182.     if (xratio1>xsratio1) {
  2183.       scaled_b1_right++;
  2184.       if (scaled_b4_left<scaled_b1_right) {
  2185.         scaled_b4_left++;
  2186.         scaled_b4_right++;
  2187.       }
  2188.       srect1++;
  2189.     } else if (xratio1<xsratio1 || xratio2>xsratio2) {
  2190.       scaled_b2_right++;
  2191.       srect2++;
  2192.     } else if (xratio2<xsratio2 || xratio3>xsratio3) {
  2193.       scaled_b3_right++;
  2194.       srect3++;
  2195.     } else if (xratio3<xsratio3) {
  2196.       scaled_b4_right++;
  2197.       srect4++;
  2198.     } else {
  2199.       throw ITException("error during CFourBoxesIF xscaling - e too small?");
  2200.     }
  2201.     rightmost = max(scaled_b2_right, scaled_b4_right);
  2202.     leftmost = min(scaled_b1_left, scaled_b3_left);
  2203.     too_wide = rightmost-leftmost > scaled_template_width;
  2204.     xsratio1 = (II_TYPE)srect1/(II_TYPE)srect2;
  2205.     xsratio2 = (II_TYPE)srect2/(II_TYPE)srect3;
  2206.     xsratio3 = (II_TYPE)srect3/(II_TYPE)srect4;
  2207.   }
  2208.   ASSERT(too_wide || fabs((II_TYPE)rect1/(II_TYPE)rect3
  2209.               -(II_TYPE)srect1/(II_TYPE)srect3)<SCALE_DIFFERENCE_EPSILON);
  2210.   ASSERT(too_wide || fabs((II_TYPE)rect1/(II_TYPE)rect4
  2211.               -(II_TYPE)srect1/(II_TYPE)srect4)<SCALE_DIFFERENCE_EPSILON);
  2212.   int overlap = rightmost-scaled_template_width+1; 
  2213.   // overlap: by how much is rightmost too far to the right? 
  2214.   // it must not be larger than scaled_template_width-1
  2215.   if (overlap>0) {
  2216.     // went outside template boundaries
  2217.     if (too_wide) {
  2218.       // feature too big, use int scale
  2219.       *pScale_x = floor(*pScale_x);
  2220.       ScaleX(*pScale_x);
  2221.     } else {
  2222.       // shift feature by overlap
  2223.       scaled_b1_left -= overlap;
  2224.       scaled_b1_right -= overlap;
  2225.       scaled_b2_left -= overlap;
  2226.       scaled_b2_right -= overlap;
  2227.       scaled_b3_left -= overlap;
  2228.       scaled_b3_right -= overlap;
  2229.       scaled_b4_left -= overlap;
  2230.       scaled_b4_right -= overlap;
  2231.       *pScale_x = xsratio1;
  2232.     }
  2233.   } else {
  2234.     *pScale_x = xsratio1;
  2235.   }
  2236.   ASSERT(-1<=scaled_b1_left && scaled_b1_right<scaled_template_width);
  2237.   ASSERT(-1<=scaled_b2_left && scaled_b2_right<scaled_template_width);
  2238.   ASSERT(-1<=scaled_b3_left && scaled_b3_right<scaled_template_width);
  2239.   ASSERT(-1<=scaled_b4_left && scaled_b4_right<scaled_template_width);
  2240.   rect1 = b1_bottom-b1_top;
  2241.   rect2 = b2_bottom-b2_top;
  2242.   rect3 = b3_bottom-b3_top;
  2243.   rect4 = b4_bottom-b4_top;
  2244.   II_TYPE yratio1 = (II_TYPE)rect1/(II_TYPE)rect2;
  2245.   II_TYPE yratio2 = (II_TYPE)rect2/(II_TYPE)rect3;
  2246.   II_TYPE yratio3 = (II_TYPE)rect3/(II_TYPE)rect4;
  2247.   srect1 = scaled_b1_bottom-scaled_b1_top;
  2248.   srect2 = scaled_b2_bottom-scaled_b2_top;
  2249.   srect3 = scaled_b3_bottom-scaled_b3_top;
  2250.   srect4 = scaled_b4_bottom-scaled_b4_top;
  2251.   II_TYPE ysratio1 = (II_TYPE)srect1/(II_TYPE)srect2;
  2252.   II_TYPE ysratio2 = (II_TYPE)srect2/(II_TYPE)srect3;
  2253.   II_TYPE ysratio3 = (II_TYPE)srect3/(II_TYPE)srect4;
  2254.   
  2255.   int bottommost = max(scaled_b2_bottom, scaled_b4_bottom);
  2256.   int topmost = min(scaled_b1_top, scaled_b3_top);
  2257.   bool too_high = bottommost-topmost > scaled_template_height;
  2258.   while (!too_high 
  2259.  && (fabs(yratio1-ysratio1)>=SCALE_DIFFERENCE_EPSILON
  2260.      || fabs(yratio2-ysratio2)>=SCALE_DIFFERENCE_EPSILON
  2261.      || fabs(yratio3-ysratio3)>=SCALE_DIFFERENCE_EPSILON)) 
  2262.   {
  2263.     if (yratio1>ysratio1) {
  2264.       scaled_b1_bottom++;
  2265.       if (scaled_b2_top<scaled_b1_bottom) {
  2266.         scaled_b2_top++;
  2267.         scaled_b2_bottom++;
  2268.       }
  2269.       srect1++;
  2270.     } else if (yratio1<ysratio1 || yratio2>ysratio2) {
  2271.       scaled_b2_bottom++;
  2272.       srect2++;
  2273.     } else if (yratio2<ysratio2 || yratio3>ysratio3) {
  2274.       scaled_b3_bottom++;
  2275.       if (scaled_b4_top<scaled_b3_bottom) {
  2276.         scaled_b4_top++;
  2277.         scaled_b4_bottom++;
  2278.       }
  2279.       srect3++;
  2280.     } else if (yratio3<ysratio3) {
  2281.       scaled_b4_bottom++;
  2282.       srect4++;
  2283.     } else {
  2284.       throw ITException("error during CFourBoxesIF yscaling - e too small?");
  2285.     }
  2286.     bottommost = max(scaled_b2_bottom, scaled_b4_bottom);
  2287.     topmost = min(scaled_b1_top, scaled_b3_top);
  2288.     too_high = bottommost-topmost > scaled_template_height;
  2289.     ysratio1 = (II_TYPE)srect1/(II_TYPE)srect2;
  2290.     ysratio2 = (II_TYPE)srect2/(II_TYPE)srect3;
  2291.     ysratio3 = (II_TYPE)srect3/(II_TYPE)srect4;
  2292.   }
  2293.   ASSERT(too_high || fabs((II_TYPE)rect1/(II_TYPE)rect3
  2294.               -(II_TYPE)srect1/(II_TYPE)srect3)<SCALE_DIFFERENCE_EPSILON);
  2295.   ASSERT(too_high || fabs((II_TYPE)rect1/(II_TYPE)rect4
  2296.               -(II_TYPE)srect1/(II_TYPE)srect4)<SCALE_DIFFERENCE_EPSILON);
  2297.   overlap = bottommost-scaled_template_height+1;
  2298.   // overlap: by how much is bottommost too far down? 
  2299.   // it must not be larger than scaled_template_height-1
  2300.   if (overlap>0) {
  2301.     // went outside template boundaries
  2302.     if (too_high) {
  2303.       // feature too big, use int scale
  2304.       *pScale_y = floor(*pScale_y);
  2305.       ScaleY(*pScale_y);
  2306.     } else {
  2307.       // shift feature by overlap
  2308.       scaled_b1_top -= overlap;
  2309.       scaled_b1_bottom -= overlap;
  2310.       scaled_b2_top -= overlap;
  2311.       scaled_b2_bottom -= overlap;
  2312.       scaled_b3_top -= overlap;
  2313.       scaled_b3_bottom -= overlap;
  2314.       scaled_b4_top -= overlap;
  2315.       scaled_b4_bottom -= overlap;
  2316.       *pScale_y = ysratio1;
  2317.     }
  2318.   } else {
  2319.     *pScale_y = ysratio1;
  2320.   }
  2321.   ASSERT(-1<=scaled_b1_top && scaled_b1_bottom<scaled_template_height);
  2322.   ASSERT(-1<=scaled_b2_top && scaled_b2_bottom<scaled_template_height);
  2323.   ASSERT(-1<=scaled_b3_top && scaled_b3_bottom<scaled_template_height);
  2324.   ASSERT(-1<=scaled_b4_top && scaled_b4_bottom<scaled_template_height);
  2325. }
  2326. void CFourBoxesIF::SetToFirstIncarnation()
  2327. {
  2328.   if (m_is_partial) {
  2329.     b1_left = start_b1_left;  b1_top = start_b1_top;
  2330.     b1_right = start_b1_right;  b1_bottom = start_b1_bottom;
  2331.     b2_left = start_b2_left;  b2_top = start_b2_top;
  2332.     b2_right = start_b2_right;  b2_bottom = start_b2_bottom;
  2333.     b3_left = start_b3_left;  b3_top = start_b3_top;
  2334.     b3_right = start_b3_right;  b3_bottom = start_b3_bottom;
  2335.     b4_left = start_b4_left;  b4_top = start_b4_top;
  2336.     b4_right = start_b4_right;  b4_bottom = start_b4_bottom;
  2337.     m_remaining_incarnations = m_stop_after_num_incarnations;
  2338.   } else {
  2339.     b1_left  =-1;  b1_top    = 0;
  2340.     b1_right = 1;  b1_bottom = 2;
  2341.     b2_left  = 0;  b2_top    = 2;
  2342.     b2_right = 2;  b2_bottom = 4;
  2343.     b3_left  = 0;  b3_top    =-1;
  2344.     b3_right = 2;  b3_bottom = 1;
  2345.     b4_left  = 1;  b4_top    = 1;
  2346.     b4_right = 3;  b4_bottom = 3;
  2347.   }
  2348.   SetNonOverlap();
  2349. }
  2350. bool CFourBoxesIF::SetToNextIncarnation()
  2351. {
  2352. if (m_is_partial) {
  2353. if (m_remaining_incarnations) {
  2354. m_remaining_incarnations--;
  2355. } else {
  2356. return false;
  2357. }
  2358. }
  2359.   b4_right++;
  2360.   if (b4_right>=m_template_width) {
  2361.     b2_right++;
  2362.     b3_right++;
  2363.     if (b2_right>=m_template_width-1) {
  2364.       b1_right++;
  2365.       b4_left++;
  2366.       if (b1_right>=m_template_width-2) {
  2367.         b2_left++;
  2368.         b3_left++;
  2369.         if (b2_left>=m_template_width-3) {
  2370.           b1_left++;
  2371.           if (b1_left>=m_template_width-4) {
  2372.             b2_bottom++;
  2373.             if (b2_bottom>=m_template_height) {
  2374.               b4_bottom++;
  2375.               if (b4_bottom>=m_template_height-1) {
  2376.                 b1_bottom++;
  2377.                 b2_top++;
  2378.                 if (b1_bottom>=m_template_height-2) {
  2379.                   b3_bottom++;
  2380.                   b4_top++;
  2381.                   if (b3_bottom>=m_template_height-3) {
  2382.                     b1_top++;
  2383.                     if (b1_top>=m_template_height-4) {
  2384.                       b3_top++;
  2385.                       if (b3_top>=m_template_height-5) {
  2386.                         return false;
  2387.                       }
  2388.                       b1_top = b3_top+1;
  2389.                     }
  2390.                     b3_bottom = b1_top+1;
  2391.                     b4_top = b3_bottom;
  2392.                   }
  2393.                   b1_bottom = b3_bottom+1;
  2394.                   b2_top = b1_bottom;
  2395.                 }
  2396.                 b4_bottom = b1_bottom+1;
  2397.               }
  2398.               b2_bottom = b4_bottom+1;
  2399.             }
  2400.             b1_left = -1;
  2401.           }
  2402.           b2_left = b1_left+1;
  2403.           b3_left = b2_left;
  2404.         }
  2405.         b1_right = b2_left+1;
  2406.         b4_left = b1_right;
  2407.       }
  2408.       b2_right = b1_right+1;
  2409.       b3_right = b2_right;
  2410.     }
  2411.     b4_right = b2_right+1;
  2412.   }
  2413.   SetNonOverlap();
  2414. return true;
  2415. }
  2416. CIntegralFeature* CFourBoxesIF::Copy() const
  2417. {
  2418. return new CFourBoxesIF(*this);
  2419. }
  2420. void CFourBoxesIF::MakePartialFromCurrentForNumIncarnations(
  2421.   featnum num)
  2422. {
  2423.   m_is_partial = true;
  2424.   m_num_incarnations=num+1;
  2425.   start_b1_left = b1_left;  start_b1_top = b1_top;
  2426.   start_b1_right = b1_right;  start_b1_bottom = b1_bottom;
  2427.   start_b2_left = b2_left;  start_b2_top = b2_top;
  2428.   start_b2_right = b2_right;  start_b2_bottom = b2_bottom;
  2429.   start_b3_left = b3_left;  start_b3_top = b3_top;
  2430.   start_b3_right = b3_right;  start_b3_bottom = b3_bottom;
  2431.   start_b4_left = b4_left;  start_b4_top = b4_top;
  2432.   start_b4_right = b4_right;  start_b4_bottom = b4_bottom;
  2433.   m_remaining_incarnations = m_stop_after_num_incarnations = num;
  2434. }
  2435. #ifdef USE_MFC
  2436. void CFourBoxesIF::Draw(CDC* pDC, int x_off, int y_off, int zoomfactor) const
  2437. {
  2438. int l1 = x_off + zoomfactor + b1_left*zoomfactor;
  2439. int t1 = y_off + zoomfactor + b1_top*zoomfactor;
  2440. int r1 = x_off + zoomfactor + b1_right*zoomfactor;
  2441. int b1 = y_off + zoomfactor + b1_bottom*zoomfactor;
  2442. int l2 = x_off + zoomfactor + b2_left*zoomfactor;
  2443. int t2 = y_off + zoomfactor + b2_top*zoomfactor;
  2444. int r2 = x_off + zoomfactor + b2_right*zoomfactor;
  2445. int b2 = y_off + zoomfactor + b2_bottom*zoomfactor;
  2446. int l3 = x_off + zoomfactor + b3_left*zoomfactor;
  2447. int t3 = y_off + zoomfactor + b3_top*zoomfactor;
  2448. int r3 = x_off + zoomfactor + b3_right*zoomfactor;
  2449. int b3 = y_off + zoomfactor + b3_bottom*zoomfactor;
  2450. int l4 = x_off + zoomfactor + b4_left*zoomfactor;
  2451. int t4 = y_off + zoomfactor + b4_top*zoomfactor;
  2452. int r4 = x_off + zoomfactor + b4_right*zoomfactor;
  2453. int b4 = y_off + zoomfactor + b4_bottom*zoomfactor;
  2454.   // box 1 and 2 in black
  2455. pDC->FillRect(CRect(l1, t1, r1, b1), g_pBlackbrush);
  2456. pDC->FillRect(CRect(l2, t2, r2, b2), g_pBlackbrush);
  2457.   // box 3 and 4 in outline, XOR the screen
  2458.   unsigned char bits[9];
  2459.   bits[0] = bits[1] = bits[3] = bits[4] = bits[6] = bits[7] = 0;
  2460.   bits[2] = bits[5] = bits[8] = 255;
  2461.   CBitmap bmp;
  2462.   bmp.CreateBitmap(3, 3, 1, 8, &bits);
  2463.   CBrush brush;
  2464.   brush.CreatePatternBrush(&bmp);
  2465.   pDC->FrameRect(CRect(l3, t3, r3, b3), &brush);
  2466.   pDC->FrameRect(CRect(l4, t4, r4, b4), &brush);
  2467. }
  2468. #endif // USE_MFC
  2469. ostream& CFourBoxesIF::output(ostream& os) const
  2470. {
  2471.   os << "FourBoxes " 
  2472.      << "(" << b1_left << "," << b1_top << "," << b1_right << "," << b1_bottom << "),"
  2473.      << "(" << b2_left << "," << b2_top << "," << b2_right << "," << b2_bottom << "),"
  2474.      << "(" << b3_left << "," << b3_top << "," << b3_right << "," << b3_bottom << "),"
  2475.      << "(" << b4_left << "," << b4_top << "," << b4_right << "," << b4_bottom << ")";
  2476.   return os;
  2477. }