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

视频捕捉/采集

开发平台:

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: Cascade.cpp,v 1.46 2004/11/11 01:58:57 matz Exp $
  13. **/
  14. // Cascade.cpp : implementation file for ClassifierCascades.
  15. // Functions for reading from files are flex/bison generated from
  16. // CascadeFileScanner.lex and CascadeFileParser.yy.
  17. //
  18. ////////////////////////////////////////////////////////////////////
  19. //
  20. // By downloading, copying, installing or using the software you 
  21. // agree to this license.  If you do not agree to this license, 
  22. // do not download, install, copy or use the software.
  23. //
  24. // Copyright (C) 2004, Mathias Kolsch, all rights reserved.
  25. // Third party copyrights are property of their respective owners.
  26. //
  27. // Redistribution and use in binary form, with or without 
  28. // modification, is permitted for non-commercial purposes only.
  29. // Redistribution in source, with or without modification, is 
  30. // prohibited without prior written permission.
  31. // If granted in writing in another document, personal use and 
  32. // modification are permitted provided that the following two
  33. // conditions are met:
  34. //
  35. // 1.Any modification of source code must retain the above 
  36. //   copyright notice, this list of conditions and the following 
  37. //   disclaimer.
  38. //
  39. // 2.Redistribution's in binary form must reproduce the above 
  40. //   copyright notice, this list of conditions and the following 
  41. //   disclaimer in the documentation and/or other materials provided
  42. //   with the distribution.
  43. //
  44. // This software is provided by the copyright holders and 
  45. // contributors "as is" and any express or implied warranties, 
  46. // including, but not limited to, the implied warranties of 
  47. // merchantability and fitness for a particular purpose are 
  48. // disclaimed.  In no event shall the copyright holder or 
  49. // contributors be liable for any direct, indirect, incidental, 
  50. // special, exemplary, or consequential damages (including, but not 
  51. // limited to, procurement of substitute goods or services; loss of 
  52. // use, data, or profits; or business interruption) however caused
  53. // and on any theory of liability, whether in contract, strict 
  54. // liability, or tort (including negligence or otherwise) arising 
  55. // in any way out of the use of this software, even if advised of 
  56. // the possibility of such damage.
  57. //
  58. ////////////////////////////////////////////////////////////////////
  59. #include "cubicles.hpp"
  60. #include "Cascade.h"
  61. #include "CascadeFileParser.h"
  62. #ifdef _DEBUG
  63. #ifdef USE_MFC
  64. #define new DEBUG_NEW
  65. #undef THIS_FILE
  66. static char THIS_FILE[] = __FILE__;
  67. #endif // USE_MFC
  68. #endif // _DEBUG
  69. #include <fstream>
  70. #include <math.h>
  71. using std::ofstream;
  72. // for parsing
  73. extern CClassifierCascade* parse_cascade(FILE* fp);
  74. /////////////////////////////////////////////////////////////////////////////
  75. //
  76. //  CClassifierCascade implementation
  77. //
  78. /////////////////////////////////////////////////////////////////////////////
  79. CClassifierCascade::CClassifierCascade()
  80.   :
  81.   m_name("unnamed"),
  82.   m_structure_type(CASCADE_TYPE_SEQUENTIAL),
  83.   m_total_false_positive_rate(1.0),
  84.   m_last_detection_rate(0.0),
  85.   m_trainset_exhausted(false),
  86.   m_template_width(-1),
  87.   m_template_height(-1),
  88.   m_image_area_ratio(-1)
  89. {
  90.   m_classifiers.reserve(20);
  91.   m_lyr_false_positive_rates.reserve(20);
  92.   m_lyr_detection_rates.reserve(20);
  93. }
  94. CClassifierCascade::CClassifierCascade(const CClassifierCascade& frm)
  95.   :
  96.   m_name(frm.m_name),
  97.   m_structure_type(frm.m_structure_type),
  98.   m_total_false_positive_rate(frm.m_total_false_positive_rate),
  99.   m_last_detection_rate(frm.m_last_detection_rate),
  100.   m_trainset_exhausted(frm.m_trainset_exhausted),
  101.   m_template_width(frm.m_template_width),
  102.   m_template_height(frm.m_template_height),
  103.   m_image_area_ratio(frm.m_image_area_ratio),
  104.   m_classifiers(frm.m_classifiers),
  105.   m_branch_classifiers(frm.m_branch_classifiers),
  106.   m_branch_names(frm.m_branch_names),
  107.   m_lyr_false_positive_rates(frm.m_lyr_false_positive_rates),
  108.   m_lyr_detection_rates(frm.m_lyr_detection_rates),
  109.   m_branch_lyr_false_positive_rates(frm.m_branch_lyr_false_positive_rates),
  110.   m_branch_lyr_detection_rates(frm.m_branch_lyr_detection_rates),
  111.   m_branch_false_positive_rates(frm.m_branch_false_positive_rates),
  112.   m_branch_detection_rates(frm.m_branch_detection_rates)
  113. {
  114. }
  115. CClassifierCascade::CClassifierCascade(int template_width, int template_height, double image_area_ratio)
  116.   :
  117.   m_name("unnamed"),
  118.   m_structure_type(CASCADE_TYPE_SEQUENTIAL),
  119.   m_total_false_positive_rate(1.0),
  120.   m_last_detection_rate(0.0),
  121.   m_trainset_exhausted(false),
  122.   m_template_width(template_width),
  123.   m_template_height(template_height),
  124.   m_image_area_ratio(image_area_ratio)
  125. {
  126.   m_classifiers.reserve(20);
  127.   m_lyr_false_positive_rates.reserve(20);
  128.   m_lyr_detection_rates.reserve(20);
  129. }
  130. CClassifierCascade::~CClassifierCascade()
  131. {
  132. }
  133. CClassifierCascade& CClassifierCascade::operator=(const CClassifierCascade& frm)
  134. {
  135.   m_name = frm.m_name;
  136.   m_structure_type = frm.m_structure_type;
  137.   m_total_false_positive_rate = frm.m_total_false_positive_rate;
  138.   m_last_detection_rate = frm.m_last_detection_rate;
  139.   m_trainset_exhausted = frm.m_trainset_exhausted;
  140.   m_template_width = frm.m_template_width;
  141.   m_template_height = frm.m_template_height;
  142.   m_image_area_ratio = frm.m_image_area_ratio;
  143.   m_classifiers = frm.m_classifiers;
  144.   m_branch_classifiers = frm.m_branch_classifiers;
  145.   m_branch_names = frm.m_branch_names;
  146.   m_lyr_false_positive_rates = frm.m_lyr_false_positive_rates;
  147.   m_lyr_detection_rates = frm.m_lyr_detection_rates;
  148.   m_branch_lyr_false_positive_rates = frm.m_branch_lyr_false_positive_rates;
  149.   m_branch_lyr_detection_rates = frm.m_branch_lyr_detection_rates;
  150.   m_branch_false_positive_rates = frm.m_branch_false_positive_rates;
  151.   m_branch_detection_rates = frm.m_branch_detection_rates;
  152.   return *this;
  153. }
  154. /* add one strong classifier as the last stage of the cascade
  155.  */
  156. CStrongClassifier& CClassifierCascade::AddStrongClassifier()
  157. {
  158.   ASSERT(m_structure_type==CASCADE_TYPE_SEQUENTIAL);
  159.   int num_clsfs = (int)m_classifiers.size()+1;
  160.   m_classifiers.resize(num_clsfs);
  161.   m_lyr_false_positive_rates.resize(num_clsfs);
  162.   m_lyr_detection_rates.resize(num_clsfs);
  163.   m_classifiers[num_clsfs-1] = CStrongClassifier(); // make sure it's an empty strong classifier
  164.   m_lyr_false_positive_rates[num_clsfs-1] = 1.0;
  165.   m_lyr_detection_rates[num_clsfs-1] = 1.0;
  166.   return m_classifiers[num_clsfs-1];
  167. }
  168. /* add one strong classifier as the last stage of the specified branch
  169.  */
  170. CStrongClassifier& CClassifierCascade::AddStrongClassifier(int branch, double fpr, double dr)
  171. {
  172.   if (m_structure_type==CASCADE_TYPE_SEQUENTIAL || branch==-1) {
  173.     if (branch!=-1) {
  174.       throw ITException("no branches other than common branch (-1) available for sequential cascade structure");
  175.     }
  176.     int num_clsfs = (int)m_classifiers.size()+1;
  177.     m_classifiers.resize(num_clsfs);
  178.     m_lyr_false_positive_rates.resize(num_clsfs);
  179.     m_lyr_detection_rates.resize(num_clsfs);
  180.     m_classifiers[num_clsfs-1] = CStrongClassifier(); // make sure it's an empty strong classifier
  181.     m_lyr_false_positive_rates[num_clsfs-1] = fpr;
  182.     m_lyr_detection_rates[num_clsfs-1] = dr;
  183.     return m_classifiers[num_clsfs-1];
  184.   } else if (m_structure_type==CASCADE_TYPE_FAN) {
  185.     if (branch>=(int)m_branch_classifiers.size()) {
  186.       throw ITException("branch number out of range");
  187.     }
  188.     ASSERT(branch<(int)m_branch_lyr_false_positive_rates.size());
  189.     ASSERT(branch<(int)m_branch_lyr_detection_rates.size());
  190.     int num_clsfs = (int)m_branch_classifiers[branch].size()+1;
  191.     m_branch_classifiers[branch].resize(num_clsfs);
  192.     m_branch_lyr_false_positive_rates[branch].resize(num_clsfs);
  193.     m_branch_lyr_detection_rates[branch].resize(num_clsfs);
  194.     m_branch_classifiers[branch][num_clsfs-1] = CStrongClassifier(); // make sure it's an empty strong classifier
  195.     m_branch_lyr_false_positive_rates[branch][num_clsfs-1] = fpr;
  196.     m_branch_lyr_detection_rates[branch][num_clsfs-1] = dr;
  197.     return m_branch_classifiers[branch][num_clsfs-1];
  198.   } else {
  199.     ASSERT(0);
  200.     throw ITException("tree type not implemented yet");
  201.   }
  202. }
  203. int CClassifierCascade::RemoveLastStrongClassifier()
  204. {
  205.   ASSERT(m_structure_type==CASCADE_TYPE_SEQUENTIAL);
  206.   ASSERT((int)m_classifiers.size());
  207.   m_classifiers.pop_back();
  208.   return (int)m_classifiers.size();
  209. }
  210. // returns number of remaining weak classifiers in last strong
  211. // classifier
  212. int CClassifierCascade::RemoveLastWeakClassifier()
  213. {
  214.   ASSERT(m_structure_type==CASCADE_TYPE_SEQUENTIAL);
  215.   int num_clsf = (int)m_classifiers.size();
  216.   ASSERT(num_clsf);
  217.   return m_classifiers[num_clsf-1].RemoveLastWeakClassifier();
  218. }
  219. double CClassifierCascade::GetFalsePositiveRate(int clsf) const { 
  220.   ASSERT(m_structure_type==CASCADE_TYPE_SEQUENTIAL);
  221.   ASSERT(0<=clsf && clsf<(int)m_classifiers.size());
  222.   return m_lyr_false_positive_rates[clsf]; 
  223. }
  224. double CClassifierCascade::GetDetectionRate(int clsf) const {
  225.   ASSERT(m_structure_type==CASCADE_TYPE_SEQUENTIAL);
  226.   ASSERT(0<=clsf && clsf<(int)m_classifiers.size());
  227.   return m_lyr_detection_rates[clsf];
  228. }
  229. void CClassifierCascade::SetFalsePositiveRate(int clsf, double fpr) { 
  230.   ASSERT(m_structure_type==CASCADE_TYPE_SEQUENTIAL);
  231.   ASSERT(0<=clsf && clsf<(int)m_classifiers.size());
  232.   m_lyr_false_positive_rates[clsf] = fpr;
  233.   m_total_false_positive_rate = 1.0;
  234.   for (int c=0; c<(int)m_classifiers.size(); c++) {
  235.     m_total_false_positive_rate *= m_lyr_false_positive_rates[c];
  236.   }
  237. }
  238. void CClassifierCascade::SetDetectionRate(int clsf, double dr) {
  239.   ASSERT(m_structure_type==CASCADE_TYPE_SEQUENTIAL);
  240.   ASSERT(0<=clsf && clsf<(int)m_classifiers.size());
  241.   m_lyr_detection_rates[clsf] = dr;
  242.   if (clsf==(int)m_classifiers.size()-1) {
  243.     m_last_detection_rate = dr;
  244.   }
  245. }
  246. void CClassifierCascade::ParseFrom(const string& filename)
  247. {
  248.   FILE* fp = fopen(filename.c_str(), "r");
  249.   if (!fp) {
  250.     throw ITEFileNotFound(filename);
  251.   }
  252.   char* buf = new char[10000];
  253.   setvbuf(fp, buf, _IOFBF, sizeof(buf));
  254.   CClassifierCascade* pCascade = parse_cascade(fp);
  255.   delete buf;
  256.   
  257.   if (pCascade==NULL) {
  258.     throw ITException("parsing exception");
  259.   }
  260.   *this = *pCascade;
  261.   delete pCascade;
  262.   return;
  263. }
  264. ostream& operator<<(ostream& os, const CClassifierCascade& casc)
  265. {
  266.   return casc.output(os);
  267. }
  268. ostream& CClassifierCascade::output(ostream& os) const {
  269.   os << "ClassifierCascade "" << m_name << "", ";
  270.   if (m_structure_type==CClassifierCascade::CASCADE_TYPE_SEQUENTIAL) {
  271.     os << "sequential, ";
  272.   } else if (m_structure_type==CClassifierCascade::CASCADE_TYPE_FAN) {
  273.     os << "fan, ";
  274.   } else if (m_structure_type==CClassifierCascade::CASCADE_TYPE_TREE) {
  275.     os << "tree, ";
  276.     ASSERT(0);
  277.     throw ITException("not implemented yet");
  278.   } else {
  279.     ASSERT(0);
  280.   }
  281.   os << m_template_width << "x" << m_template_height 
  282.      << ", ratio " << m_image_area_ratio
  283.      << " (fpr:" << m_total_false_positive_rate
  284.      << ", dr:" << m_last_detection_rate
  285.      << ", " << (m_trainset_exhausted?"exhausted":"successful")
  286.      << ")" << endl;
  287.   if (m_structure_type==CClassifierCascade::CASCADE_TYPE_FAN) {
  288.     os << (int) m_branch_classifiers.size() << " branches." << endl;
  289.     os << "COMMON BRANCH" << endl;
  290.   }
  291.   os << (int)m_classifiers.size() << " strong classifiers." << endl;
  292.   for (int hcnt=0; hcnt<(int)m_classifiers.size(); hcnt++) {
  293.     os << "STRONG classifier " << hcnt <<" (fpr:" 
  294.        << m_lyr_false_positive_rates[hcnt] 
  295.        << ", dr:" << m_lyr_detection_rates[hcnt] << "):n"
  296.        << m_classifiers[hcnt];
  297.   }
  298.   for (int brc=0; brc<(int)m_branch_classifiers.size(); brc++) {
  299.     os << "BRANCH " << brc << " "" << m_branch_names[brc]
  300.        << "" (fpr:" << m_branch_false_positive_rates[brc]
  301.        << ", dr:" << m_branch_detection_rates[brc] << ")" << endl;
  302.     os << (int) m_branch_classifiers[brc].size() 
  303.        << " strong classifiers." << endl;
  304.     for (int hcnt=0; hcnt<(int)m_branch_classifiers[brc].size(); hcnt++) {
  305.       os << "STRONG classifier " << hcnt+(int)m_classifiers.size() <<" (fpr:" 
  306.          << m_branch_lyr_false_positive_rates[brc][hcnt] 
  307.          << ", dr:" << m_branch_lyr_detection_rates[brc][hcnt] << "):n"
  308.          << m_branch_classifiers[brc][hcnt];
  309.     }
  310.   }
  311.   return os;
  312. }
  313. bool CClassifierCascade::Evaluate(const CIntegralImage& image,
  314.                                   CStringVector& matches) const
  315. {
  316.   for (CSClsfVector::const_iterator it=m_classifiers.begin();
  317.        it!=m_classifiers.end(); it++) {
  318.     bool is_pos = it->Evaluate(image);
  319.     if (!is_pos) return false;
  320.   }
  321.   // what structure?
  322.   if (m_structure_type==CASCADE_TYPE_SEQUENTIAL) {
  323.     matches.push_back(m_name);
  324.     return true;
  325.   } else if (m_structure_type==CASCADE_TYPE_FAN) {
  326.     ASSERT(matches.size()==0);
  327.     int num_branches = (int) m_branch_classifiers.size();
  328.     for (int brcnt=0; brcnt<num_branches; brcnt++) {
  329.       bool is_pos = true;
  330.       for (CSClsfVector::const_iterator it=m_branch_classifiers[brcnt].begin();
  331.            it!=m_branch_classifiers[brcnt].end(); it++) {
  332.         is_pos = it->Evaluate(image);
  333.         if (!is_pos) break;
  334.       }
  335.       if (is_pos) {
  336.         matches.push_back(m_branch_names[brcnt]);
  337.       }
  338.     }
  339.     return matches.size()>0;
  340.   } else if (m_structure_type==CASCADE_TYPE_TREE) {
  341.     throw ITException("not implemented yet");
  342.   } else {
  343.     ASSERT(0);
  344.     return 0;
  345.   }
  346. }
  347. #ifdef DEBUG
  348. bool CClassifierCascade::EvaluateDebug(const CIntegralImage& image, 
  349.                                        CStringVector& matches,
  350.                                        ostream& os) const
  351. {
  352.   os << "Cascade evaluating image, " << (int)m_classifiers.size() << " strong classifiers." << endl;
  353.   int hcnt=0;
  354.   for (CSClsfVector::const_iterator it=m_classifiers.begin(); it!=m_classifiers.end(); it++, hcnt++) {
  355.     bool is_pos = it->Evaluate(image);
  356.     os << "STRONG " << hcnt << ": " << is_pos << endl;
  357.     if (!is_pos) return false;
  358.   }
  359.   // what structure?
  360.   if (m_structure_type==CASCADE_TYPE_SEQUENTIAL) {
  361.     matches.push_back(m_name);
  362.     return true;
  363.   } else if (m_structure_type==CASCADE_TYPE_FAN) {
  364.     ASSERT(matches.size()==0);
  365.     int num_branches = (int) m_branch_classifiers.size();
  366.     for (int brcnt=0; brcnt<num_branches; brcnt++) {
  367.       bool is_pos = true;
  368.       for (CSClsfVector::const_iterator it=m_branch_classifiers[brcnt].begin();
  369.            it!=m_branch_classifiers[brcnt].end(); it++) {
  370.         is_pos = it->Evaluate(image);
  371.         if (!is_pos) break;
  372.       }
  373.       if (is_pos) {
  374.         matches.push_back(m_branch_names[brcnt]);
  375.       }
  376.     }
  377.     return matches.size()>0;
  378.   } else if (m_structure_type==CASCADE_TYPE_TREE) {
  379.     throw ITException("not implemented yet");
  380.   } else {
  381.     ASSERT(0);
  382.     return 0;
  383.   }
  384. }
  385. #endif // DEBUG
  386. bool CClassifierCascade::Evaluate(
  387.   const CIntegralImage& image,
  388.   double mean, double stddev, int left, int top,
  389.   CStringVector& matches) const
  390. {
  391.   for (CSClsfVector::const_iterator it=m_classifiers.begin();
  392.        it!=m_classifiers.end();
  393.        it++) {
  394.     bool is_pos = it->Evaluate(image, mean, stddev, left, top);
  395.     if (!is_pos) return false;
  396.   }
  397.   // what structure?
  398.   if (m_structure_type==CASCADE_TYPE_SEQUENTIAL) {
  399.     matches.push_back(m_name);
  400.     return true;
  401.   } else if (m_structure_type==CASCADE_TYPE_FAN) {
  402.     ASSERT(matches.size()==0);
  403.     int num_branches = (int) m_branch_classifiers.size();
  404.     for (int brcnt=0; brcnt<num_branches; brcnt++) {
  405.       bool is_pos = true;
  406.       for (CSClsfVector::const_iterator it=m_branch_classifiers[brcnt].begin();
  407.            it!=m_branch_classifiers[brcnt].end(); it++) {
  408.         is_pos = it->Evaluate(image, mean, stddev, left, top);
  409.         if (!is_pos) break;
  410.       }
  411.       if (is_pos) {
  412.         matches.push_back(m_branch_names[brcnt]);
  413.       }
  414.     }
  415.     return matches.size()>0;
  416.   } else if (m_structure_type==CASCADE_TYPE_TREE) {
  417.     throw ITException("not implemented yet");
  418.   } else {
  419.     ASSERT(0);
  420.     return 0;
  421.   }
  422. }
  423. void CClassifierCascade::ScaleFeaturesEvenly(double scale_x, double scale_y,
  424.         int scaled_template_width, int scaled_template_height) const
  425. {
  426.   CSClsfVector& mutable_classifers = (CSClsfVector&) m_classifiers;
  427.   for (CSClsfVector::iterator it=mutable_classifers.begin(); 
  428.        it!=mutable_classifers.end(); it++) {
  429.     it->ScaleFeaturesEvenly(scale_x, scale_y,
  430.                             scaled_template_width, scaled_template_height);
  431.   }
  432.   if (m_structure_type==CASCADE_TYPE_FAN) {
  433.     for (int brcnt=0; brcnt<(int)m_branch_classifiers.size(); brcnt++) {
  434.       CSClsfVector& mutable_classifers = 
  435.         (CSClsfVector&) m_branch_classifiers[brcnt];
  436.       for (CSClsfVector::iterator it=mutable_classifers.begin(); 
  437.            it!=mutable_classifers.end(); it++) {
  438.         
  439.         it->ScaleFeaturesEvenly(scale_x, scale_y,
  440.                                 scaled_template_width, 
  441.                                 scaled_template_height);
  442.       }
  443.     }
  444.   }
  445. }
  446. // return a copy to name(s)
  447. CStringVector CClassifierCascade::GetNames() const
  448. {
  449.   if (m_structure_type==CASCADE_TYPE_SEQUENTIAL) {
  450.     CStringVector sv;
  451.     sv.push_back(m_name);
  452.     return sv;
  453.   } else if (m_structure_type==CASCADE_TYPE_FAN) {
  454.     return m_branch_names;
  455.   
  456.   } else {
  457.     throw ITException("not implemented yet");
  458.   }
  459. }
  460. int CClassifierCascade::GetNumStrongClassifiers(int branch/*=-1*/) const
  461. {
  462.   if (branch==-1) {
  463.     return (int)m_classifiers.size(); 
  464.   } else {
  465.     if (m_structure_type==CASCADE_TYPE_SEQUENTIAL) {
  466.       throw ITException("no such branch for sequential type");
  467.     } else if (m_structure_type==CASCADE_TYPE_FAN) {
  468.       if (branch<0 || branch>=(int)m_branch_classifiers.size()) {
  469.         throw ITException("branch number out of range");
  470.       }
  471.       return (int)m_branch_classifiers[branch].size(); 
  472.     
  473.     } else {
  474.       ASSERT(0);
  475.       throw ITException("structure type not implemented");
  476.     }
  477.   }
  478. }