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

视频捕捉/采集

开发平台:

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: cubicles.cpp,v 1.21 2005/10/28 17:47:04 matz Exp $
  13. **/
  14. // cubicles.cpp: Implements the public C interface to the cubicles
  15. // library.  Also needed for Windows DLL creation as it defines the
  16. // entry point for the DLL application.
  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 "IntegralImage.h"
  61. #include "Cascade.h"
  62. #include "Scanner.h"
  63. #if defined (IMG_LIB_OPENCV)
  64. #include "cubicles.h"
  65. #else
  66. #error cubicles.cpp is currently only implemented with OpenCV
  67. #endif
  68. #if defined(WIN32)
  69. BOOL APIENTRY DllMain( HANDLE /*hModule*/, 
  70.                        DWORD  /*ul_reason_for_call*/, 
  71.                        LPVOID /*lpReserved*/
  72.  )
  73. {
  74.     return TRUE;
  75. }
  76. #endif // WIN32
  77. #ifdef __cplusplus
  78. extern "C" {
  79. #endif
  80. //
  81. // global variables
  82. //
  83. CCascadeVector                g_cu_cascades;
  84. CScannerVector                g_cu_scanners;
  85. CIntegralImage                g_cu_integral;
  86. CIntegralImage                g_cu_squared_integral;
  87. int                           g_cu_image_width = -1;
  88. int                           g_cu_image_height = -1;
  89. CRect                         g_cu_bbox;
  90. int                           g_cu_min_width = -1;
  91. int                           g_cu_max_width = -1;
  92. int                           g_cu_min_height = -1;
  93. int                           g_cu_max_height = -1;
  94. // make sure cascadeID is typedef'ed as "unsigned int" or change this:
  95. #define CHECK_CASCADE_ID 
  96.   if (g_cu_cascades.size()<=cascadeID) { 
  97.     CV_ERROR(CV_StsBadArg, "invalid cascadeID"); 
  98.   }
  99. /**
  100.  * Initialize
  101.  */
  102. void cuInitialize(int image_width, int image_height)
  103. {
  104.   CV_FUNCNAME( "cuInitialize" ); // declare cvFuncName
  105.   __BEGIN__;
  106.   if (image_width<0 || image_height<0) {
  107.     CV_ERROR(CV_BadImageSize, "negative image width or height");
  108.   }
  109.   try {
  110.     g_cu_integral.SetSize(image_width, image_height);
  111.     g_cu_squared_integral.SetSize(image_width, image_height);
  112.   } catch (ITException& ite) {
  113.     CV_ERROR(CV_StsError, ite.GetMessage().c_str());
  114.   }
  115.   // this serves as "initialized" flag
  116.   g_cu_image_width = image_width;
  117.   g_cu_image_height = image_height;
  118.   __END__;
  119. }
  120. /**
  121.  * Uninitialize -- call for garbage collection of global variables;
  122.  * they are all stack-allocated, so this is not really necessary
  123.  */
  124. void cuUninitialize()
  125. {
  126.   CV_FUNCNAME( "cuUninitialize" ); // declare cvFuncName
  127.   __BEGIN__;
  128.   if (g_cu_image_width<0 || g_cu_image_height<0) {
  129.     CV_ERROR(CV_StsError, "cubicles not initialized");
  130.   }
  131.   // clear out memory
  132.   g_cu_cascades.clear();
  133.   g_cu_scanners.clear();
  134.   g_cu_integral.~CIntegralImage();
  135.   g_cu_squared_integral.~CIntegralImage();
  136.   // this serves as "initialized" flag
  137.   g_cu_image_width = -1;
  138.   g_cu_image_height = -1;
  139.   __END__;
  140. }
  141. void cuLoadCascade(const string& filename, CuCascadeID* pID)
  142. {
  143.   CV_FUNCNAME( "cuLoadCascade" ); // declare cvFuncName
  144.   __BEGIN__;
  145.   if (filename.length()==0) {
  146.     CV_ERROR(CV_StsBadArg, "no file name specified");
  147.   }
  148.   if (pID==NULL) {
  149.     CV_ERROR(CV_StsBadArg, "pID: invalid pointer");
  150.   }
  151.   try {
  152.     CClassifierCascade cascade;
  153. #if defined(WIN32)
  154.     cascade.ParseFrom(ConvertPathToWindows(filename).c_str());
  155. #else
  156.     cascade.ParseFrom(filename.c_str());
  157. #endif // WIN32
  158.     
  159.     CuCascadeID cascadeID = (CuCascadeID) g_cu_cascades.size();
  160.     g_cu_cascades.push_back(cascade);
  161.     CImageScanner scanner;
  162.     g_cu_scanners.push_back(scanner);
  163.     *pID = cascadeID;
  164.   } catch (ITException& ite) {
  165.     string msg = "error while parsing cascade from file ";
  166.     msg = msg + filename + string(":n") + ite.GetMessage();
  167.     CV_ERROR(CV_StsError, msg.c_str());
  168.   }
  169.   __END__;
  170. }
  171. void cuGetCascadeProperties(CuCascadeID cascadeID, CuCascadeProperties& cp)
  172. {
  173.   CV_FUNCNAME( "cuGetCascadeProperties" ); // declare cvFuncName
  174.   __BEGIN__;
  175.   CHECK_CASCADE_ID;
  176.   try {
  177.     cp.cascadeID = cascadeID;
  178.     cp.names = g_cu_cascades[cascadeID].GetNames();
  179.     cp.template_width = g_cu_cascades[cascadeID].GetTemplateWidth();
  180.     cp.template_height = g_cu_cascades[cascadeID].GetTemplateHeight();
  181.     cp.image_area_ratio = g_cu_cascades[cascadeID].GetImageAreaRatio();
  182.   } catch (ITException& ite) {
  183.     CV_ERROR(CV_StsError, ite.GetMessage().c_str());
  184.   }
  185.   __END__;
  186. }
  187. void cuGetScannerParameters(CuCascadeID cascadeID, CuScannerParameters& sp)
  188. {
  189.   CV_FUNCNAME( "cuGetScannerParameters" ); // declare cvFuncName
  190.   __BEGIN__;
  191.   CHECK_CASCADE_ID;
  192.   try {
  193.     CRect area;
  194.     g_cu_scanners[cascadeID].GetScanParameters(&sp.start_scale,
  195.                                             &sp.stop_scale,
  196.                                             &sp.scale_inc_factor,
  197.                                             &sp.translation_inc_x,
  198.                                             &sp.translation_inc_y,
  199.                                             area,
  200.                                             &sp.post_process,
  201.                                             &sp.active);
  202.     sp.left = area.left;
  203.     sp.top = area.top;
  204.     sp.right = area.right;
  205.     sp.bottom = area.bottom;
  206.   } catch (ITException& ite) {
  207.     CV_ERROR(CV_StsError, ite.GetMessage().c_str());
  208.   }
  209.   __END__;
  210. }
  211. void cuSetScannerParameters(CuCascadeID cascadeID, const CuScannerParameters& sp)
  212. {
  213.   CV_FUNCNAME( "cuSetScannerParameters" ); // declare cvFuncName
  214.   __BEGIN__;
  215.   CHECK_CASCADE_ID;
  216.   try {
  217.     CRect area(sp.left, sp.top, sp.right, sp.bottom);
  218.     g_cu_scanners[cascadeID].SetActive(sp.active);
  219.     g_cu_scanners[cascadeID].SetScanParameters(sp.start_scale,
  220.                                            sp.stop_scale,
  221.                                            sp.scale_inc_factor,
  222.                                            sp.translation_inc_x,
  223.                                            sp.translation_inc_y,
  224.                                            area);
  225.     g_cu_scanners[cascadeID].SetAutoPostProcessing(sp.post_process);
  226.   } catch (ITException& ite) {
  227.     CV_ERROR(CV_StsError, ite.GetMessage().c_str());
  228.   }
  229.   __END__;
  230. }
  231. void cuSetScannerActive(CuCascadeID cascadeID, bool active)
  232. {
  233.   CV_FUNCNAME( "cuSetScannerActive" ); // declare cvFuncName
  234.   __BEGIN__;
  235.   CHECK_CASCADE_ID;
  236.   try {
  237.     g_cu_scanners[cascadeID].SetActive(active);
  238.   } catch (ITException& ite) {
  239.     CV_ERROR(CV_StsError, ite.GetMessage().c_str());
  240.   }
  241.   __END__;
  242. }
  243. void cuSetScanArea(CuCascadeID cascadeID, int left, int top, int right, int bottom)
  244. {
  245.   CV_FUNCNAME( "cuSetScanArea" ); // declare cvFuncName
  246.   __BEGIN__;
  247.   CHECK_CASCADE_ID;
  248.   try {
  249.     CRect area(left, top, right, bottom);
  250.     g_cu_scanners[cascadeID].SetScanArea(area);
  251.   } catch (ITException& ite) {
  252.     CV_ERROR(CV_StsError, ite.GetMessage().c_str());
  253.   }
  254.   __END__;
  255. }
  256. void cuSetScanScales(CuCascadeID cascadeID, double start_scale, double stop_scale)
  257. {
  258.   CV_FUNCNAME( "cuSetScanScales" ); // declare cvFuncName
  259.   __BEGIN__;
  260.   CHECK_CASCADE_ID;
  261.   try {
  262.     g_cu_scanners[cascadeID].SetScanScales(start_scale,
  263.                                            stop_scale);
  264.   } catch (ITException& ite) {
  265.     CV_ERROR(CV_StsError, ite.GetMessage().c_str());
  266.   }
  267.   __END__;
  268. }
  269. void cuScan(const IplImage* grayImage, CuScanMatchVector& matches)
  270. {
  271.   CV_FUNCNAME( "cuScan" ); // declare cvFuncName
  272.   __BEGIN__;
  273.   if (g_cu_image_width<=0 || g_cu_image_height<=0) {
  274.     CV_ERROR(CV_StsError, "cubicles has not been initialized");
  275.   }
  276.   if (grayImage==NULL) {
  277.     CV_ERROR(CV_HeaderIsNull, "grayImage");
  278.   }
  279.   if (grayImage->nChannels!=1) {
  280.     CV_ERROR(CV_BadNumChannels, "can only scan gray-level images");
  281.   }
  282.   if (grayImage->depth!=IPL_DEPTH_8U) {
  283.     CV_ERROR(CV_BadDepth, "can only scan unsigned byte images");
  284.   }
  285.   if (grayImage->origin!=0) {
  286.     CV_ERROR(CV_BadOrigin, "need image origin in top left corner");
  287.   }
  288.   if (grayImage->width!=g_cu_image_width 
  289.       || grayImage->height!=g_cu_image_height) {
  290.     CV_ERROR(CV_BadImageSize, "different from initialization");
  291.   }
  292.   try {
  293.     g_cu_bbox = CRect(-1, -1, -1, -1);
  294.     matches.clear();
  295.     // todo: maybe sometime we should allow a maximum processing time
  296.     // in order to guarantee a certain max latency. On the next call
  297.     // to Process, we would pick up where we left off, e.g. at a
  298.     // certain scanner with a certain scale
  299.     
  300.     // find bounding box around all scanners' scan_areas and
  301.     // integrate image only within that bbox
  302.     int num_cascades = (int) g_cu_cascades.size();
  303.     CRect bbox = CRect(INT_MAX, INT_MAX, 0, 0);
  304.     for (int sc=0; sc<num_cascades; sc++) {
  305.       if (g_cu_scanners[sc].IsActive()) {
  306.         const CRect& scan_area = g_cu_scanners[sc].GetScanArea();
  307.         if (scan_area.left<bbox.left) bbox.left = scan_area.left;
  308.         if (scan_area.right>bbox.right) bbox.right = scan_area.right;
  309.         if (scan_area.top<bbox.top) bbox.top = scan_area.top;
  310.         if (scan_area.bottom>bbox.bottom) bbox.bottom = scan_area.bottom;
  311.       }
  312.     }
  313.     bbox.left = max(0, bbox.left);
  314.     bbox.top = max(0, bbox.top);
  315.     bbox.right = min(bbox.right, grayImage->width);
  316.     bbox.bottom = min(bbox.bottom, grayImage->height);
  317.     
  318.     if (bbox.right-bbox.left<=0 || bbox.bottom-bbox.top<=0) {
  319.       return;
  320.     }
  321.   
  322.     CByteImage byteImage((BYTE*)grayImage->imageData,
  323.                          grayImage->width,
  324.                          grayImage->height);
  325.     CIntegralImage::CreateSimpleNSquaredFrom(byteImage,
  326.                                              g_cu_integral,
  327.                                              g_cu_squared_integral, bbox);
  328.     
  329.     int num_active = 0;
  330.     CScanMatchMatrix events;
  331.     events.resize(num_cascades);
  332.     for (int numc=0; numc<num_cascades; numc++) {
  333.       if (g_cu_scanners[numc].IsActive()) {
  334.         num_active++;
  335.         ASSERT(g_cu_cascades[numc].GetNumStrongClassifiers()>0);
  336.         // do the scan!
  337.         g_cu_scanners[numc].Scan(g_cu_cascades[numc],
  338.                                  g_cu_integral, g_cu_squared_integral,
  339.                                  events[numc]);
  340.         // this is a bit awkward and really not elegant, but we avoid
  341.         // exposing all sorts of internal structures
  342.         for (CScanMatchVector::const_iterator cm = events[numc].begin();
  343.              cm!=events[numc].end();
  344.              cm++)
  345.         {
  346.           CuScanMatch m;
  347.           m.name = cm->name;
  348.           m.left = cm->left;
  349.           m.top = cm->top;
  350.           m.right = cm->right;
  351.           m.bottom = cm->bottom;
  352.           m.scale = cm->scale;
  353.           m.scale_x = cm->scale_x;
  354.           m.scale_y = cm->scale_y;
  355.           matches.push_back(m);
  356.         }
  357. // must be called after the actual scan, and the behavior with
  358. // multiple active scanners is somewhat undetermined
  359. g_cu_scanners[numc].GetScaleSizes(&g_cu_min_width, &g_cu_max_width, 
  360.   &g_cu_min_height, &g_cu_max_height);
  361.       }
  362.     }
  363.     if (num_active>0) {
  364.       g_cu_bbox = bbox;
  365.     }
  366.     
  367.   } catch (ITException& ite) {
  368.     CV_ERROR(CV_StsError, ite.GetMessage().c_str());
  369.   }
  370.   __END__;
  371. } // Scan
  372. void cuGetScannedArea(int* pLeft, int* pTop, int* pRight, int* pBottom)
  373. {
  374.   CV_FUNCNAME( "cuGetScannedArea" ); // declare cvFuncName
  375.   __BEGIN__;
  376.   if (pLeft==NULL || pTop==NULL || pRight==NULL || pBottom==NULL) {
  377.     CV_ERROR(CV_StsBadArg, "null pointer");
  378.   }
  379.   *pLeft = g_cu_bbox.left;
  380.   *pTop = g_cu_bbox.top;
  381.   *pRight = g_cu_bbox.right;
  382.   *pBottom = g_cu_bbox.bottom;
  383.   __END__;
  384. }
  385. void cuGetScaleSizes(int* min_width, int* max_width,
  386.      int* min_height, int* max_height)
  387. {
  388.   CV_FUNCNAME( "cuGetScaleSizes" ); // declare cvFuncName
  389.   __BEGIN__;
  390.   if (min_width==NULL || max_width==NULL ||
  391.       min_height==NULL || max_height==NULL) {
  392.     CV_ERROR(CV_StsBadArg, "null pointer");
  393.   }
  394.   *min_width = g_cu_min_width;
  395.   *max_width = g_cu_max_width;
  396.   *min_height = g_cu_min_height;
  397.   *max_height = g_cu_max_height;
  398.   __END__;
  399. }
  400. /** verbosity: 0 minimal, 3 maximal
  401. */
  402. void cuGetVersion(string& version, int verbosity)
  403. {
  404.   CV_FUNCNAME( "cuGetScannedArea" ); // declare cvFuncName
  405.   __BEGIN__;
  406.   if (verbosity<0 || 3<verbosity) {
  407.     CV_ERROR(CV_StsBadArg, "invalid verbosity");
  408.   }
  409.   version = "cubicles "CU_CURRENT_VERSION_STRING;
  410.   if (verbosity>=1) {
  411. #if defined(WIN32)
  412.     version = version + ", win32";
  413. #elif defined(TARGET_SYSTEM)
  414.     version = version + ", "TARGET_SYSTEM;
  415. #else
  416. #error TARGET_SYSTEM must be defined
  417. #endif
  418. #if defined(DEBUG)
  419.     version = version + " debug";
  420. #endif
  421. #if defined(II_TYPE_FLOAT)
  422.     version = version + ", float";
  423. #elif defined(II_TYPE_DOUBLE)
  424.     version = version + ", double";
  425. #elif defined(II_TYPE_INT)
  426.     version = version + ", int";
  427. #elif defined(II_TYPE_UINT)
  428.     version = version + ", uint";
  429. #else 
  430. #error you must define II_TYPE
  431. #endif
  432. #if defined(WITH_TRAINING)
  433.     version = version + ", training-enabled";
  434. #endif
  435. #if defined(IMG_LIB_MAGICK)
  436.     version = version + ", Magick";
  437. #elif defined(IMG_LIB_OPENCV)
  438.     version = version + ", OpenCV";
  439. #elif defined(IMG_LIB_NONE)
  440.     version = version + ", no image library";
  441. #else
  442. #error at least IMG_LIB_NONE must be defined
  443. #endif
  444.   }
  445.   if (verbosity>=2) {
  446.     version = version + ", built on "__DATE__" at "__TIME__;
  447.   }
  448.   if (verbosity>=3) {
  449.     version = version + "nCVS id: $Id: cubicles.cpp,v 1.21 2005/10/28 17:47:04 matz Exp $";
  450.     
  451.     /* todo: OpenCV info
  452.      */
  453.     cvUseOptimized(0);
  454.     int num_loaded_functions = cvUseOptimized(1);
  455.     printf("OpenCV optimized functions: %dn", num_loaded_functions);
  456.     const char *pVersion, *pPlugins;
  457.     cvGetModuleInfo(NULL, &pVersion, &pPlugins);
  458.     printf("OpenCV version: %sn", pVersion);
  459.     printf("OpenCV plugins: %sn", pPlugins);
  460.   }
  461.   __END__;
  462. }
  463. #ifdef __cplusplus
  464. }
  465. #endif