PageRenderTime 347ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/BoostTrackerPublic/Matrix.cpp

https://gitlab.com/jimador/simple-object-tracking
C++ | 508 lines | 389 code | 77 blank | 42 comment | 86 complexity | ee42c31d53763216bc2e70185e0e191a MD5 | raw file
  1. // MILTRACK
  2. // Copyright 2009 Boris Babenko (bbabenko@cs.ucsd.edu | http://vision.ucsd.edu/~bbabenko). Distributed under the terms of the GNU Lesser General Public License
  3. // (see the included gpl.txt and lgpl.txt files). Use at own risk. Please send me your feedback/suggestions/bugs.
  4. #include "Matrix.h"
  5. template<> float Matrixu::ii ( const int row, const int col, const int depth ) const
  6. {
  7. return (float) ((Ipp32f*)_iidata[depth])[row*_iipixStep + col];
  8. }
  9. template<> float Matrixu::dii_dx(uint x, uint y, uint channel)
  10. {
  11. if( !isInitII() ) abortError(__LINE__,__FILE__,"cannot take dii/dx, ii is not init");
  12. if( (x+1) > (uint)cols() || x < 1 ) return 0.0f;
  13. //0.5*(GET3(ii,y,(x+1),bin,rows,cols) - GET3(ii,y,(x-1),bin,rows,cols));
  14. return 0.5f * ( ii(y,(x+1),channel) - ii(y,(x-1),channel) );
  15. }
  16. template<> float Matrixu::dii_dy(uint x, uint y, uint channel)
  17. {
  18. if( !isInitII() ) abortError(__LINE__,__FILE__,"cannot take dii/dx, ii is not init");
  19. if( (y+1) > (uint)rows() || y < 1 ) return 0.0f;
  20. //0.5*(GET3(ii,y,(x+1),bin,rows,cols) - GET3(ii,y,(x-1),bin,rows,cols));
  21. return 0.5f * ( ii((y+1),x,channel) - ii((y-1),x,channel) );
  22. }
  23. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  24. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  25. template<> void Matrixu::initII()
  26. {
  27. bool err=false;
  28. _iidata.resize(_depth);
  29. for( uint k=0; k<_data.size(); k++ ){
  30. if( _iidata[k] == NULL )
  31. _iidata[k] = ippiMalloc_32f_C1(_cols+1,_rows+1,&(_iidataStep));
  32. if( _iidata[k] == NULL ) abortError(__LINE__,__FILE__,"OUT OF MEMORY!");
  33. _iipixStep = _iidataStep/sizeof(Ipp32f);
  34. IppStatus is = ippiIntegral_8u32f_C1R((Ipp8u*)_data[k], _dataStep, (Ipp32f*)_iidata[k], _iidataStep, _roi, 0);
  35. assert( is == ippStsNoErr );
  36. err = err || _data[k] == NULL;
  37. }
  38. _ii_init = true;
  39. }
  40. template<> float Matrixu::sumRect(const IppiRect &rect, int channel) const
  41. {
  42. // debug checks
  43. assert(_ii_init);
  44. assert( rect.x >= 0 && rect.y >= 0 && (rect.y+rect.height) <= _rows
  45. && (rect.x+rect.width) <= _cols && channel < _depth);
  46. int maxy = (rect.y+rect.height)*_iipixStep;
  47. int maxx = rect.x+rect.width;
  48. int y = rect.y*_iipixStep;
  49. float tl = ((Ipp32f*)_iidata[channel])[y + rect.x];
  50. float tr = ((Ipp32f*)_iidata[channel])[y + maxx];
  51. float br = ((Ipp32f*)_iidata[channel])[maxy + maxx];
  52. float bl = ((Ipp32f*)_iidata[channel])[maxy + rect.x];
  53. return br + tl - tr - bl;
  54. //return ii(maxy,maxx,channel) + ii(rect.y,rect.x,channel)
  55. // - ii(rect.y,maxx,channel) - ii(maxy,rect.x,channel);
  56. }
  57. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  58. //////////////////////////////////////////////////////////////////////////////////////////////////////////
  59. template<> void Matrixu::LoadImage(const char *filename, bool color)
  60. {
  61. IplImage *img;
  62. img = cvLoadImage(filename,(int)color);
  63. if( img == NULL )
  64. abortError(__LINE__,__FILE__,"Error loading file");
  65. Resize(img->height, img->width, img->nChannels);
  66. if( color )
  67. IplImage2Matrix(img);
  68. else{
  69. for( int row=0; row<_rows; row++ )
  70. for( int k=0; k<_cols; k++ ){
  71. ((Ipp8u*)_data[0])[row*_dataStep+k] = img->imageData[row*img->widthStep+k];
  72. }
  73. }
  74. cvReleaseImage(&img);
  75. }
  76. template<> void Matrixu::SaveImage(const char *filename)
  77. {
  78. createIpl();
  79. int success = cvSaveImage( filename, _iplimg );
  80. freeIpl();
  81. }
  82. template<> bool Matrixu::CaptureImage(CvCapture* capture, Matrixu &res, int color)
  83. {
  84. IplImage *img;
  85. if( capture == NULL ) return false;
  86. img = cvQueryFrame( capture );
  87. if( img == NULL ) return false;
  88. res.Resize(img->height, img->width, 1+2*color);
  89. if( color ){
  90. //res.Resize(img->height, img->width, 3);
  91. res.IplImage2Matrix(img);
  92. }
  93. else{
  94. static IplImage *img2;
  95. if( img2 == NULL ) img2 = cvCreateImage( cvSize(res._cols, res._rows), IPL_DEPTH_8U, 1 );
  96. cvCvtColor( img, img2, CV_RGB2GRAY );
  97. img2->origin = 0;
  98. res.GrayIplImage2Matrix(img2);
  99. }
  100. img = NULL;
  101. return true;
  102. }
  103. template<> bool Matrixu::WriteFrame(CvVideoWriter* w, Matrixu &img)
  104. {
  105. img.createIpl();
  106. if( w != NULL ){
  107. IplImage* iplimg = img.getIpl();
  108. iplimg->origin = 1;
  109. cvWriteFrame( w, iplimg );
  110. return true;
  111. }else
  112. return false;
  113. }
  114. template<> void Matrixu::PlayCam(int color, const char* fname)
  115. {
  116. CvCapture* capture = cvCreateCameraCapture( 0 );
  117. if( capture==NULL ) abortError(__LINE__,__FILE__,"camera not found!");
  118. CvVideoWriter* w = NULL;
  119. Matrixu frame;
  120. frame._keepIpl = false;
  121. cout << "Press q to quit" << endl;
  122. StopWatch sw(true);
  123. double ttime=0.0;
  124. for( int cnt=0; true; cnt++ )
  125. {
  126. CaptureImage(capture,frame,color);
  127. // initialize video output
  128. if( fname != NULL && w == NULL)
  129. w = cvCreateVideoWriter( fname, CV_FOURCC('I','Y', 'U', 'V'), 10, cvSize(frame.cols(), frame.rows()), 3 );
  130. // output (both screen and possibly to file)
  131. frame._keepIpl=true;
  132. frame.display(1); char q = cvWaitKey(1);
  133. WriteFrame(w, frame);
  134. frame._keepIpl=false; frame.freeIpl();
  135. // check key input
  136. if( q=='q' ) break;
  137. // timing
  138. ttime = sw.Elapsed(true);
  139. fprintf(stderr,"%s%d Frames/%f sec = %f FPS",ERASELINE,cnt,ttime,((double)cnt)/ttime);
  140. }
  141. cvReleaseCapture( &capture );
  142. if( w != NULL )
  143. cvReleaseVideoWriter( &w );
  144. }
  145. template<> void Matrixu::PlayCamOpenCV()
  146. {
  147. CvCapture* capture = cvCaptureFromCAM( -1 );
  148. if( capture == NULL )
  149. abortError(__LINE__,__FILE__,"Error finding cam");
  150. cout << "Press q to quit" << endl;
  151. IplImage *img;
  152. cvNamedWindow( "Cam", 0/*CV_WINDOW_AUTOSIZE*/ );
  153. StopWatch sw(true);
  154. double ttime=0.0;
  155. for( int cnt=0; true; cnt++ )
  156. {
  157. img = cvQueryFrame( capture );
  158. cvShowImage( "Cam", img );
  159. ttime = sw.Elapsed(true);
  160. fprintf(stderr,"%s%d Frames/%f sec = %f FPS",ERASELINE,cnt,ttime,((double)cnt)/ttime);
  161. char q = cvWaitKey(1);
  162. if( q=='q' ) break;
  163. }
  164. cvReleaseCapture( &capture );
  165. cout << endl << "Ending PlayCam" << endl;
  166. }
  167. template<> void Matrixu::createIpl(bool force)
  168. {
  169. if( _iplimg != NULL && !force) return;
  170. if( _iplimg != NULL ) cvReleaseImage(&_iplimg);
  171. CvSize sz; sz.width = _cols; sz.height = _rows;
  172. int depth = 3;
  173. _iplimg = cvCreateImageHeader( sz, IPL_DEPTH_8U, depth );
  174. //_iplimg->align = 32;
  175. //_iplimg->widthStep = (((_iplimg->width * _iplimg->nChannels *
  176. // (_iplimg->depth & ~IPL_DEPTH_SIGN) + 7)/8)+ _iplimg->align - 1) & (~(_iplimg->align - 1));
  177. //_iplimg->widthStep = _dataStep*depth;
  178. //_iplimg->imageSize = _iplimg->height*_iplimg->widthStep;
  179. cvCreateData(_iplimg);
  180. //cvInitImageHeader( _iplimg, sz, IPL_DEPTH_8U, _depth, IPL_ORIGIN_TL, 16 );
  181. //IplImage *_iplimg = cvCreateImage( sz, IPL_DEPTH_8U, _depth );
  182. //assert( _depth==1 ? _iplimg->widthStep == _dataStep : _iplimg->widthStep/3 == _dataStep ); // should always be the same (multiple of 32)
  183. if( _depth == 1 )
  184. for( int row=0; row<_rows; row++ )
  185. for( int k=0; k<_cols*3; k+=3 ){
  186. _iplimg->imageData[row*_iplimg->widthStep+k+2]=((Ipp8u*)_data[0])[row*_dataStep+k/3];
  187. _iplimg->imageData[row*_iplimg->widthStep+k+1]=((Ipp8u*)_data[0])[row*_dataStep+k/3];
  188. _iplimg->imageData[row*_iplimg->widthStep+k ]=((Ipp8u*)_data[0])[row*_dataStep+k/3];
  189. }
  190. else
  191. //for( int k=0; k<_rows*_dataStep*3; k+=3 ){
  192. // _iplimg->imageData[k+2] = ((Ipp8u*)_data[0])[k/3]; // B
  193. // _iplimg->imageData[k+1] = ((Ipp8u*)_data[1])[k/3]; // G
  194. // _iplimg->imageData[k ] = ((Ipp8u*)_data[2])[k/3]; // R
  195. //}
  196. for( int row=0; row<_rows; row++ )
  197. for( int k=0; k<_cols*3; k+=3 ){
  198. _iplimg->imageData[row*_iplimg->widthStep+k+2]=((Ipp8u*)_data[0])[row*_dataStep+k/3];
  199. _iplimg->imageData[row*_iplimg->widthStep+k+1]=((Ipp8u*)_data[1])[row*_dataStep+k/3];
  200. _iplimg->imageData[row*_iplimg->widthStep+k ]=((Ipp8u*)_data[2])[row*_dataStep+k/3];
  201. }
  202. }
  203. template<> void Matrixu::freeIpl()
  204. {
  205. if( !_keepIpl && _iplimg != NULL) cvReleaseImage(&_iplimg);
  206. }
  207. template<> void Matrixu::IplImage2Matrix(IplImage *img)
  208. {
  209. //Resize(img->height, img->width, img->nChannels);
  210. bool origin = img->origin==1;
  211. if( _depth == 1 )
  212. for( int row=0; row<_rows; row++ )
  213. for( int k=0; k<_cols*3; k+=3 )
  214. if( origin )
  215. ((Ipp8u*)_data[0])[(_rows - row - 1)*_dataStep+k/3] = img->imageData[row*img->widthStep+k];
  216. else
  217. ((Ipp8u*)_data[0])[row*_dataStep+k/3] = img->imageData[row*img->widthStep+k];
  218. else
  219. #pragma omp parallel for
  220. for( int row=0; row<_rows; row++ )
  221. for( int k=0; k<_cols*3; k+=3 ){
  222. if( origin ){
  223. ((Ipp8u*)_data[0])[(_rows - row - 1)*_dataStep+k/3] = img->imageData[row*img->widthStep+k+2];
  224. ((Ipp8u*)_data[1])[(_rows - row - 1)*_dataStep+k/3] = img->imageData[row*img->widthStep+k+1];
  225. ((Ipp8u*)_data[2])[(_rows - row - 1)*_dataStep+k/3] = img->imageData[row*img->widthStep+k];
  226. }
  227. else{
  228. ((Ipp8u*)_data[0])[row*_dataStep+k/3] = img->imageData[row*img->widthStep+k+2];
  229. ((Ipp8u*)_data[1])[row*_dataStep+k/3] = img->imageData[row*img->widthStep+k+1];
  230. ((Ipp8u*)_data[2])[row*_dataStep+k/3] = img->imageData[row*img->widthStep+k];
  231. }
  232. }
  233. if( _keepIpl )
  234. _iplimg = img;
  235. }
  236. template<> void Matrixu::GrayIplImage2Matrix(IplImage *img)
  237. {
  238. //Resize(img->height, img->width, img->nChannels);
  239. bool origin = img->origin==1;
  240. if( _depth == 1 )
  241. for( int row=0; row<_rows; row++ )
  242. for( int k=0; k<_cols; k++ )
  243. if( origin )
  244. ((Ipp8u*)_data[0])[(_rows - row - 1)*_dataStep+k] = img->imageData[row*img->widthStep+k];
  245. else
  246. ((Ipp8u*)_data[0])[row*_dataStep+k] = img->imageData[row*img->widthStep+k];
  247. }
  248. template<> void Matrixu::display(int fignum, float p)
  249. {
  250. assert(size() > 0);
  251. createIpl();
  252. char name[1024];
  253. sprintf_s(name,"Figure %d",fignum);
  254. cvNamedWindow( name, 0/*CV_WINDOW_AUTOSIZE*/ );
  255. cvShowImage( name, _iplimg );
  256. cvResizeWindow( name, max((int)(_cols*p),200), (int)max((int)(_rows*p),_rows*(200.0f/_cols)) );
  257. //cvWaitKey(0);//DEBUG
  258. freeIpl();
  259. }
  260. template<> void Matrixu::drawRect(IppiRect rect, int lineWidth, int R, int G, int B )
  261. {
  262. createIpl();
  263. CvPoint p1, p2;
  264. p1 = cvPoint(rect.x, rect.y);
  265. p2 = cvPoint(rect.x+rect.width,rect.y+rect.height);
  266. cvDrawRect(_iplimg, p1, p2, CV_RGB(R, G, B), lineWidth);
  267. IplImage2Matrix(_iplimg);
  268. freeIpl();
  269. }
  270. template<> void Matrixu::drawRect(float width, float height, float x,float y, float sc, float th, int lineWidth, int R, int G, int B)
  271. {
  272. sc = 1.0f/sc;
  273. th = -th;
  274. double cth = cos(th)*sc;
  275. double sth = sin(th)*sc;
  276. CvPoint p1, p2, p3, p4;
  277. p1.x = (int)(-cth*width/2 + sth*height/2 + width/2 + x);
  278. p1.y = (int)(-sth*width/2 - cth*height/2 + height/2 + y);
  279. p2.x = (int)(cth*width/2 + sth*height/2 + width/2 + x);
  280. p2.y = (int)(sth*width/2 - cth*height/2 + height/2 + y);
  281. p3.x = (int)(cth*width/2 - sth*height/2 + width/2 + x);
  282. p3.y = (int)(sth*width/2 + cth*height/2 + height/2 + y);
  283. p4.x = (int)(-cth*width/2 - sth*height/2 + width/2 + x);
  284. p4.y = (int)(-sth*width/2 + cth*height/2 + height/2 + y);
  285. //cout << p1.x << " " << p1.y << endl;
  286. //cout << p2.x << " " << p2.y << endl;
  287. //cout << p3.x << " " << p3.y << endl;
  288. //cout << p4.x << " " << p4.y << endl;
  289. createIpl();
  290. cvLine( _iplimg, p1, p2, CV_RGB( R, G, B), lineWidth, CV_AA );
  291. cvLine( _iplimg, p2, p3, CV_RGB( R, G, B), lineWidth, CV_AA );
  292. cvLine( _iplimg, p3, p4, CV_RGB( R, G, B), lineWidth, CV_AA );
  293. cvLine( _iplimg, p4, p1, CV_RGB( R, G, B), lineWidth, CV_AA );
  294. IplImage2Matrix(_iplimg);
  295. freeIpl();
  296. }
  297. template<> void Matrixu::drawEllipse(float height, float width, float x,float y, int lineWidth, int R, int G, int B)
  298. {
  299. createIpl();
  300. CvPoint p = cvPoint((int)x,(int)y);
  301. CvSize s = cvSize((int)width, (int)height);
  302. cvEllipse( _iplimg, p, s, 0, 0, 365, CV_RGB( R, G, B), lineWidth );
  303. IplImage2Matrix(_iplimg);
  304. freeIpl();
  305. }
  306. template<> void Matrixu::drawEllipse(float height, float width, float x,float y, float startang, float endang, int lineWidth, int R, int G, int B)
  307. {
  308. createIpl();
  309. CvPoint p = cvPoint((int)x,(int)y);
  310. CvSize s = cvSize((int)width, (int)height);
  311. cvEllipse( _iplimg, p, s, 0, startang, endang, CV_RGB( R, G, B), lineWidth );
  312. IplImage2Matrix(_iplimg);
  313. freeIpl();
  314. }
  315. template<> void Matrixu::drawText(const char* txt, float x, float y, int R, int G, int B)
  316. {
  317. createIpl();
  318. CvFont font;
  319. cvInitFont( &font, CV_FONT_HERSHEY_SIMPLEX, 1, 1, 0, 2, 8 );
  320. CvPoint p = cvPoint((int)x,(int)y);
  321. cvPutText( _iplimg, txt, p, &font, CV_RGB( R, G, B) );
  322. IplImage2Matrix(_iplimg);
  323. freeIpl();
  324. }
  325. template<> void Matrixu::warp(Matrixu &res,uint rows, uint cols, float x, float y, float sc, float th, float sr, float phi)
  326. {
  327. res.Resize(rows,cols,_depth);
  328. double coeffs[2][3];
  329. double quad[4][2];
  330. double cth = cos(th)*sc;
  331. double sth = sin(th)*sc;
  332. quad[0][0] = -cth*cols/2 + sth*rows/2 + cols/2;
  333. quad[0][1] = -sth*cols/2 - cth*rows/2 + rows/2;
  334. quad[1][0] = cth*cols/2 + sth*rows/2 + cols/2;
  335. quad[1][1] = sth*cols/2 - cth*rows/2 + rows/2;
  336. quad[2][0] = cth*cols/2 - sth*rows/2 + cols/2;
  337. quad[2][1] = sth*cols/2 + cth*rows/2 + rows/2;
  338. quad[3][0] = -cth*cols/2 - sth*rows/2 + cols/2;
  339. quad[3][1] = -sth*cols/2 + cth*rows/2 + rows/2;
  340. //cout << quad[0][0]+x << " " << quad[0][1]+y << endl;
  341. //cout << quad[1][0]+x << " " << quad[1][1]+y << endl;
  342. //cout << quad[2][0]+x << " " << quad[2][1]+y << endl;
  343. //cout << quad[3][0]+x << " " << quad[3][1]+y << endl << endl;
  344. IppiRect r;
  345. r.x = (int)x;
  346. r.y = (int)y;
  347. r.width = cols;
  348. r.height = rows;
  349. IppStatus ii = ippiGetAffineTransform(r, quad, coeffs);
  350. //#pragma omp parallel for
  351. for( int k=0; k<_depth; k++ )
  352. ippiWarpAffine_8u_C1R((Ipp8u*)_data[k],_roi, _dataStep, _roirect, (Ipp8u*)res._data[k],res._dataStep, res._roirect, coeffs, IPPI_INTER_LINEAR);
  353. }
  354. template<> void Matrixu::warpAll(uint rows, uint cols, vector<vectorf> params, vector<Matrixu> &res)
  355. {
  356. res.resize(params[0].size());
  357. #pragma omp parallel for
  358. for( int k=0; k<(int)params[0].size(); k++ )
  359. warp(res[k],rows,cols,params[0][k],params[1][k],params[2][k],params[3][k]);
  360. }
  361. template<> void Matrixu::computeGradChannels()
  362. {
  363. Ipp32s kernel[3] = {-1, 0, 1};
  364. IppiSize r = _roi;
  365. r.width-=3;
  366. r.height-=3;
  367. ippiFilterRow_8u_C1R((Ipp8u*)_data[0], _dataStep, (Ipp8u*)_data[_depth-2], _dataStep, r, kernel, 3, 2, -1);
  368. ippiFilterColumn_8u_C1R((Ipp8u*)_data[0], _dataStep, (Ipp8u*)_data[_depth-1], _dataStep, r, kernel, 3, 2, -1);
  369. }
  370. template<> void Matrixu::SaveImages(std::vector<Matrixu> imgs, const char *dirname, float resize)
  371. {
  372. char fname[1024];
  373. for( uint k=0; k<imgs.size(); k++ ){
  374. sprintf_s(fname,"%s/img%05d.png",dirname,k);
  375. if( resize == 1.0f )
  376. imgs[k].SaveImage(fname);
  377. else{
  378. imgs[k].imResize(resize).SaveImage(fname);
  379. }
  380. }
  381. }
  382. template<> Matrixu Matrixu::imResize(float r, float c)
  383. {
  384. float pr, pc; int nr, nc;
  385. if( c<0 ){
  386. pr = r; pc = r;
  387. nr = (int)(r*_rows);
  388. nc = (int)(r*_cols);
  389. }else{
  390. pr = r/_rows; pc = c/_cols;
  391. nr = (int)r;
  392. nc = (int)c;
  393. }
  394. Matrixu res((int)(nr), (int)(nc), _depth);
  395. IppStatus ippst;
  396. for( int k=0; k<_depth; k++ )
  397. ippst = ippiResize_8u_C1R((Ipp8u*)_data[k],_roi, _dataStep, _roirect, (Ipp8u*)res._data[k], res._dataStep, res._roi, pc, pr, IPPI_INTER_LINEAR);
  398. return res;
  399. }
  400. template<> void Matrixu::conv2RGB(Matrixu &res)
  401. {
  402. res.Resize(_rows,_cols,3);
  403. for( int k=0; k<_rows*_dataStep; k++ )
  404. {
  405. ((Ipp8u*)res._data[0])[k] = ((Ipp8u*)_data[0])[k];
  406. ((Ipp8u*)res._data[1])[k] = ((Ipp8u*)_data[0])[k];
  407. ((Ipp8u*)res._data[2])[k] = ((Ipp8u*)_data[0])[k];
  408. }
  409. }
  410. template<> void Matrixu::conv2BW(Matrixu &res)
  411. {
  412. res.Resize(_rows,_cols,1);
  413. double t;
  414. for( int k=0; k<(int)size(); k++ )
  415. {
  416. t = (double) ((Ipp8u*)_data[0])[k];
  417. t+= (double) ((Ipp8u*)_data[1])[k];
  418. t+= (double) ((Ipp8u*)_data[2])[k];
  419. ((Ipp8u*)res._data[0])[k] = (Ipp8u) (t/3.0);
  420. }
  421. if( res._keepIpl ) res.freeIpl();
  422. }
  423. template<> float Matrixf::Dot(const Matrixf &x)
  424. {
  425. assert( this->size() == x.size() );
  426. float sum = 0.0f;
  427. #pragma omp parallel for reduction(+: sum)
  428. for( int i=0; i<(int)size(); i++ )
  429. sum += (*this)(i)*x(i);
  430. return sum;
  431. }