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

视频捕捉/采集

开发平台:

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: Image.cpp,v 1.35 2004/11/24 08:41:13 matz Exp $
  13. **/
  14. // Image.cpp defines a bunch of simple image container functions
  15. //
  16. ////////////////////////////////////////////////////////////////////
  17. //
  18. // By downloading, copying, installing or using the software you 
  19. // agree to this license.  If you do not agree to this license, 
  20. // do not download, install, copy or use the software.
  21. //
  22. // Copyright (C) 2004, Mathias Kolsch, all rights reserved.
  23. // Third party copyrights are property of their respective owners.
  24. //
  25. // Redistribution and use in binary form, with or without 
  26. // modification, is permitted for non-commercial purposes only.
  27. // Redistribution in source, with or without modification, is 
  28. // prohibited without prior written permission.
  29. // If granted in writing in another document, personal use and 
  30. // modification are permitted provided that the following two
  31. // conditions are met:
  32. //
  33. // 1.Any modification of source code must retain the above 
  34. //   copyright notice, this list of conditions and the following 
  35. //   disclaimer.
  36. //
  37. // 2.Redistribution's in binary form must reproduce the above 
  38. //   copyright notice, this list of conditions and the following 
  39. //   disclaimer in the documentation and/or other materials provided
  40. //   with the distribution.
  41. //
  42. // This software is provided by the copyright holders and 
  43. // contributors "as is" and any express or implied warranties, 
  44. // including, but not limited to, the implied warranties of 
  45. // merchantability and fitness for a particular purpose are 
  46. // disclaimed.  In no event shall the copyright holder or 
  47. // contributors be liable for any direct, indirect, incidental, 
  48. // special, exemplary, or consequential damages (including, but not 
  49. // limited to, procurement of substitute goods or services; loss of 
  50. // use, data, or profits; or business interruption) however caused
  51. // and on any theory of liability, whether in contract, strict 
  52. // liability, or tort (including negligence or otherwise) arising 
  53. // in any way out of the use of this software, even if advised of 
  54. // the possibility of such damage.
  55. //
  56. ////////////////////////////////////////////////////////////////////
  57. #include "cubicles.hpp"
  58. #include "Image.h"
  59. #include "IntegralImage.h"
  60. #include <math.h>
  61. // this for loading and writing images only
  62. #if defined(IMG_LIB_MAGICK)
  63. #pragma warning (disable: 4251)
  64. #pragma warning (disable: 4786)
  65. #include <Magick++.h>
  66. using namespace Magick;
  67. #pragma warning (default: 4251)
  68. #pragma warning (default: 4786)
  69. #elif defined(IMG_LIB_OPENCV)
  70. #include <cv.h>
  71. #include <highgui.h>
  72. #elif defined(IMG_LIB_NONE)
  73. // nothing
  74. #else
  75. #error at least IMG_LIB_NONE must be defined
  76. #endif
  77. #ifdef _DEBUG
  78. #ifdef USE_MFC
  79. #define new DEBUG_NEW
  80. #undef THIS_FILE
  81. static char THIS_FILE[] = __FILE__;
  82. #endif // USE_MFC
  83. #endif // _DEBUG
  84. #ifndef M_PI
  85. #define M_PI 3.141592653589793
  86. #endif /* M_PI */
  87. #ifdef USE_MFC
  88. #define PREPARE_DIB PrepareDIB()
  89. #else // USE_MFC
  90. #define PREPARE_DIB 
  91. #endif // USE_MFC
  92. #ifdef DEBUG
  93. bool g_printlots = false;
  94. #endif // DEBUG
  95. #ifdef WIN32
  96. #include <malloc.h>
  97. #define alloca _alloca
  98. #endif
  99. // ----------------------------------------------------------------------
  100. // class CByteImage
  101. // ----------------------------------------------------------------------
  102. CByteImage::CByteImage()
  103. : m_width(0),
  104.   m_height(0),
  105.   m_pData(NULL),
  106.   m_data_is_local(true)
  107. {
  108.   PREPARE_DIB;
  109. }
  110. CByteImage::CByteImage(int width, int height)
  111. : m_width(0),
  112.   m_height(0),
  113.   m_pData(NULL),
  114.   m_data_is_local(true)
  115. {
  116.   Allocate(width, height);
  117.   PREPARE_DIB;
  118. }
  119. CByteImage::CByteImage(BYTE* pData, int width, int height)
  120. : m_width(width),
  121.   m_height(height),
  122.   m_pData(pData),
  123.   m_data_is_local(false)
  124. {
  125.   ASSERT (m_width>0 && m_height>0);
  126.   PREPARE_DIB;
  127. }
  128. CByteImage::~CByteImage()
  129. {
  130.   Deallocate();
  131. }
  132. void CByteImage::Deallocate()
  133. {
  134.   if (m_data_is_local) {
  135.     m_data.resize(0);
  136.   }
  137.   m_pData = NULL;
  138. }
  139. void CByteImage::Allocate(int width, int height)
  140. {
  141.   ASSERT(width>0 && height>0);
  142.   if (m_data_is_local && (int)m_data.size()>=width*height) {
  143.     m_width = width;
  144.     m_height = height;
  145.   } else {
  146.     ASSERT(width>=0 && height>=0);
  147.     m_width = width;
  148.     m_height = height;
  149.     m_data.resize(m_width*m_height);
  150.     if (m_width*m_height>0) {
  151.       m_pData = &m_data[0];
  152.       ASSERT(m_pData);
  153.     } else {
  154.       m_pData = NULL;
  155.     }
  156.   }
  157.   m_data_is_local = true;
  158. }
  159. void CByteImage::Copy(const CByteImage& from)
  160. {
  161.   Allocate(from.m_width, from.m_height);
  162.   m_data = from.m_data;
  163. }
  164. void CByteImage::CopyArea(const CByteImage& from, const CRect& from_area, 
  165.               int new_width, int new_height) 
  166. {
  167.   Allocate(new_width, new_height);
  168.   double step_x = (double)from_area.right/(double)m_width;
  169.   double step_y = (double)from_area.bottom/(double)m_height;
  170.   double from_y = from_area.top;
  171.   for (int y=0; y<m_height; y++) {
  172.     double from_x = from_area.left;
  173.     for (int x=0; x<m_width; x++) {
  174.       Pixel(x, y) = (BYTE) from.InterpolateLinear(from_x, from_y);
  175.       from_x += step_x;
  176.     }
  177.     from_y += step_y;
  178.   }
  179. }
  180. #ifdef DEBUG
  181. BYTE CByteImage::Pixel(int x, int y) const 
  182. {
  183.   if (!m_pData) {
  184.     throw ITException("m_pData zero");
  185.   }
  186.   if (!(0<=x && x<m_width && 0<=y && y<m_height)) {
  187.     throw ITException("out of bounds");
  188.   }
  189.   return m_pData[x + y*m_width];
  190. }
  191. BYTE& CByteImage::Pixel(int x, int y)
  192. {
  193.   if (!m_pData) {
  194.     throw ITException("m_pData zero");
  195.   }
  196.   if (!(0<=x && x<m_width && 0<=y && y<m_height)) {
  197.     throw ITException("out of bounds");
  198.   }
  199.   return m_pData[x + y*m_width];
  200. }
  201. #endif // DEBUG
  202. #ifdef USE_MFC
  203. void CByteImage::PrepareDIB()
  204. {
  205.   m_bmi.pMap[0] = 0xff000000;
  206.   for (int color=1; color<256; color++) {
  207.     m_bmi.pMap[color] = m_bmi.pMap[color-1]+0x010101;
  208.   }
  209.   m_bmi.header.biSize = sizeof(BITMAPINFOHEADER);
  210.   m_bmi.header.biPlanes = 1;
  211.   m_bmi.header.biBitCount = (WORD) 8;
  212.   m_bmi.header.biCompression = BI_RGB;
  213.   m_bmi.header.biSizeImage = 0;
  214.   m_bmi.header.biXPelsPerMeter = 3150;
  215.   m_bmi.header.biYPelsPerMeter = 3150;
  216.   m_bmi.header.biClrUsed = 0;
  217.   m_bmi.header.biClrImportant = 0;
  218. }
  219. void CByteImage::SetBitsToDevice(CDC* pDC) const
  220. {
  221.   m_bmi.header.biWidth = m_width;
  222.   m_bmi.header.biHeight = -m_height;
  223.   SetDIBitsToDevice(
  224.     pDC->m_hDC,           // handle to DC
  225.     0,                    // x-coord of destination upper-left corner
  226.     0,                    // y-coord of destination upper-left corner 
  227.     m_width,              // source rectangle width
  228.     m_height,             // source rectangle height
  229.     0,                    // x-coord of source lower-left corner
  230.     0,                    // y-coord of source lower-left corner
  231.     0,                    // first scan line in array
  232.     m_height,             // number of scan lines
  233.     m_pData,              // array of DIB bits
  234.     (BITMAPINFO*) &m_bmi, // bitmap information
  235.     DIB_RGB_COLORS        // RGB or palette indexes
  236.     );
  237. }
  238. #endif // USE_MFC
  239. void CByteImage::WriteToFile(FILE* fp)
  240. {
  241.   fprintf(fp, "%dx%dn", m_width, m_height);
  242.   for (int y=0; y<m_height; y++) {
  243.     for (int x=0; x<m_width; x++) {
  244.       fprintf(fp, "%d ", Pixel(x, y));
  245.     }
  246.     fprintf(fp, "n");
  247.   }
  248. }
  249. void CByteImage::ReadFromFile(FILE* fp)
  250. {
  251.   int width, height, scanned;
  252.   scanned = fscanf(fp, "%dx%dn", &width, &height);
  253.   if (scanned!=2) {
  254.     throw ITEFile("-", "file read error in CByteImage::ReadFromFile");
  255.   }
  256.   Allocate(width, height);
  257.   for (int y=0; y<m_height; y++) {
  258.     for (int x=0; x<m_width; x++) {
  259.       int val;
  260.       scanned = fscanf(fp, "%d ", &val);
  261.       if (scanned!=1 || val<0 || 255<val) {
  262.         char buf[128];
  263.         sprintf(buf, 
  264.           "file read error in CByteImage::ReadFromFile, at(%d, %d)", 
  265.           x, y);
  266.         throw ITEFile("-", buf);
  267.       }
  268.       Pixel(x, y) = (BYTE) val;
  269.     }
  270.   }
  271. }
  272. int iround(double f) {
  273.   return (int)(f+0.5);
  274. }
  275. double CByteImage::InterpolateNearestNeighbor(double x, double y) const
  276. {
  277.   int rx = iround(x);
  278.   if (rx<0 || m_width<=rx) {
  279.     return 0;
  280.   }
  281.   int ry = iround(y);
  282.   if (ry<0 || m_height<=ry) {
  283.     return 0;
  284.   }
  285.   BYTE val = Pixel(rx, ry);
  286.   return val;
  287. }
  288. double CByteImage::InterpolateLinear(double x, double y) const
  289. {
  290.   int left = (int) floor(x);
  291.   if (left<-1 || m_width<=left) {
  292.     return 0;
  293.   }
  294.   int top = (int) floor(y);
  295.   if (top<-1 || m_height<=top) {
  296.     return 0;
  297.   }
  298.   int right = left+1;
  299.   int bottom = top+1;
  300.   BYTE val_lt, val_lb, val_rt, val_rb;
  301.   if (left==-1) {
  302.     val_lt = 0;
  303.     val_lb = 0;
  304.   } else {
  305.     if (top==-1) {
  306.       val_lt = 0;
  307.     } else {
  308.       val_lt = Pixel(left, top);
  309.     }
  310.     if (bottom==m_height) {
  311.       val_lb = 0;
  312.     } else {
  313.       val_lb = Pixel(left, bottom);
  314.     }
  315.   }
  316.   if (right==m_width) {
  317.     val_rt = 0;
  318.     val_rb = 0;
  319.   } else {
  320.     if (top==-1) {
  321.       val_rt = 0;
  322.     } else {
  323.       val_rt = Pixel(right, top);
  324.     }
  325.     if (bottom==m_height) {
  326.       val_rb = 0;
  327.     } else {
  328.       val_rb = Pixel(right, bottom);
  329.     }
  330.   }
  331.   double frac_x = x-(double)left;
  332.   double frac_y = y-(double)top;
  333.   double val = (1.0-frac_y)*((1.0-frac_x)*val_lt+frac_x*val_rt)
  334.     + frac_y*((1.0-frac_x)*val_lb+frac_x*val_rb);
  335.   return val;
  336. }
  337. void CByteImage::Rotate(double degrees, int xCenter, int yCenter)
  338. {
  339.   if (degrees==0.0) return;
  340.   //#ifdef DEBUG
  341.   if (xCenter<0 || xCenter>=m_width || yCenter<0 || yCenter>=m_height) {
  342.     char* buf = (char*) alloca(512*sizeof(char));
  343.     sprintf(buf, "%f %d %d %d %dn", degrees, xCenter, yCenter, m_width, m_height);
  344.     throw ITException(buf);
  345.   }
  346.   //#endif // DEBUG
  347.   ASSERT(0<=xCenter && xCenter<m_width);
  348.   ASSERT(0<=yCenter && yCenter<m_height);
  349.   CByteImage old_img;
  350.   old_img.Copy(*this);
  351.   double rad = degrees*M_PI/180.0;
  352.   double cos_rad = cos(rad);
  353.   double sin_rad = sin(rad);
  354.   for (int y=0; y<m_height; y++) {
  355.     for (int x=0; x<m_width; x++) {
  356.       double rel_x = x-xCenter;
  357.       double rel_y = y-yCenter;
  358.       double rot_x = rel_x*cos_rad - rel_y*sin_rad;
  359.       double rot_y = rel_x*sin_rad + rel_y*cos_rad;
  360.       double val = old_img.InterpolateLinear(xCenter+rot_x, yCenter+rot_y);
  361.       ASSERT(0.0<=val && val<=255.0);
  362.       Pixel(x, y) = (BYTE) val;
  363.     }
  364.   }  
  365. }
  366. void CByteImage::Crop(const CRect& area)
  367. {
  368.   ASSERT(area.left<area.right && area.top<area.bottom);
  369.   ASSERT(0<=area.left && area.right<m_width);
  370.   ASSERT(0<=area.top && area.bottom<m_height);
  371.   int old_width = m_width;
  372.   BYTE* pOldData = m_pData;
  373.   if (!m_data_is_local) {
  374.     Allocate(area.right-area.left, area.bottom-area.top);
  375.     // previous call changed m_width and m_height also
  376.   } else {
  377.     m_width = area.right-area.left;
  378.     m_height = area.bottom-area.top;
  379.   }
  380.   for (int y=0; y<m_height; y++) {
  381.     for (int x=0; x<m_width; x++) {
  382.       Pixel(x, y) = pOldData[(area.left+x) + (area.top+y)*old_width];
  383.     }
  384.   }
  385.   m_data.resize(m_width*m_height);
  386. }
  387. /* this is not very efficient and should only be used for testing
  388. */
  389. void CByteImage::Standardize(int ip_method)
  390. {
  391.   if (ip_method==0) {
  392.     // equalize histogram
  393.     ASSERT(0);
  394.     /*
  395.       IplImage* ipl_img = CreateIplImage();
  396.       const int range = 256;
  397.       IplLUT lut = { range+1, NULL,NULL,NULL, IPL_LUT_LOOKUP };
  398.       IplLUT* plut = &lut;
  399.       lut.key = new int[range+1];
  400.       lut.value = new int[range];
  401.       // Initialize the histogram levels
  402.       for(int i=0; i<=range; i++) lut.key[i] = i;
  403.       // Compute histogram
  404.       iplComputeHisto( ipl_img, &plut );
  405.       // Equalize histogram = rescale range of image data
  406.       iplHistoEqualize( ipl_img, ipl_img, &plut );
  407.       delete[] lut.key;
  408.       delete[] lut.value;
  409.       DeleteIplImage(ipl_img);
  410.     */
  411.   } else if (ip_method==1) {
  412.     // normalize image
  413.     // find avg
  414.     int sum=0;
  415.     { for (int y=0; y<m_height; y++) {
  416.       for (int x=0; x<m_width; x++) {
  417.         sum += Pixel(x, y);
  418.       }
  419.     } }
  420.     double N = m_height*m_width;
  421.     double avg = (double)sum/N;
  422.     // find stddev
  423.     double varsum=0;
  424.     { for (int y=0; y<m_height; y++) {
  425.       for (int x=0; x<m_width; x++) {
  426.         double val = (double)Pixel(x, y)-avg;
  427.         varsum += val*val;
  428.       }
  429.     } }
  430.     double stddev = sqrt(varsum/N);
  431.     // normalize
  432.     { for (int y=0; y<m_height; y++) {
  433.       for (int x=0; x<m_width; x++) {
  434.         double newpix = ((double)Pixel(x, y)-avg) / stddev;
  435.         newpix *= 127.5;
  436.         newpix += 127.5;
  437.         if (newpix<0) {
  438.           Pixel(x, y) = 0;
  439.         } else if (newpix>255) {
  440.           Pixel(x, y) = 255;
  441.         } else {
  442.           Pixel(x, y) = (BYTE) newpix;
  443.         }
  444.       }
  445.     } }
  446.   } else if (ip_method==2) {
  447.     // adjust image range
  448.     BYTE min=255;
  449.     BYTE max=0;
  450.     { for (int y=0; y<m_height; y++) {
  451.       for (int x=0; x<m_width; x++) {
  452.         BYTE pix = Pixel(x, y);
  453.         if (max<pix) max=pix;
  454.         if (min>pix) min=pix;
  455.       }
  456.     } }
  457.     double fac = 255.0/(double)(max-min);
  458.     // move pixel values
  459.     { for (int y=0; y<m_height; y++) {
  460.       for (int x=0; x<m_width; x++) {
  461.         Pixel(x, y) = (BYTE) ((double)(Pixel(x, y)-min)*fac);
  462.       }
  463.     } }
  464.   } else {
  465.     ASSERT(0);
  466.   }
  467. }
  468. // load image from disk
  469. void CByteImage::ImportFromFile(string filename) throw (ITEFile)
  470. {
  471.   if (filename.compare("")==0) {
  472.     throw ITEFile("-", "no filename given");
  473.   }
  474. #ifdef WIN32
  475.   filename = ConvertPathToWindows(filename);
  476. #endif // WIN32
  477. #if defined(IMG_LIB_MAGICK)
  478.   try {
  479.     Image tmpimg;
  480.     tmpimg.read(filename.c_str());
  481.     int width = tmpimg.baseColumns();
  482.     int height = tmpimg.baseRows();
  483.     
  484.     const PixelPacket* pData = tmpimg.getConstPixels(0, 0, width, height);
  485.     ASSERT(pData);
  486.     Allocate(width, height);
  487.     for (int y=0; y<height; y++) {
  488.       for (int x=0; x<width; x++) {
  489.         Pixel(x, y) =
  490.           (BYTE) (0.212671 * (double)(pData->red>>(QuantumDepth-8)) +
  491.                   0.715160 * (double)(pData->green>>(QuantumDepth-8)) +
  492.                   0.072169 * (double)(pData->blue>>(QuantumDepth-8)));
  493.         pData++;
  494.       }
  495.     }
  496.   } catch (Magick::Exception &error) {
  497.     throw ITEFile(filename,
  498.   string("exception during image reading with Magick:n")
  499.                   +error.what());
  500.   }
  501.     
  502. #elif defined(IMG_LIB_OPENCV)
  503.   // load image, don't change number of channels
  504.   IplImage* img = cvLoadImage(filename.c_str(), -1);
  505.   if (img==NULL) {
  506.     throw ITEFile(filename, "load failed in OpenCV");
  507.   }
  508.   Allocate(img->width, img->height);
  509.   if (img->nChannels==3) {
  510.     CvSize size = cvSize(img->width, img->height);
  511.     IplImage* gray = cvCreateImage(size, IPL_DEPTH_8U, 1);
  512.     cvCvtColor(img, gray, CV_BGR2GRAY);
  513.     cvReleaseImage(&img);
  514.     img = gray;
  515.   }
  516.   if (img->nChannels==1) {
  517.     ASSERT(m_pData);
  518.     memcpy(img->imageData, m_pData, m_width*m_height*sizeof(BYTE));
  519.   } else {
  520.     throw ITEFile(filename, "can not import");
  521.   }
  522.   cvReleaseImage(&img);
  523. #elif defined(IMG_LIB_NONE)
  524.   throw ITEFile(filename, "file import functionality not available");
  525. #else
  526. #error IMG_LIB not defined - you must at least define IMG_LIB_NONE explicitely
  527. #endif // IMG_LIB
  528. }
  529. void CByteImage::ExportToFile(string filename) throw (ITEFile)
  530. {
  531.   if (filename.compare("")==0) {
  532.     throw ITEFile("-", "no filename given");
  533.   }
  534. #ifdef WIN32
  535.   filename = ConvertPathToWindows(filename);
  536. #endif // WIN32
  537. #if defined(IMG_LIB_MAGICK)
  538.   Image tmpimg(Geometry(m_width, m_height), Color("red"));
  539.   tmpimg.modifyImage();
  540.   PixelPacket* pTmpPixel = tmpimg.getPixels(0, 0, m_width, m_height);
  541.   for (int y=0; y<m_height; y++) {
  542.     for (int x=0; x<m_width; x++) {
  543.       BYTE p = Pixel(x, y);
  544.       pTmpPixel->red = p;
  545.       pTmpPixel->green = p;
  546.       pTmpPixel->blue = p;
  547.       pTmpPixel++;
  548.     }
  549.   }
  550.   tmpimg.type(GrayscaleType);
  551.   tmpimg.syncPixels();
  552.   try {
  553.     tmpimg.write(filename.c_str());
  554.   } catch (Exception &error) {
  555.     throw ITEFile(filename,
  556.   string("exception in Magick.read: ")+error.what());
  557.   }
  558. #else // IMG_LIB
  559.   throw ITEFile(filename, "file export functionality not available");
  560. #endif // IMG_LIB
  561. }