stereoMatching.cpp
上传用户:fengshi120
上传日期:2014-07-17
资源大小:6155k
文件大小:14k
源码类别:

3D图形编程

开发平台:

C/C++

  1. /*************************************************************************** 
  2. *
  3. * Copyright 2000 by David Demirdjian.   All rights reserved. 
  4. *  
  5. * Developed  by David Demirdjian
  6. *  
  7. * Permission to use, copy, or modify this software and  its documentation 
  8. * for  educational  and  research purposes only and without fee  is hereby 
  9. * granted, provided  that this copyright notice and the original authors's 
  10. * names appear  on all copies and supporting documentation.  If individual 
  11. * files are  separated from  this  distribution directory  structure, this 
  12. * copyright notice must be included.  For any other uses of this software, 
  13. * in original or  modified form, including but not limited to distribution 
  14. * in whole or in  part, specific  prior permission  must be  obtained from 
  15. * MIT.  These programs shall not  be  used, rewritten, or  adapted as  the 
  16. * basis  of  a  commercial  software  or  hardware product  without  first 
  17. * obtaining appropriate  licenses from David Demirdjian.  The author makes 
  18. * no representations about the suitability of this software for any purpose.  
  19. * It is provided "as is" without express or implied warranty. 
  20. *  
  21. **************************************************************************/
  22. #include "stdafx.h"
  23. #include "stereoMatching.h"
  24. #include "processingMMX.h"
  25. typedef unsigned char uchar;
  26. typedef unsigned short ushort;
  27. #define ALLOC_ALIGN_MEMORY(X, X_origin, type, size) (X_origin)=((type*)malloc((size)*sizeof(type)+127)); (X) = (type*)((((unsigned int)(X_origin))+127) & (~127));
  28. #define DELETENULL(object) if (object) {delete object;object = NULL;}
  29. #define FREENULL(object) if (object) {free(object); object = NULL;}
  30. #ifdef _DEBUG
  31. #define new DEBUG_NEW
  32. #undef THIS_FILE
  33. static char THIS_FILE[] = __FILE__;
  34. #endif
  35. // ******************************************************************
  36. // ******************************************************************
  37. StereoMatching::StereoMatching()
  38. {
  39. maxNbDepth = 48;
  40. numScales = 5;
  41. scale = 0;
  42. width = 320; 
  43. height = 240;
  44. scaleProcessing = MONOSCALE;
  45. sbuffer = NULL;
  46. inputImages = NULL;
  47. scorePrev_origin = scoreInit_origin = scoreNext_origin = NULL;
  48. }
  49. StereoMatching::~StereoMatching()
  50. {
  51. destroyContext();
  52. }
  53. void StereoMatching::initializeContext()
  54. {
  55. destroyContext();
  56. sbuffer = new StereoBuffer[numScales];
  57. inputImages = new InputImages[numScales];
  58. for (int i=0, fact=1; i<numScales; ++i)
  59. {
  60. sbuffer[i].setSize(width/fact, height/fact, maxNbDepth/fact);
  61. sbuffer[i].alloc();
  62. inputImages[i].alloc(width/fact, height/fact, maxNbDepth/fact+21);
  63. fact *= 2;
  64. }
  65. // alloc for sub-pixel 
  66. ALLOC_ALIGN_MEMORY(scorePrev, scorePrev_origin, float, width*height);
  67. ALLOC_ALIGN_MEMORY(scoreInit, scoreInit_origin, float, width*height);
  68. ALLOC_ALIGN_MEMORY(scoreNext, scoreNext_origin, float, width*height);
  69. }
  70. void StereoMatching::destroyContext()
  71. {
  72. if (sbuffer)
  73. {
  74. for (int i=0; i<numScales; ++i)
  75. sbuffer[i].deAlloc();
  76. delete[] sbuffer;
  77. sbuffer = NULL;
  78. }
  79. if (inputImages)
  80. {
  81. for (int i=0; i<numScales; ++i)
  82. inputImages[i].deAlloc();
  83. delete[] inputImages;
  84. inputImages = NULL;
  85. }
  86. FREENULL(scorePrev_origin);
  87. FREENULL(scoreInit_origin);
  88. FREENULL(scoreNext_origin);
  89. }
  90. void StereoMatching::setHoropter (const int horopt)
  91. {
  92. horopter = horopt;
  93. }
  94. // set numScales
  95. void StereoMatching::setNumScales (const int numScales)
  96. {
  97. this->numScales = numScales;
  98. }
  99. int StereoMatching::getNumScales() const
  100. {
  101. return numScales;
  102. }
  103. // set the scale to process
  104. void StereoMatching::setScale (const int scale)
  105. {
  106. this->scale = scale;
  107. }
  108. int StereoMatching::getScale() const
  109. {
  110. return scale;
  111. }
  112. // for monoscale (standard) or multiscale
  113. void StereoMatching::setScaleProcessing(tScaleProcessing sprocessing)
  114. {
  115. scaleProcessing = sprocessing;
  116. }
  117. StereoMatching::tScaleProcessing StereoMatching::getScaleProcessing(void) const
  118. {
  119. return scaleProcessing;
  120. }
  121. void StereoMatching::setNumDepth (const int nbD)
  122. {
  123. if (nbD % 8 == 0) 
  124. nbDepth= nbD;
  125. else 
  126. nbDepth= 8*(1 +nbD/8);
  127. // change the max. num of depth (for memory allocation)
  128. if (nbDepth>maxNbDepth) {
  129. destroyContext();
  130. maxNbDepth = nbDepth + 32;
  131. initializeContext();
  132. }
  133. }
  134. void StereoMatching::setInputImageSize(int w, int h)
  135. {
  136. if (width!=w && height!=h) {
  137. destroyContext();
  138. width=w; 
  139. height=h;
  140. initializeContext();
  141. }
  142. }
  143. void StereoMatching::setAcceptDisparityThreshold(const float newVal)
  144. {
  145. peakValidationThreshold = newVal;
  146. }
  147. int StereoMatching::getWidth() const
  148. {
  149. return width;
  150. }
  151. int StereoMatching::getHeight() const
  152. {
  153. return height;
  154. }
  155. int StereoMatching::getHoropter() const
  156. {
  157. return horopter;
  158. }
  159. int StereoMatching::getNumDepth() const
  160. {
  161. return nbDepth;
  162. }
  163. float StereoMatching::getAcceptDisparityThreshold() const
  164. {
  165. return peakValidationThreshold;
  166. }
  167. void StereoMatching::setCorrelationWindowSize(const int hmaskX, const int hmaskY)
  168. {
  169. maskSizeX=hmaskX;
  170. maskSizeY=hmaskY;
  171. }
  172. int StereoMatching::getCorrelationWindowSizeX() const
  173. {
  174. return maskSizeX;
  175. }
  176. int StereoMatching::getCorrelationWindowSizeY() const
  177. {
  178. return maskSizeY;
  179. }
  180. // compute normalize/translated images
  181. void StereoMatching::setInputImages(int sc, const uchar* iml8_bw,  const uchar* imr8_bw)
  182. {
  183. InputImages* inImage = inputImages+sc;
  184. inImage->numImages = 2;
  185. int f = (int)pow(2, sc);
  186. int w = width/f, h = height/f;
  187. if (sc>0) {
  188. // shrink images
  189. shrinkImages(inImage->subIm_l, iml8_bw, width, height, f);
  190. shrinkImages(inImage->subIm_r, imr8_bw, width, height, f);
  191. // intensity normalization
  192. normalizeImages(inImage->subIm_l, inImage->subIm_r, w*h);
  193. } else {
  194. // intensity normalization
  195. normalizeImages(iml8_bw, imr8_bw, inImage->subIm_l, inImage->subIm_r, w*h);
  196. }
  197. // translate left image (horopter)
  198. translateImage(horopter/f, inImage->subIm_l, w*h);
  199. }
  200. // compute normalize/translated images
  201. void StereoMatching::setInputImages(int sc, const uchar* iml8_bw,  const uchar* imr8_bw,
  202. const uchar* imt8_bw)
  203. {
  204. InputImages* inImage = inputImages+sc;
  205. inImage->numImages = 3;
  206. int f = (int)pow(2, sc);
  207. int w = width/f, h = height/f;
  208. if (sc>0) {
  209. // shrink images
  210. shrinkImages(inImage->subIm_l, iml8_bw, width, height, f);
  211. shrinkImages(inImage->subIm_r, imr8_bw, width, height, f);
  212. shrinkImages(inImage->subIm_t, imt8_bw, width, height, f);
  213. // intensity normalization
  214. normalizeImages(inImage->subIm_l, inImage->subIm_r, inImage->subIm_t, w*h);
  215. } else {
  216. // intensity normalization
  217. normalizeImages(iml8_bw, imr8_bw, imt8_bw,
  218. inImage->subIm_l, inImage->subIm_r, inImage->subIm_t, w*h);
  219. }
  220. // translate left image (horopter)
  221. translateImage(horopter/f, inImage->subIm_l, w*h);
  222. }
  223. // --------- stereo ---------------------------------------------
  224. void StereoMatching::doStereo_fixedScale(StereoImage* simage, int sc, const InputImages* inImage)
  225. {
  226. int f = (int)pow(2, sc);
  227. // SAD estimation, etc...
  228. if (inImage->numImages == 2)
  229. estimateStereo_Horiz(inImage->subIm_l, inImage->subIm_r, width/f,height/f,
  230.  maskSizeX,maskSizeY,  
  231. (uchar)peakValidationThreshold, nbDepth/f, 8,
  232.  sbuffer+sc, simage);
  233. else if (inImage->numImages == 3)
  234. estimateStereo(inImage->subIm_l, inImage->subIm_r, inImage->subIm_t, 
  235. width/f,height/f,  maskSizeX,maskSizeY,  
  236. (uchar)peakValidationThreshold, nbDepth/f, 8,
  237.  sbuffer+sc, simage);
  238. simage->setUndefinedBorders(maskSizeX/2,maskSizeX/2);
  239. }
  240. void StereoMatching::doStereo(StereoImage* simage, 
  241.   const uchar* iml8_bw, const uchar* imr8_bw, const uchar* imt8_bw)
  242. {
  243. // (re)alloc (output) simage if it does not fit
  244. int f = (int)pow(2, scale);
  245. if( simage->width != width/f || simage->height != height/f)
  246. simage->alloc(width/f,height/f);
  247. // pre-process (input) images (inputImages)
  248. if (!imt8_bw) setInputImages(scale, iml8_bw,imr8_bw);
  249. else setInputImages(scale, iml8_bw,imr8_bw,imt8_bw);
  250. switch(scaleProcessing) {
  251. case MONOSCALE:
  252. if (scale==0) {
  253. doStereo_fixedScale(simage, scale, inputImages);
  254. } else {
  255. doStereo_fixedScale(simage, scale, inputImages+scale);
  256. }
  257. // sub-pixel estimation
  258. getList_subPixel(simage, scale);
  259. break;
  260. case MULTISCALE: {
  261. // compute image at LOWER scale
  262. // alloc lowres stereo image
  263. StereoImage* lowscaleSImage = new StereoImage();
  264. lowscaleSImage->alloc(simage->width/2,simage->height/2);
  265. int lowScale = scale+1;
  266. setInputImages(lowScale, iml8_bw,imr8_bw);
  267. doStereo_fixedScale(lowscaleSImage, lowScale, inputImages+lowScale);
  268. // sub-pixel estimation
  269. getList_subPixel(lowscaleSImage, lowScale);
  270. StereoImage* highscaleSImage = new StereoImage();
  271. highscaleSImage->alloc(simage->width,simage->height);
  272. setInputImages(scale, iml8_bw,imr8_bw);
  273. doStereo_fixedScale(highscaleSImage, scale, inputImages+scale);
  274. getList_subPixel(highscaleSImage, scale);
  275. // compute image at HIGHER scale 
  276. doStereo_multiscale(simage, highscaleSImage, lowscaleSImage, 0);
  277. delete lowscaleSImage;
  278. delete highscaleSImage;
  279. }
  280. break;
  281. }
  282. subPixelPerformed = true;
  283. }
  284. // -------- multiscale algorithm
  285. // assumes simageHigh and simageLow are 2 stereo images estimated at some consecutive scales
  286. void StereoMatching::doStereo_multiscale(StereoImage* simage,
  287. const StereoImage* simageHigh, const StereoImage* simageLow, 
  288. const unsigned char acceptNew)
  289. {
  290. // copy 8u/32f depth image
  291. unsigned char* ptDepth8u_new = simage->imDepth8u;
  292. unsigned char* ptDepth8u_lowres = simageLow->imDepth8u;
  293. for (int i=0; i<simageLow->height; ++i) {
  294. for (int j=0; j<simageLow->width; ++j) {
  295. *ptDepth8u_new = 2* *ptDepth8u_lowres;
  296. *(ptDepth8u_new+1) = 2* *ptDepth8u_lowres;
  297. *(ptDepth8u_new+simage->width) = 2* *ptDepth8u_lowres;
  298. *(ptDepth8u_new+simage->width+1) = 2* *ptDepth8u_lowres;
  299. ptDepth8u_lowres++;
  300. ptDepth8u_new+=2;
  301. }
  302. ptDepth8u_new+=simage->width;
  303. }
  304. short* x_low = simageLow->x, *y_low = simageLow->y;
  305. float* d_low = simageLow->depth_float_list;
  306. short* x_high = simage->x, *y_high = simage->y;
  307. float* d_high = simage->depth_float_list;
  308. simage->m_nGood3DPoints = 4*simageLow->m_nGood3DPoints;
  309. for (int i=0; i<simageLow->m_nGood3DPoints; ++i,++x_low,++y_low,++d_low) {
  310. float NEWD = 2* *d_low;
  311. *x_high = 2* *x_low;
  312. *y_high = 2* *y_low;
  313. *d_high = NEWD;
  314. ++x_high; ++y_high; ++d_high;
  315. *x_high = 2* *x_low;
  316. *y_high = 2* *y_low+1;
  317. *d_high = NEWD;
  318. ++x_high; ++y_high; ++d_high;
  319. *x_high = 2* *x_low+1;
  320. *y_high = 2* *y_low;
  321. *d_high = NEWD;
  322. ++x_high; ++y_high; ++d_high;
  323. *x_high = 2* *x_low+1;
  324. *y_high = 2* *y_low+1;
  325. *d_high = NEWD;
  326. ++x_high; ++y_high; ++d_high;
  327. }
  328. simage->generateDepth32f();
  329. float* ptDepth32f_new = simage->imDepth32f;
  330. float* ptDepth32f_highres = simageHigh->imDepth32f;
  331. for (int i=0; i<simageHigh->height; ++i) {
  332. for (int j=0; j<simageHigh->width; ++j) {
  333. if (*ptDepth32f_highres != 0) *ptDepth32f_new = *ptDepth32f_highres;
  334. ptDepth32f_highres++;
  335. ptDepth32f_new++;
  336. }
  337. }
  338. simage->generateDepth8uFromDepth32f();
  339. }
  340. // --------- stereo + filling -----------------------------------
  341. void StereoMatching::doStereo_grow(StereoImage* sdata, int mode, const uchar acceptNew, int nbIteration)
  342. {
  343. int backStep = (maskSizeY/2)*width;
  344. // save original sdata->imDepth8u in imDepth_ref
  345. memcpy(sbuffer[0].imDepth_ref, sdata->imDepth8u, width*height);
  346. for (int i=0; i<nbIteration; ++i) {
  347. // count non undefined pixels
  348. binarize(sdata->imDepth8u, sbuffer[0].count_non_null_pixels, sdata->UNDEFINED_DEPTH, width*height);
  349. sum_5x5_mmx(sbuffer[0].count_non_null_pixels, sbuffer[0].count_non_null_pixels, width*height, width, sbuffer[0].buffTemp);
  350. // count sum of depths
  351. set_undefined_to_zero(sdata->imDepth8u, sdata->imDepth8u, sdata->UNDEFINED_DEPTH, width*height);
  352. sum_5x5_mmx(sdata->imDepth8u, sbuffer[0].Depth16, width*height, width, sbuffer[0].buffTemp);
  353. divide(sbuffer[0].Depth16 + 2*width, sbuffer[0].count_non_null_pixels + 2*width, sdata->imDepth8u + 2*width, width*(height-4-(maskSizeY/2)));
  354. if (mode==1)
  355. checkDisparityValidity( sdata->imDepth8u+ 2*width,  sbuffer[0].buff[0]+ 2*width, width*height,
  356. sbuffer[0].corrScore+ 2*width,  acceptNew, 
  357. sdata->UNDEFINED_DEPTH, nbDepth, width*(height-(maskSizeY/2)));
  358. else 
  359. checkDisparityValidityAndSearchAround( sdata->imDepth8u+backStep, sbuffer[0].buff[0]+backStep, width*height, 
  360. sbuffer[0].corrScore+backStep, acceptNew, 
  361. sdata->UNDEFINED_DEPTH, nbDepth, width*height-2*backStep);
  362. overrideImage(sdata->imDepth8u+ 2*width, sbuffer[0].imDepth_ref+ 2*width, sdata->UNDEFINED_DEPTH, width*(height-4-(maskSizeY/2)));
  363. // set to UNDEFINED, pixels of sdata->imDepth8u which are surrounded by 0 defined points
  364. set_undefined_to_zero(sbuffer[0].count_non_null_pixels+ 2*width, sdata->imDepth8u+ 2*width, sdata->UNDEFINED_DEPTH, 
  365. width*(height-4) - backStep);
  366. sdata->setUndefinedBorders(maskSizeX/2,maskSizeX/2);
  367. }
  368. }
  369. // ------ functions to estimate validity of points (x,y,d) -------
  370. bool StereoMatching::checkValidity(short x, short y, uchar d, const char tol) const
  371. {
  372. if (x>=maskSizeY/2 && x<width-maskSizeY/2 && y>=maskSizeY/2 && y<height-maskSizeY/2 && d>=0 && d<nbDepth)
  373. {
  374. int idx = x + y*width;
  375. //uchar actual_disp = *(imDepth8u + idx);
  376. //if (actual_disp < nbDepth && actual_disp >= 0 && actual_disp != UNDEFINED_DEPTH) 
  377. // return  (*(buff[d]+idx) < *(buff[actual_disp]+idx) + tol);
  378. //else 
  379. // return true;
  380. return (*(sbuffer[0].buff[d]+idx) < *(sbuffer[0].corrScore+idx) + tol);
  381. }
  382. else return false;
  383. }
  384. short StereoMatching::checkValidity_error(short x, short y, uchar d, const char tol) const
  385. {
  386. if (x>=maskSizeY/2 && x<width-maskSizeY/2 && y>=maskSizeY/2 && y<height-maskSizeY/2 && d>=0 && d<nbDepth)
  387. {
  388. int idx = x + y*width;
  389. return abs(*(sbuffer[0].buff[d]+idx) - *(sbuffer[0].corrScore+idx));
  390. }
  391. else return -1;
  392. }