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

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. leftImageXOffset = 0;
  43. leftImageYOffset = 0;
  44. width = 320; 
  45. height = 240;
  46. scaleProcessing = MONOSCALE;
  47. sbuffer = NULL;
  48. inputImages = NULL;
  49. scorePrev_origin = scoreInit_origin = scoreNext_origin = NULL;
  50. }
  51. StereoMatching::~StereoMatching()
  52. {
  53. destroyContext();
  54. }
  55. void StereoMatching::initializeContext()
  56. {
  57. destroyContext();
  58. sbuffer = new StereoBuffer[numScales];
  59. inputImages = new InputImages[numScales];
  60. for (int i=0, fact=1; i<numScales; ++i)
  61. {
  62. sbuffer[i].setSize(width/fact, height/fact, maxNbDepth/fact);
  63. sbuffer[i].alloc();
  64. inputImages[i].alloc(width/fact, height/fact, maxNbDepth/fact+21);
  65. fact *= 2;
  66. }
  67. // alloc for sub-pixel 
  68. ALLOC_ALIGN_MEMORY(scorePrev, scorePrev_origin, float, width*height);
  69. ALLOC_ALIGN_MEMORY(scoreInit, scoreInit_origin, float, width*height);
  70. ALLOC_ALIGN_MEMORY(scoreNext, scoreNext_origin, float, width*height);
  71. }
  72. void StereoMatching::destroyContext()
  73. {
  74. if (sbuffer)
  75. {
  76. for (int i=0; i<numScales; ++i)
  77. sbuffer[i].deAlloc();
  78. delete[] sbuffer;
  79. sbuffer = NULL;
  80. }
  81. if (inputImages)
  82. {
  83. for (int i=0; i<numScales; ++i)
  84. inputImages[i].deAlloc();
  85. delete[] inputImages;
  86. inputImages = NULL;
  87. }
  88. FREENULL(scorePrev_origin);
  89. FREENULL(scoreInit_origin);
  90. FREENULL(scoreNext_origin);
  91. }
  92. void StereoMatching::setHoropter (const int horopt)
  93. {
  94. horopter = horopt;
  95. }
  96. // set numScales
  97. void StereoMatching::setNumScales (const int numScales)
  98. {
  99. this->numScales = numScales;
  100. }
  101. int StereoMatching::getNumScales() const
  102. {
  103. return numScales;
  104. }
  105. // set the scale to process
  106. void StereoMatching::setScale (const int scale)
  107. {
  108. this->scale = scale;
  109. }
  110. int StereoMatching::getScale() const
  111. {
  112. return scale;
  113. }
  114. void StereoMatching::setLeftImageXOffset(int x)
  115. {
  116. leftImageXOffset = x;
  117. }
  118. void StereoMatching::setLeftImageYOffset(int y)
  119. {
  120. leftImageYOffset = y;
  121. }
  122. int StereoMatching::getLeftImageXOffset() const
  123. {
  124. return leftImageXOffset;
  125. }
  126. int StereoMatching::getLeftImageYOffset() const
  127. {
  128. return leftImageYOffset;
  129. }
  130. // for monoscale (standard) or multiscale
  131. void StereoMatching::setScaleProcessing(tScaleProcessing sprocessing)
  132. {
  133. scaleProcessing = sprocessing;
  134. }
  135. StereoMatching::tScaleProcessing StereoMatching::getScaleProcessing(void) const
  136. {
  137. return scaleProcessing;
  138. }
  139. void StereoMatching::setNumDepth (const int nbD)
  140. {
  141. if (nbD % 8 == 0) 
  142. nbDepth= nbD;
  143. else 
  144. nbDepth= 8*(1 +nbD/8);
  145. // change the max. num of depth (for memory allocation)
  146. if (nbDepth>maxNbDepth) {
  147. destroyContext();
  148. maxNbDepth = nbDepth + 32;
  149. initializeContext();
  150. }
  151. }
  152. void StereoMatching::setInputImageSize(int w, int h)
  153. {
  154. if (width!=w && height!=h) {
  155. destroyContext();
  156. width=w; 
  157. height=h;
  158. initializeContext();
  159. }
  160. }
  161. void StereoMatching::setAcceptDisparityThreshold(const float newVal)
  162. {
  163. peakValidationThreshold = newVal;
  164. }
  165. int StereoMatching::getWidth() const
  166. {
  167. return width;
  168. }
  169. int StereoMatching::getHeight() const
  170. {
  171. return height;
  172. }
  173. int StereoMatching::getHoropter() const
  174. {
  175. return horopter;
  176. }
  177. int StereoMatching::getNumDepth() const
  178. {
  179. return nbDepth;
  180. }
  181. float StereoMatching::getAcceptDisparityThreshold() const
  182. {
  183. return peakValidationThreshold;
  184. }
  185. void StereoMatching::setCorrelationWindowSize(const int hmaskX, const int hmaskY)
  186. {
  187. maskSizeX=hmaskX;
  188. maskSizeY=hmaskY;
  189. }
  190. int StereoMatching::getCorrelationWindowSizeX() const
  191. {
  192. return maskSizeX;
  193. }
  194. int StereoMatching::getCorrelationWindowSizeY() const
  195. {
  196. return maskSizeY;
  197. }
  198. // compute normalize/translated images
  199. void StereoMatching::setInputImages(int sc, int  xOffset, int  yOffset, const uchar* iml8_bw,  const uchar* imr8_bw)
  200. {
  201. InputImages* inImage = inputImages+sc;
  202. inImage->numImages = 2;
  203. int f = (int)pow(2.0f, sc);
  204. int w = width/f, h = height/f;
  205. if (sc>0) {
  206. // shrink images
  207. shrinkImages(inImage->subIm_l, iml8_bw, width, height, f);
  208. shrinkImages(inImage->subIm_r, imr8_bw, width, height, f);
  209. // intensity normalization
  210. normalizeImages(inImage->subIm_l, inImage->subIm_r, w*h);
  211. } else {
  212. // intensity normalization
  213. normalizeImages(iml8_bw, imr8_bw, inImage->subIm_l, inImage->subIm_r, w*h);
  214. }
  215. // translate left image (horopter)
  216. translateImage((horopter+leftImageXOffset+leftImageYOffset*width)/f, inImage->subIm_l, w*h);
  217. }
  218. // compute normalize/translated images
  219. void StereoMatching::setInputImages(int sc, int  xOffset, int  yOffset, const uchar* iml8_bw,  const uchar* imr8_bw,
  220. const uchar* imt8_bw)
  221. {
  222. InputImages* inImage = inputImages+sc;
  223. inImage->numImages = 3;
  224. int f = (int)pow(2.0f, sc);
  225. int w = width/f, h = height/f;
  226. if (sc>0) {
  227. // shrink images
  228. shrinkImages(inImage->subIm_l, iml8_bw, width, height, f);
  229. shrinkImages(inImage->subIm_r, imr8_bw, width, height, f);
  230. shrinkImages(inImage->subIm_t, imt8_bw, width, height, f);
  231. // intensity normalization
  232. normalizeImages(inImage->subIm_l, inImage->subIm_r, inImage->subIm_t, w*h);
  233. } else {
  234. // intensity normalization
  235. normalizeImages(iml8_bw, imr8_bw, imt8_bw,
  236. inImage->subIm_l, inImage->subIm_r, inImage->subIm_t, w*h);
  237. }
  238. // translate left image (horopter)
  239. translateImage(horopter/f, inImage->subIm_l, w*h);
  240. }
  241. // --------- stereo ---------------------------------------------
  242. void StereoMatching::doStereo_fixedScale(StereoImage* simage, int sc, const InputImages* inImage)
  243. {
  244. int f = (int)pow(2.0f, sc);
  245. // SAD estimation, etc...
  246. if (inImage->numImages == 2) {
  247. int numdepths = nbDepth/f;
  248. numdepths = ((numdepths-1)/8+1)*8;
  249. estimateStereo_Horiz(inImage->subIm_l, inImage->subIm_r, width/f,height/f,
  250.  maskSizeX,maskSizeY,  
  251. (uchar)peakValidationThreshold, numdepths, 8,
  252.  sbuffer+sc, simage);
  253. } else if (inImage->numImages == 3)
  254. estimateStereo(inImage->subIm_l, inImage->subIm_r, inImage->subIm_t, 
  255. width/f,height/f,  maskSizeX,maskSizeY,  
  256. (uchar)peakValidationThreshold, nbDepth/f, 8,
  257.  sbuffer+sc, simage);
  258. simage->setUndefinedBorders(maskSizeX/2,maskSizeX/2);
  259. }
  260. void StereoMatching::doStereo(StereoImage* simage, 
  261.   const uchar* iml8_bw, const uchar* imr8_bw, const uchar* imt8_bw)
  262. {
  263. // (re)alloc (output) simage if it does not fit
  264. int f = (int)pow(2.0f, scale);
  265. if( simage->width != width/f || simage->height != height/f)
  266. simage->alloc(width/f,height/f);
  267. // pre-process (input) images (inputImages)
  268. if (!imt8_bw) setInputImages(scale, leftImageXOffset, leftImageYOffset, iml8_bw,imr8_bw);
  269. else setInputImages(scale, leftImageXOffset, leftImageYOffset, iml8_bw,imr8_bw,imt8_bw);
  270. switch(scaleProcessing) {
  271. case MONOSCALE:
  272. if (scale==0) {
  273. doStereo_fixedScale(simage, scale, inputImages);
  274. } else {
  275. doStereo_fixedScale(simage, scale, inputImages+scale);
  276. }
  277. // sub-pixel estimation
  278. getList_subPixel(simage, scale);
  279. break;
  280. case MULTISCALE: {
  281. // compute image at LOWER scale
  282. // alloc lowres stereo image
  283. StereoImage* lowscaleSImage = new StereoImage();
  284. lowscaleSImage->alloc(simage->width/2,simage->height/2);
  285. int lowScale = scale+1;
  286. setInputImages(lowScale, leftImageXOffset, leftImageYOffset, iml8_bw,imr8_bw);
  287. doStereo_fixedScale(lowscaleSImage, lowScale, inputImages+lowScale);
  288. // sub-pixel estimation
  289. getList_subPixel(lowscaleSImage, lowScale);
  290. StereoImage* highscaleSImage = new StereoImage();
  291. highscaleSImage->alloc(simage->width,simage->height);
  292. setInputImages(scale, leftImageXOffset, leftImageYOffset, iml8_bw,imr8_bw);
  293. doStereo_fixedScale(highscaleSImage, scale, inputImages+scale);
  294. getList_subPixel(highscaleSImage, scale);
  295. // compute image at HIGHER scale 
  296. doStereo_multiscale(simage, highscaleSImage, lowscaleSImage, 0);
  297. delete lowscaleSImage;
  298. delete highscaleSImage;
  299. }
  300. break;
  301. }
  302. subPixelPerformed = true;
  303. }
  304. // -------- multiscale algorithm
  305. // assumes simageHigh and simageLow are 2 stereo images estimated at some consecutive scales
  306. void StereoMatching::doStereo_multiscale(StereoImage* simage,
  307. const StereoImage* simageHigh, const StereoImage* simageLow, 
  308. const unsigned char acceptNew)
  309. {
  310. // copy 8u/32f depth image
  311. unsigned char* ptDepth8u_new = simage->imDepth8u;
  312. unsigned char* ptDepth8u_lowres = simageLow->imDepth8u;
  313. for (int i=0; i<simageLow->height; ++i) {
  314. for (int j=0; j<simageLow->width; ++j) {
  315. *ptDepth8u_new = 2* *ptDepth8u_lowres;
  316. *(ptDepth8u_new+1) = 2* *ptDepth8u_lowres;
  317. *(ptDepth8u_new+simage->width) = 2* *ptDepth8u_lowres;
  318. *(ptDepth8u_new+simage->width+1) = 2* *ptDepth8u_lowres;
  319. ptDepth8u_lowres++;
  320. ptDepth8u_new+=2;
  321. }
  322. ptDepth8u_new+=simage->width;
  323. }
  324. short* x_low = simageLow->x, *y_low = simageLow->y;
  325. float* d_low = simageLow->depth_float_list;
  326. short* x_high = simage->x, *y_high = simage->y;
  327. float* d_high = simage->depth_float_list;
  328. simage->m_nGood3DPoints = 4*simageLow->m_nGood3DPoints;
  329. for (int i=0; i<simageLow->m_nGood3DPoints; ++i,++x_low,++y_low,++d_low) {
  330. float NEWD = 2* *d_low;
  331. *x_high = 2* *x_low;
  332. *y_high = 2* *y_low;
  333. *d_high = NEWD;
  334. ++x_high; ++y_high; ++d_high;
  335. *x_high = 2* *x_low;
  336. *y_high = 2* *y_low+1;
  337. *d_high = NEWD;
  338. ++x_high; ++y_high; ++d_high;
  339. *x_high = 2* *x_low+1;
  340. *y_high = 2* *y_low;
  341. *d_high = NEWD;
  342. ++x_high; ++y_high; ++d_high;
  343. *x_high = 2* *x_low+1;
  344. *y_high = 2* *y_low+1;
  345. *d_high = NEWD;
  346. ++x_high; ++y_high; ++d_high;
  347. }
  348. simage->generateDepth32f();
  349. float* ptDepth32f_new = simage->imDepth32f;
  350. float* ptDepth32f_highres = simageHigh->imDepth32f;
  351. for (int i=0; i<simageHigh->height; ++i) {
  352. for (int j=0; j<simageHigh->width; ++j) {
  353. if (*ptDepth32f_highres != 0) *ptDepth32f_new = *ptDepth32f_highres;
  354. ptDepth32f_highres++;
  355. ptDepth32f_new++;
  356. }
  357. }
  358. simage->generateDepth8uFromDepth32f();
  359. }
  360. // --------- stereo + filling -----------------------------------
  361. void StereoMatching::doStereo_grow(StereoImage* sdata, int mode, const uchar acceptNew, int nbIteration)
  362. {
  363. int backStep = (maskSizeY/2)*width;
  364. // save original sdata->imDepth8u in imDepth_ref
  365. memcpy(sbuffer[0].imDepth_ref, sdata->imDepth8u, width*height);
  366. for (int i=0; i<nbIteration; ++i) {
  367. // count non undefined pixels
  368. binarize(sdata->imDepth8u, sbuffer[0].count_non_null_pixels, sdata->UNDEFINED_DEPTH, width*height);
  369. sum_5x5_mmx(sbuffer[0].count_non_null_pixels, sbuffer[0].count_non_null_pixels, width*height, width, sbuffer[0].buffTemp);
  370. // count sum of depths
  371. set_undefined_to_zero(sdata->imDepth8u, sdata->imDepth8u, sdata->UNDEFINED_DEPTH, width*height);
  372. sum_5x5_mmx(sdata->imDepth8u, sbuffer[0].Depth16, width*height, width, sbuffer[0].buffTemp);
  373. divide(sbuffer[0].Depth16 + 2*width, sbuffer[0].count_non_null_pixels + 2*width, sdata->imDepth8u + 2*width, width*(height-4-(maskSizeY/2)));
  374. if (mode==1)
  375. checkDisparityValidity( sdata->imDepth8u+ 2*width,  sbuffer[0].buff[0]+ 2*width, width*height,
  376. sbuffer[0].corrScore+ 2*width,  acceptNew, 
  377. sdata->UNDEFINED_DEPTH, nbDepth, width*(height-(maskSizeY/2)));
  378. else 
  379. checkDisparityValidityAndSearchAround( sdata->imDepth8u+backStep, sbuffer[0].buff[0]+backStep, width*height, 
  380. sbuffer[0].corrScore+backStep, acceptNew, 
  381. sdata->UNDEFINED_DEPTH, nbDepth, width*height-2*backStep);
  382. overrideImage(sdata->imDepth8u+ 2*width, sbuffer[0].imDepth_ref+ 2*width, sdata->UNDEFINED_DEPTH, width*(height-4-(maskSizeY/2)));
  383. // set to UNDEFINED, pixels of sdata->imDepth8u which are surrounded by 0 defined points
  384. set_undefined_to_zero(sbuffer[0].count_non_null_pixels+ 2*width, sdata->imDepth8u+ 2*width, sdata->UNDEFINED_DEPTH, 
  385. width*(height-4) - backStep);
  386. sdata->setUndefinedBorders(maskSizeX/2,maskSizeX/2);
  387. }
  388. }
  389. // ------ functions to estimate validity of points (x,y,d) -------
  390. bool StereoMatching::checkValidity(short x, short y, uchar d, const char tol) const
  391. {
  392. if (x>=maskSizeY/2 && x<width-maskSizeY/2 && y>=maskSizeY/2 && y<height-maskSizeY/2 && d>=0 && d<nbDepth)
  393. {
  394. int idx = x + y*width;
  395. //uchar actual_disp = *(imDepth8u + idx);
  396. //if (actual_disp < nbDepth && actual_disp >= 0 && actual_disp != UNDEFINED_DEPTH) 
  397. // return  (*(buff[d]+idx) < *(buff[actual_disp]+idx) + tol);
  398. //else 
  399. // return true;
  400. return (*(sbuffer[0].buff[d]+idx) < *(sbuffer[0].corrScore+idx) + tol);
  401. }
  402. else return false;
  403. }
  404. short StereoMatching::checkValidity_error(short x, short y, uchar d, const char tol) const
  405. {
  406. if (x>=maskSizeY/2 && x<width-maskSizeY/2 && y>=maskSizeY/2 && y<height-maskSizeY/2 && d>=0 && d<nbDepth)
  407. {
  408. int idx = x + y*width;
  409. return abs(*(sbuffer[0].buff[d]+idx) - *(sbuffer[0].corrScore+idx));
  410. }
  411. else return -1;
  412. }