PageRenderTime 73ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/src/CaptureManager.cpp

https://github.com/p1r4nh4/CellTrack
C++ | 1239 lines | 1100 code | 89 blank | 50 comment | 261 complexity | 683283fe060a5eb74ec4bf76625ff4dc MD5 | raw file
  1. #include "CaptureManager.h"
  2. #include "Preferences.h"
  3. #include "Util.h"
  4. #include <iostream>
  5. #include <fstream>
  6. #include <set>
  7. CaptureManager::CaptureManager(void)
  8. : book(NULL), canvas(NULL), RedrawListener(NULL), BookChangeListener(NULL), ReloadListener(NULL)
  9. { Reset(); }
  10. CaptureManager::~CaptureManager(void){
  11. Reset();
  12. }
  13. void CaptureManager::Reset(){
  14. int i;
  15. if (book) {
  16. for (i=0; i<totalFrameCount; i++){
  17. delete book[i];
  18. }
  19. delete[] book;
  20. }
  21. frameCount = 0;
  22. slideCount = 1;
  23. hasFluorescence = false;
  24. viewFluorescence = false;
  25. totalFrameCount = 0;
  26. offset = 1;
  27. fps = 0;
  28. pos = 0;
  29. zPos = 0;
  30. deltaZ = 0.0;
  31. calibration = 0.0;
  32. loadedImgs = 0;
  33. size = cvSize(0, 0);
  34. img.ReleaseAll();
  35. loadRadius = 4;
  36. drawBorder = true;
  37. drawPoints = true;
  38. drawOtherBorder = false;
  39. drawOtherPoints = false;
  40. drawTopBorder = false;
  41. drawTopPoints = false;
  42. drawBottomBorder = false;
  43. drawBottomPoints = false;
  44. }
  45. void CaptureManager::SetCanvas(MyCanvas *canvas_)
  46. {
  47. canvas = canvas_;
  48. }
  49. MyCanvas* CaptureManager::GetCanvas()
  50. {
  51. return canvas;
  52. }
  53. bool CaptureManager::OpenMovie(const char* avi)
  54. {
  55. Reset();
  56. MyCapture_Movie capture(avi);
  57. return OpenMovie_initialize(capture);
  58. }
  59. bool CaptureManager::OpenMovie( const wxArrayString& files )
  60. {
  61. Reset();
  62. MyCapture_Files capture(files);
  63. return OpenMovie_initialize(capture);
  64. }
  65. bool CaptureManager::OpenConfocal(const wxArrayString &files, int zSlides, bool fluorescence, double delta, double calib)
  66. {
  67. Reset();
  68. deltaZ = delta;
  69. calibration = calib;
  70. m_capture = new MyCapture_Confocal(files, zSlides, fluorescence);
  71. return OpenConfocal_initialize();
  72. }
  73. void CaptureManager::SetQueue(ImageJobQueue* queue)
  74. {
  75. m_queue = queue;
  76. }
  77. #include <wx/progdlg.h>
  78. bool CaptureManager::OpenMovie_initialize(MyCapture &capture)
  79. {
  80. if (!capture.IsOK())
  81. return false;
  82. frameCount = capture.frameCount;
  83. totalFrameCount = frameCount;
  84. slideCount = 1;
  85. fps = capture.fps ? capture.fps : Preferences::GetSavingFpsDefault();
  86. book = new ImagePlus*[frameCount];
  87. wxProgressDialog progressDlg(_T("Loading movie..."), wxString::Format(_T("Frame 0 of %d"), frameCount),frameCount, NULL, wxPD_APP_MODAL|wxPD_ELAPSED_TIME|wxPD_REMAINING_TIME|wxPD_AUTO_HIDE);
  88. for (int i=0; i<totalFrameCount; i++){
  89. progressDlg.Update(i+1, wxString::Format(_T("Frame %d of %d"), i+1, totalFrameCount));
  90. IplImage *newframe = capture.queryFrame(i);
  91. IplImage *resized;
  92. if (i == 0){
  93. size = cvSize(newframe->width, newframe->height);
  94. book[i] = new ImagePlus(newframe);
  95. }
  96. else if(!cvSizeEquals(newframe, size)){
  97. resized = cvCloneImage(book[0]->orig);
  98. cvResize(newframe, resized);
  99. book[i] = new ImagePlus(resized);
  100. cvReleaseImage(&resized);
  101. }
  102. else
  103. book[i] = new ImagePlus(newframe);
  104. }
  105. if (BookChangeListener)
  106. BookChangeListener->OnBookChange();
  107. SetPos(0);
  108. return true;
  109. }
  110. bool CaptureManager::OpenConfocal_initialize()
  111. {
  112. if (!m_capture->IsOK())
  113. return false;
  114. slideCount = m_capture->getSlideNumber();
  115. hasFluorescence = m_capture->getFluorescence();
  116. frameCount = m_capture->frameCount/(hasFluorescence?2:1)/slideCount;
  117. totalFrameCount = frameCount*(hasFluorescence?2:1)*slideCount;
  118. offset = (hasFluorescence?2:1)*slideCount;
  119. fps = Preferences::GetSavingFpsDefault();
  120. book = new ImagePlus*[totalFrameCount];
  121. IplImage* testImg = NULL;
  122. if (testImg = cvLoadImage((m_capture->getFilename(0)).mb_str()))
  123. {
  124. size = cvSize(testImg->width, testImg->height);
  125. cvReleaseImage(&testImg);
  126. testImg = NULL;
  127. }
  128. /*wxProgressDialog progressDlg(_T("Loading movie..."), wxString::Format(_T("Frame 0 of %d"), totalFrameCount),totalFrameCount, NULL, wxPD_APP_MODAL|wxPD_ELAPSED_TIME|wxPD_REMAINING_TIME|wxPD_AUTO_HIDE);
  129. for (int i=0; i<totalFrameCount; i++){
  130. if (i == 31)
  131. std::cout << "loading frame .. " << i << std::endl;
  132. progressDlg.Update(i+1, wxString::Format(_T("Frame %d of %d"), i+1, totalFrameCount));
  133. IplImage *newframe = capture.queryFrame(i);
  134. IplImage *resized;
  135. if (i == 0){
  136. size = cvSize(newframe->width, newframe->height);
  137. book[1] = new ImagePlus(newframe);
  138. }
  139. else if(!cvSizeEquals(newframe, size)){
  140. resized = cvCloneImage(book[1]->orig);
  141. cvResize(newframe, resized);
  142. book[i+(i%2 == 1 ? 1 : -1)] = new ImagePlus(resized);
  143. cvReleaseImage(&resized);
  144. }
  145. else
  146. book[i+(i%2 == 1 ? 1 : -1)] = new ImagePlus(newframe);
  147. }*/
  148. for (int i=0; i<totalFrameCount; i++)
  149. {
  150. book[i] = new ImagePlus(i%2==0?hasFluorescence:false);
  151. }
  152. if (BookChangeListener)
  153. BookChangeListener->OnBookChange();
  154. return true;
  155. }
  156. bool CaptureManager::SaveMovie(const char* avi)
  157. {
  158. bool resize = false;
  159. CvSize newsize = size;
  160. if ( Preferences::GetSavingSizeOverride() && !cvSizeEquals(Preferences::GetSavingSize(), size) ){
  161. resize = true;
  162. newsize = Preferences::GetSavingSize();
  163. }
  164. CvVideoWriter* writer = cvCreateVideoWriter(avi,
  165. Preferences::GetSavingCodec(),
  166. Preferences::GetSavingFpsOverride() || !fps ? Preferences::GetSavingFpsDefault() : fps,
  167. newsize, 1);
  168. IplImage *resized;
  169. if (resize)
  170. resized = cvCreateImage(newsize,8,3);
  171. IplImage *frame_flip = cvCreateImage(newsize,8,3);
  172. wxProgressDialog progressDlg(_T("Saving movie..."), wxString::Format(_T("Frame 0 of %d"), frameCount),frameCount, NULL, wxPD_APP_MODAL|wxPD_ELAPSED_TIME|wxPD_REMAINING_TIME|wxPD_AUTO_HIDE);
  173. for (int i=0; i<frameCount; i++) {
  174. progressDlg.Update(i+1, wxString::Format(_T("Frame %d of %d"), i+1, frameCount));
  175. if (resize)
  176. cvResize(book[i*offset]->ToIplImage(), resized);
  177. else
  178. resized = book[i*offset]->ToIplImage();
  179. cvConvertImage( resized, frame_flip, CV_CVTIMG_SWAP_RB );
  180. cvWriteFrame(writer, frame_flip);
  181. }
  182. cvReleaseVideoWriter(&writer);
  183. cvReleaseImage(&frame_flip);
  184. frame_flip = NULL;
  185. if (resize)
  186. cvReleaseImage(&resized);
  187. return true;
  188. }
  189. //TODO: Check who uses this and how to change accordingly
  190. int CaptureManager::GetFrameCount()
  191. {
  192. return frameCount;
  193. }
  194. CvSize CaptureManager::GetSize()
  195. {
  196. return size;
  197. }
  198. int CaptureManager::GetPos()
  199. {
  200. return pos;
  201. }
  202. int CaptureManager::GetZPos()
  203. {
  204. return zPos;
  205. }
  206. int CaptureManager::GetTotalPos()
  207. {
  208. return CalculateDirect(pos, zPos, viewFluorescence);
  209. }
  210. int CaptureManager::CalculateDirect(int p, int z, bool fluorescence)
  211. {
  212. return p*offset+z*(hasFluorescence?2:1) + ((hasFluorescence&&fluorescence)?0:1);
  213. }
  214. void CaptureManager::Release(int p, int z, bool fluorescence)
  215. {
  216. // unload previous loaded image
  217. if (!IsInNeighborhood(p, z))
  218. {
  219. int direct = CalculateDirect(p, z, fluorescence);
  220. if (book[direct]->isLoading)
  221. book[direct]->isLoading = false;
  222. else
  223. m_queue->AddJob(Job(Job::thread_delete, direct, book[direct]->orig), 1);
  224. book[direct]->orig = NULL;
  225. }
  226. }
  227. void CaptureManager::Preload(int direct)
  228. {
  229. if (!book[direct]->orig && !book[direct]->isLoading)
  230. {
  231. m_queue->AddJob(Job(Job::thread_load, direct, m_capture->getFilename(direct)), 1);
  232. book[direct]->isLoading = true;
  233. }
  234. }
  235. ImagePlus* CaptureManager::Access(int p, int z, bool fluorescence, bool noImage, int preload)
  236. {
  237. if (p < 0 || p >= frameCount || z < 0 || z >= slideCount)
  238. return NULL;
  239. // preload next three pictures
  240. if (preload)
  241. {
  242. for (int i = 1; i <= 3; i++)
  243. {
  244. int newpos = i + p;
  245. int newZPos = z + newpos/frameCount;
  246. if (preload == 1) // all
  247. {
  248. if (newZPos <= slideCount)
  249. {
  250. if (newpos >= frameCount)
  251. newpos = newpos % frameCount;
  252. Preload(CalculateDirect(newpos, newZPos, fluorescence));
  253. }
  254. }
  255. else if (preload == 2) // t-direction
  256. {
  257. if (newpos < frameCount)
  258. Preload(CalculateDirect(newpos, z, fluorescence));
  259. }
  260. else // z-direction
  261. {
  262. newZPos = z + i;
  263. if (newZPos < slideCount)
  264. Preload(CalculateDirect(p, newZPos, fluorescence));
  265. }
  266. }
  267. }
  268. int direct = CalculateDirect(p, z, fluorescence);
  269. ImagePlus* temp = book[direct];
  270. if (!temp->orig && !noImage)
  271. temp->orig = cvLoadImage(m_capture->getFilename(direct).mb_str());
  272. return temp;
  273. }
  274. ImagePlus* CaptureManager::DirectAccess(int x)
  275. {
  276. return book[x];
  277. }
  278. void CaptureManager::ReloadCurrentFrame(bool redraw, bool callPlugin)
  279. {
  280. if (callPlugin && ReloadListener)
  281. ReloadListener->OnReload();
  282. img = *book[GetTotalPos()];
  283. if (redraw && img.orig)
  284. Redraw(callPlugin);
  285. }
  286. bool CaptureManager::IsInNeighborhood(int testPos, int testZPos) const
  287. {
  288. return (testPos >= 0 && testPos < frameCount && testZPos >= 0 && testZPos < slideCount && abs(testPos - pos) + abs(testZPos - zPos) <= loadRadius);
  289. }
  290. void CaptureManager::LoadNeighborhood(int newpos, int newZPos)
  291. {
  292. //std::cout << "Queue Size: " << m_queue->GetLength() << std::endl;
  293. //std::cout << "Loading: " << newpos << " " << newZPos << std::endl;
  294. std::set<std::pair<int,int> > toLoad;
  295. std::set<int> toUnload;
  296. for (int i = pos - loadRadius; i<loadRadius+pos+1; i++)
  297. {
  298. for (int j = zPos - (loadRadius - abs(i - pos)); j < zPos + (loadRadius - abs(i - pos)) + 1; j++)
  299. {
  300. if (i >= 0 && i < frameCount && j >= 0 && j < slideCount)
  301. {
  302. toUnload.insert(i*offset + j*(hasFluorescence?2:1));
  303. }
  304. }
  305. }
  306. for (int i = newpos - loadRadius; i<loadRadius+newpos+1; i++)
  307. {
  308. for (int j = newZPos - (loadRadius - abs(i - newpos)); j < newZPos + (loadRadius - abs(i - newpos)) + 1; j++)
  309. {
  310. if (i >= 0 && i < frameCount && j >= 0 && j < slideCount)
  311. {
  312. std::set<int>::iterator it = toUnload.find(i*offset + j*(hasFluorescence?2:1));
  313. if (it != toUnload.end())
  314. toUnload.erase(it);
  315. // No else because of initial state when nothing is loaded yet.
  316. // Later I will catch the case of an already loaded image anyway.
  317. toLoad.insert(std::pair<int,int>(i*offset + j*(hasFluorescence?2:1), 2 + abs(newpos - i) + abs(newZPos - j)));
  318. }
  319. }
  320. }
  321. for (std::set<int>::iterator it = toUnload.begin(); it != toUnload.end(); it++)
  322. {
  323. if (book[*it]->isLoading)
  324. book[*it]->isLoading = false;
  325. else
  326. m_queue->AddJob(Job(Job::thread_delete, *it, book[*it]->orig), 2);
  327. book[*it]->orig = NULL;
  328. if (book[*it + 1]->isLoading)
  329. book[*it + 1]->isLoading = false;
  330. else
  331. m_queue->AddJob(Job(Job::thread_delete, *it + 1, book[*it + 1]->orig), 2 + (viewFluorescence?1:-1));
  332. book[*it + 1]->orig = NULL;
  333. }
  334. for (std::set<std::pair<int,int> >::iterator it = toLoad.begin(); it != toLoad.end(); it++)
  335. {
  336. if (!book[it->first]->orig && !book[it->first]->isLoading)
  337. {
  338. m_queue->AddJob(Job(Job::thread_load, it->first, m_capture->getFilename(it->first)), it->second);
  339. book[it->first]->isLoading = true;
  340. }
  341. if (!book[it->first + 1]->orig && !book[it->first + 1]->isLoading)
  342. {
  343. m_queue->AddJob(Job(Job::thread_load, it->first + 1, m_capture->getFilename(it->first + 1)), it->second);
  344. book[it->first + 1]->isLoading = true;
  345. }
  346. }
  347. loadedImgs + (toLoad.size() - toUnload.size());
  348. }
  349. void CaptureManager::ReloadCurrentFrameContours(bool redraw, bool callPlugin)
  350. {
  351. if (callPlugin && ReloadListener)
  352. ReloadListener->OnReload();
  353. img.CloneContours(book[GetTotalPos()]);
  354. if (redraw)
  355. Redraw(callPlugin);
  356. }
  357. void CaptureManager::PushbackCurrentFrame()
  358. {
  359. *(book[GetTotalPos()]) = img;
  360. }
  361. bool CaptureManager::SetPos(int newpos, bool reload)
  362. {
  363. if (newpos<0 || newpos>=frameCount || (newpos==pos && img.orig && !reload))
  364. return false;
  365. LoadNeighborhood(newpos, zPos);
  366. pos = newpos;
  367. ReloadCurrentFrame();
  368. return true;
  369. }
  370. bool CaptureManager::SetZPos(int newpos, bool reload)
  371. {
  372. if (newpos<0 || newpos>=slideCount || (newpos==zPos && img.orig && !reload))
  373. return false;
  374. LoadNeighborhood(pos, newpos);
  375. zPos = newpos;
  376. ReloadCurrentFrame();
  377. return true;
  378. }
  379. bool CaptureManager::SetPos(int newpos, int newZPos, bool reload)
  380. {
  381. if (newpos<0 || newpos>=frameCount || newZPos<0 || newZPos>=slideCount
  382. || (newZPos==zPos && newpos==pos && img.orig && !reload))
  383. return false;
  384. LoadNeighborhood(newpos, newZPos);
  385. pos = newpos;
  386. zPos = newZPos;
  387. ReloadCurrentFrame();
  388. return true;
  389. }
  390. bool CaptureManager::OnDeleteBefore()
  391. {
  392. if (!pos)
  393. return false;
  394. for (int i=0; i<pos*offset; i++)
  395. delete book[i];
  396. for (int i=0; i<totalFrameCount-pos*offset; i++)
  397. book[i] = book[i+pos*offset];
  398. frameCount-=pos;
  399. totalFrameCount-=pos*offset;
  400. SetPos(0,true);
  401. if (BookChangeListener)
  402. BookChangeListener->OnBookChange();
  403. return true;
  404. }
  405. bool CaptureManager::OnDeleteAfter()
  406. {
  407. for (int i=(pos+1)*offset; i<totalFrameCount; i++)
  408. delete book[i];
  409. frameCount=pos+1;
  410. totalFrameCount=(pos+1)*offset;
  411. if (BookChangeListener)
  412. BookChangeListener->OnBookChange();
  413. return true;
  414. }
  415. bool CaptureManager::OnDelete()
  416. {
  417. if (!frameCount)
  418. return false;
  419. if (frameCount == 1)
  420. {
  421. wxLogError(_T("Cannot delete the last and only frame."));
  422. return false;
  423. }
  424. ImagePlus* todelete[offset];
  425. for (int i = pos*offset; i<(pos+1)*offset; i++)
  426. {
  427. todelete[i/pos] = book[i];
  428. }
  429. int i;
  430. for (i=pos*offset; i<totalFrameCount-offset; i++)
  431. book[i]=book[i+1];
  432. for (;i<totalFrameCount;i++)
  433. book[i] = NULL;
  434. frameCount--;
  435. totalFrameCount-=offset;
  436. if (BookChangeListener)
  437. BookChangeListener->OnBookChange();
  438. SetPos(pos==frameCount ? frameCount-1 : pos, true);
  439. for (int j = 0; j<offset; i++)
  440. delete todelete[i];
  441. return true;
  442. }
  443. bool CaptureManager::OnPrev()
  444. {
  445. return SetPos(pos-1);
  446. }
  447. bool CaptureManager::OnNext()
  448. {
  449. return SetPos(pos+1);
  450. }
  451. bool CaptureManager::ShowFluorescence(bool show)
  452. {
  453. viewFluorescence = show;
  454. ReloadCurrentFrame();
  455. }
  456. void CaptureManager::Redraw(bool callPlugin)
  457. {
  458. if (!canvas)
  459. return;
  460. // canvas->SetImage(img.ToWxImage());
  461. if (callPlugin && RedrawListener)
  462. RedrawListener->OnRedraw();
  463. canvas->SetImage(img);
  464. }
  465. void CaptureManager::SetRedrawListener( PluginBase* RedrawListener_ )
  466. {
  467. if (RedrawListener && RedrawListener_)
  468. wxLogError(_T("canvas already had a redraw listener."));
  469. RedrawListener = RedrawListener_;
  470. }
  471. void CaptureManager::SetReloadListener( PluginBase* ReloadListener_ )
  472. {
  473. if (ReloadListener && ReloadListener_)
  474. wxLogError(_T("canvas already had a Reload listener."));
  475. ReloadListener = ReloadListener_;
  476. }
  477. void CaptureManager::SetBookChangeListener( PluginBase* BookChangeListener_ )
  478. {
  479. if (BookChangeListener && BookChangeListener_)
  480. wxLogError(_T("canvas already had a BookChange listener."));
  481. BookChangeListener = BookChangeListener_;
  482. }
  483. #include "MyPoint.h"
  484. std::vector<double> CaptureManager::GetSpeeds(int c, float &totalDisp, float &avgSpeed)
  485. {
  486. std::vector<CvPoint> traj = GetTrajectory(c);
  487. std::vector<double> s(frameCount-1, 0.0);
  488. totalDisp = 0;
  489. int goodSteps = 0;
  490. for (int i=0; i<frameCount-1; i++)
  491. {
  492. if (!(MyPoint(-1,-1)==traj[i] || MyPoint(-1,-1)==traj[i+1]))
  493. {
  494. goodSteps++;
  495. totalDisp += (s[i] = MyPoint(traj[i]).Euclidean(MyPoint(traj[i+1])));
  496. }
  497. }
  498. avgSpeed = (goodSteps ? totalDisp/goodSteps : 0);
  499. return s;
  500. }
  501. std::vector<double> CaptureManager::GetAreas(int c, float &avgArea)
  502. {
  503. std::vector<double> a(frameCount, 0.0);
  504. int goodSteps = 0;
  505. float totalArea = 0.0;
  506. for (int i=0; i<frameCount; i++)
  507. {
  508. if (book[i*offset]->contourArray.size() > c)
  509. {
  510. goodSteps++;
  511. totalArea += (a[i]=fabs(cvContourArea(book[i*offset]->contourArray[c])));
  512. }
  513. }
  514. avgArea = (goodSteps ? totalArea/goodSteps : 0);
  515. return a;
  516. }
  517. std::vector<double> CaptureManager::GetAreaDiff(int c, float &avgDiff)
  518. {
  519. std::vector<double> a = GetAreas(c,avgDiff);
  520. std::vector<double> diff(frameCount-1, 0.0);
  521. float totalDiff = 0;
  522. int goodSteps = 0;
  523. for (int i=0; i<frameCount-1; i++)
  524. {
  525. if (book[i*offset]->contourArray.size() > c)
  526. {
  527. goodSteps++;
  528. totalDiff += (diff[i] = a[i+1]-a[i]);
  529. }
  530. }
  531. avgDiff = (goodSteps ? totalDiff/goodSteps : 0);
  532. return diff;
  533. }
  534. std::vector<double> CaptureManager::GetVolumes(int c, float &avgVolume)
  535. {
  536. std::vector<double> v(frameCount, 0.0);
  537. int goodSteps = 0;
  538. float totalVolume = 0.0;
  539. for (int i=0; i<frameCount; i++)
  540. {
  541. float frameVolume = 0.0;
  542. for (int j=0; j<slideCount-1; j++)
  543. {
  544. if (Access(i,j, false, true)->contourArray.size() > c && Access(i,j+1, false, true)->contourArray.size() > c)
  545. {
  546. float area1 = calibration*calibration*fabs(cvContourArea(Access(i,j, false, true)->contourArray[c]));
  547. float area2 = calibration*calibration*fabs(cvContourArea(Access(i,j+1, false, true)->contourArray[c]));
  548. frameVolume += deltaZ*(area1 + area2)/2.0f;
  549. }
  550. }
  551. goodSteps++;
  552. totalVolume += (v[i] = frameVolume);
  553. }
  554. avgVolume = (goodSteps ? totalVolume/goodSteps : 0);
  555. return v;
  556. }
  557. std::vector<double> CaptureManager::GetVolumeDiff(int c, float &avgDiff)
  558. {
  559. std::vector<double> v = GetVolumes(c, avgDiff);
  560. std::vector<double> diff(frameCount-1, 0.0);
  561. double totalDiff = 0;
  562. int goodSteps = 0;
  563. for (int i=0; i<frameCount-1; i++)
  564. {
  565. if (Access(i,0, false, true)->contourArray.size() > c)
  566. {
  567. goodSteps++;
  568. totalDiff += (diff[i] = v[i+1]-v[i]);
  569. }
  570. }
  571. avgDiff = (goodSteps ? totalDiff/goodSteps : 0);
  572. return diff;
  573. }
  574. #include "FindContoursPlugin.h"
  575. std::vector<double> CaptureManager::GetDeformation(int c, float &avgDef)
  576. {
  577. std::vector<CvPoint> traj = GetTrajectory(c);
  578. std::vector<double> areas = GetAreas(c,avgDef);
  579. std::vector<double> defs(frameCount-1, 0.0);
  580. float totalDef = 0;
  581. int goodSteps = 0;
  582. CvSeq *h_next;
  583. ImagePlus *img_ = new ImagePlus(img);
  584. IplImage *gray = cvCreateImage(cvGetSize(img.orig), IPL_DEPTH_8U, 1);
  585. IplImage *edge = cvCreateImage(cvGetSize(img.orig), IPL_DEPTH_8U, 1);
  586. for (int i=0; i<frameCount-1; i++)
  587. {
  588. if (!(MyPoint(-1,-1)==traj[i] || MyPoint(-1,-1)==traj[i+1]))
  589. {
  590. wxPoint *ps = ContourToPointArray(Access(i,0,false, true)->contourArray[c], MyPoint(traj[i+1])-MyPoint(traj[i]).ToWxPoint());
  591. img_->RemoveAllContours();
  592. img_->AddContour(ps,Access(i,0,false, true)->contourArray[c]->total);
  593. delete[] ps;
  594. CvSeq *seq = Access(i+1,0,false, true)->contourArray[c];
  595. CvSeq *oseq = img_->contourArray[0];
  596. //Draw both contours on the temporary image
  597. cvZero(img_->orig);
  598. h_next = seq->h_next; seq->h_next = NULL;
  599. cvDrawContours(img_->orig, seq, CV_RGB(255,255,255), CV_RGB(0,0,0), 1, CV_FILLED, CV_AA, cvPoint(0,0));
  600. seq->h_next = h_next;
  601. cvDrawContours(img_->orig, oseq, CV_RGB(255,255,200), CV_RGB(0,0,0), 1, CV_FILLED, CV_AA, cvPoint(0,0));
  602. //detect contours on the drawn image:
  603. FindContoursPlugin::ProcessImage_static(img_,gray,edge,150,50,3,1);
  604. float unionArea = 0;
  605. for (int j=0; j<img_->contourArray.size(); j++)
  606. {
  607. unionArea += fabs(cvContourArea(img_->contourArray[j]));
  608. }
  609. goodSteps++;
  610. totalDef += (defs[i] = 2*unionArea - areas[i] - areas[i+1]);
  611. }
  612. }
  613. cvReleaseImage(&gray);
  614. cvReleaseImage(&edge);
  615. delete img_;
  616. avgDef = (goodSteps ? totalDef/goodSteps : 0);
  617. return defs;
  618. }
  619. std::vector<CvPoint> CaptureManager::GetTrajectory(int c)
  620. {
  621. std::vector<CvPoint> traj(frameCount);
  622. for (int i=0; i<frameCount; i++)
  623. {
  624. if (Access(i,0,false, true)->contourArray.size() <= c)
  625. traj[i]=cvPoint(-1,-1);
  626. else
  627. {
  628. CvMoments m;
  629. double m00,m10,m01;
  630. cvMoments(Access(i,0,false, true)->contourArray[c], &m);
  631. m00 = cvGetSpatialMoment(&m,0,0);
  632. m01 = cvGetSpatialMoment(&m,0,1);
  633. m10 = cvGetSpatialMoment(&m,1,0);
  634. traj[i] = cvPoint(cvRound(m.m10/m.m00), cvRound(m.m01/m.m00));
  635. }
  636. }
  637. return traj;
  638. }
  639. #include <stdio.h>
  640. bool CaptureManager::SaveData_setup(const char* file, FILE* &fp)
  641. {
  642. if (!book[0]->contourArray.size())
  643. {
  644. wxLogError(_T("No objects in the first frame. Detect/draw boundaries in the first frame and apply tracking first."));
  645. return false;
  646. }
  647. if (!(fp = fopen(file,"w")))
  648. {
  649. wxLogError(_T("Unable to open file %s"), file);
  650. return false;
  651. }
  652. return true;
  653. }
  654. bool CaptureManager::SaveTrackData(const char* file)
  655. {
  656. FILE *fp;
  657. if(!SaveData_setup(file,fp)) return false;
  658. int numContours=book[0]->contourArray.size();
  659. fprintf(fp, "#width: %d, height: %d, frameCount: %d, fps: %d\n", size.width, size.height, frameCount, numContours, fps);
  660. fprintf(fp, "#cellCount: %d\n", numContours);
  661. for (int c=0; c<numContours; c++)
  662. {
  663. CvSeq *oseq = book[0]->contourArray[c];
  664. int np = oseq->total;
  665. fprintf(fp, "#Cell: %d, pointCount: %d\n", c+1, np);
  666. for (int j=0; j<frameCount; j++)
  667. {
  668. for (int i=0; i<np; i++)
  669. {
  670. if(book[j*offset]->contourArray.size() <= c || book[j*offset]->contourArray[c]->total <= i)
  671. fprintf(fp,"-1 -1 ");
  672. else
  673. {
  674. CvPoint *p = (CvPoint*) cvGetSeqElem(book[j*offset]->contourArray[c], i);
  675. fprintf(fp, "%d\t%d\t", p->x, p->y);
  676. }
  677. }
  678. fprintf(fp,"\n");
  679. }
  680. }
  681. fclose(fp);
  682. return true;
  683. }
  684. bool CaptureManager::ImportTrackData(const char* file)
  685. {
  686. FILE *fp = fopen(file,"r");
  687. if (!fp)
  688. {
  689. wxLogError(_T("Unable to open file %s"), file);
  690. return false;
  691. }
  692. //check if there's already some detected cells.
  693. bool hasCells = false;
  694. for( int i=0; i<frameCount; i++ )
  695. {
  696. if (book[i*offset]->contourArray.size())
  697. {
  698. hasCells = true;
  699. break;
  700. }
  701. }
  702. if (hasCells)
  703. {
  704. int reply = wxMessageBox(_T("There are already detected cells. Do you want to remove existing cells before importing tracking data?"), _T("Remove existing cells?"), wxYES_NO | wxCANCEL, NULL);
  705. if (reply == wxCANCEL)
  706. return false;
  707. else if(reply == wxYES)
  708. {
  709. for( int i=0; i<frameCount; i++ )
  710. book[i*offset]->RemoveAllContours();
  711. }
  712. }
  713. //TODO: give notice if the movie info of the track-data does not match with current movie.
  714. int NumCells;
  715. int Width, Height, FrameCount, FSP;
  716. if( fscanf(fp, "#width: %d, height: %d, frameCount: %d, fps: %d\n#cellCount: %d\n", &Width, &Height, &FrameCount, &FSP, &NumCells) !=5 )
  717. {
  718. wxLogError(_T("Unable to parse file header %s"), file); return false;
  719. }
  720. for (int c=0; c<NumCells; c++)
  721. {
  722. int cellid,np;
  723. if( fscanf(fp, "#Cell: %d, pointCount: %d\n", &cellid, &np) !=2 )
  724. {
  725. wxLogError(_T("Unable to parse file %s for cell %d header %s"), file, c+1); return false;
  726. }
  727. for (int j=0; j<frameCount && j<FrameCount; j++)
  728. {
  729. std::vector<wxPoint> roi(np);
  730. for (int i=0; i<np; i++)
  731. {
  732. if( fscanf(fp, "%d %d", &roi[i].x, &roi[i].y) !=2 )
  733. {
  734. wxLogError(_T("Unable to parse file %s for cell %d coordinates"), file, c+1); return false;
  735. }
  736. }
  737. book[j*offset]->AddRoi(roi);
  738. }
  739. }
  740. fclose(fp);
  741. this->ReloadCurrentFrameContours();
  742. return true;
  743. }
  744. bool CaptureManager::SaveContours(const char* file)
  745. {
  746. std::ofstream outfile;
  747. outfile.open(file, std::ofstream::out);
  748. if (!outfile)
  749. {
  750. wxLogError(_T("Unable to open file %s"), file);
  751. return false;
  752. }
  753. //int numContours=book[0]->contourArray.size();
  754. outfile << "#width: " << size.width << ", height: " << size.height << ", frameCount: " << frameCount << ", slideCount: " << slideCount << ", fluorescence: " << (hasFluorescence?"yes":"no") << ", fps: " << fps << std::endl;
  755. for (int frame=0; frame < frameCount; frame++)
  756. {
  757. for (int slide=0; slide < slideCount; slide++)
  758. {
  759. for (int fluor=0; fluor < (hasFluorescence?2:1); fluor++)
  760. {
  761. int direct = CalculateDirect(frame, slide, (fluor==0?true:false));
  762. int numContours = book[direct]->contourArray.size();
  763. outfile << "#Frame: " << frame << ", Slide: " << slide << ", Fluorescence: " << (hasFluorescence&&fluor==0?"yes":"no") << ", Cell count: " << numContours << std::endl;
  764. for (int cell = 0; cell < numContours; cell++)
  765. {
  766. CvSeq *seq = book[direct]->contourArray[cell];
  767. int numPoints = seq->total;
  768. outfile << "#Cell: " << cell+1 << ", Point Count: " << numPoints << std::endl;
  769. for (int i=0; i<numPoints; i++)
  770. {
  771. CvPoint* point = (CvPoint*) cvGetSeqElem(seq, i);
  772. outfile << point->x << " " << point->y << " ";
  773. }
  774. outfile << std::endl;
  775. }
  776. }
  777. }
  778. }
  779. outfile.flush();
  780. outfile.close();
  781. return true;
  782. }
  783. bool CaptureManager::ImportContours(const char* file)
  784. {
  785. std::ifstream infile;
  786. //std::cout << "opening: " << file << std::endl;
  787. infile.open(file, std::ifstream::in);
  788. if (!infile)
  789. {
  790. wxLogError(_T("Unable to open file %s"), file);
  791. return false;
  792. }
  793. //check if there's already some detected cells.
  794. bool hasCells = false;
  795. for( int j=0; j<slideCount; j++)
  796. {
  797. for( int i=0; i<frameCount; i++ )
  798. {
  799. for( int k=0; k<2; k++ )
  800. {
  801. if (book[CalculateDirect(i,j,(k==0?false:true))]->contourArray.size())
  802. {
  803. hasCells = true;
  804. break;
  805. }
  806. }
  807. }
  808. }
  809. if (hasCells)
  810. {
  811. int reply = wxMessageBox(_T("There are already detected cells. Do you want to remove existing cells before importing tracking data?"), _T("Remove existing cells?"), wxYES_NO | wxCANCEL, NULL);
  812. if (reply == wxCANCEL)
  813. return false;
  814. else if(reply == wxYES)
  815. {
  816. for( int j=0; j<slideCount; j++)
  817. for( int i=0; i<frameCount; i++ )
  818. for( int k=0; k<2; k++ )
  819. book[CalculateDirect(i,j,(k==0?false:true))]->RemoveAllContours();
  820. }
  821. }
  822. //TODO: give notice if the movie info of the track-data does not match with current movie.
  823. int NumCells;
  824. int Width, Height, FrameCount, SlideCount, FPS;
  825. std::string ignStr, flString;
  826. infile >> ignStr >> Width >> ignStr >> ignStr >> Height >> ignStr >> ignStr >> FrameCount >> ignStr >> ignStr >> SlideCount >> ignStr >> ignStr >> flString >> ignStr >> FPS;
  827. //std::cout << Width << " " << Height << " " << FrameCount << " " << SlideCount << " " << flString << " " << FPS << std::endl;
  828. bool fluor = (flString.compare("yes,") == 0);
  829. if (Width != size.width || Height != size.height || FrameCount != frameCount || SlideCount != slideCount || fluor != hasFluorescence || FPS != fps)
  830. {
  831. int reply = wxMessageBox(_T("The contours to be loaded do not fit the current image series. Proceed?"), _T("Proceed?"), wxYES_NO | wxCANCEL, NULL);
  832. if (reply == wxCANCEL)
  833. return false;
  834. }
  835. int frame = -1, slide = -1, numContours = -1;
  836. bool noErrors = true;
  837. while (noErrors && !infile.eof())
  838. {
  839. flString.clear();
  840. infile >> ignStr >> frame >> ignStr >> ignStr >> slide >> ignStr >> ignStr >> flString >> ignStr >> ignStr >> numContours;
  841. //std::cout << frame << " " << slide << " " << flString << " " << numContours << " " << std::endl;
  842. if (frame >= 0 && frame < frameCount && slide >= 0 && slide < slideCount && noErrors)
  843. {
  844. for (int cell=0; cell<numContours && noErrors; cell++)
  845. {
  846. int cellid,numPoints;
  847. /*if(cell >= 1)
  848. {
  849. char* buffer = (char*) malloc (sizeof(char)*1);
  850. fread (buffer,1,1,fp);
  851. std::cout << cell << " -- " << buffer << std::endl;
  852. }*/
  853. infile >> ignStr >> cellid >> ignStr >> ignStr >> ignStr >> numPoints;
  854. std::vector<wxPoint> roi(numPoints);
  855. for (int i=0; i<numPoints && noErrors; i++)
  856. {
  857. infile >> roi[i].x >> roi[i].y;
  858. //std::cout << roi[i].x << " " << roi[i].y << std::endl;
  859. }
  860. if (noErrors)
  861. book[CalculateDirect(frame, slide, (flString.compare("yes,") == 0))]->AddRoi(roi);
  862. }
  863. }
  864. }
  865. infile.close();
  866. this->ReloadCurrentFrameContours();
  867. return true;
  868. }
  869. bool CaptureManager::SaveTrajectoryData(const char* file)
  870. {
  871. FILE *fp;
  872. if(!SaveData_setup(file,fp)) return false;
  873. int numContours=book[0]->contourArray.size();
  874. fprintf(fp, "#width: %d, height: %d, frameCount: %d, fps: %d\n", size.width, size.height, frameCount, numContours, fps);
  875. fprintf(fp, "#cellCount: %d\n", numContours);
  876. for (int c=0; c<numContours; c++)
  877. {
  878. CvSeq *oseq = book[0]->contourArray[c];
  879. int np = oseq->total;
  880. fprintf(fp, "#Cell: %d, pointCount: %d\n", c+1, np);
  881. std::vector<CvPoint> traj = GetTrajectory(c);
  882. for (int i=0; i<traj.size(); i++){
  883. fprintf(fp, "%d\t%d\n", traj[i].x, traj[i].y);
  884. }
  885. }
  886. fclose(fp);
  887. return true;
  888. }
  889. bool CaptureManager::SaveSpeedData(const char* file)
  890. {
  891. FILE *fp;
  892. if(!SaveData_setup(file,fp)) return false;
  893. int numContours=book[0]->contourArray.size();
  894. fprintf(fp, "#width: %d, height: %d, frameCount: %d, fps: %d\n", size.width, size.height, frameCount, numContours, fps);
  895. fprintf(fp, "#cellCount: %d\n", numContours);
  896. for (int c=0; c<numContours; c++)
  897. {
  898. CvSeq *oseq = book[0]->contourArray[c];
  899. int np = oseq->total;
  900. float totalDisp, avgSpeed;
  901. std::vector<double> speeds = GetSpeeds(c, totalDisp, avgSpeed);
  902. fprintf(fp, "#Cell: %d, pointCount: %d, totalDistance: %f, avgSped: %f\n", c+1, np, totalDisp, avgSpeed);
  903. for (int i=0; i<speeds.size(); i++)
  904. {
  905. fprintf(fp, "%f\n", speeds[i]);
  906. }
  907. }
  908. fclose(fp);
  909. return true;
  910. }
  911. bool CaptureManager::SaveAreaData(const char* file)
  912. {
  913. FILE *fp;
  914. if(!SaveData_setup(file,fp)) return false;
  915. int numContours=book[0]->contourArray.size();
  916. fprintf(fp, "#width: %d, height: %d, frameCount: %d, fps: %d\n", size.width, size.height, frameCount, numContours, fps);
  917. fprintf(fp, "#cellCount: %d\n", numContours);
  918. for (int c=0; c<numContours; c++)
  919. {
  920. CvSeq *oseq = book[0]->contourArray[c];
  921. int np = oseq->total;
  922. float avgArea;
  923. std::vector<double> areas = GetAreas(c, avgArea);
  924. fprintf(fp, "#Cell: %d, pointCount: %d, avgArea: %f\n", c+1, np, avgArea);
  925. for (int i=0; i<areas.size(); i++)
  926. {
  927. fprintf(fp, "%f\n", areas[i]);
  928. }
  929. }
  930. fclose(fp);
  931. return true;
  932. }
  933. bool CaptureManager::SaveVolumeData(const char* file)
  934. {
  935. std::ofstream outfile;
  936. outfile.open(file, std::ofstream::out);
  937. if (!outfile)
  938. {
  939. wxLogError(_T("Unable to open file %s"), file);
  940. return false;
  941. }
  942. int numContours = Access(0,0,false)->contourArray.size();
  943. outfile << "#width: " << size.width << ", height: " << size.height << ", frameCount: " << frameCount << ", fps: " << fps << std::endl;
  944. outfile << "#cellCount: " << numContours << std::endl;
  945. for (int c=0; c<numContours; c++)
  946. {
  947. CvSeq *oseq = Access(0,0,false)->contourArray[c];
  948. int np = oseq->total;
  949. float avgVolume;
  950. std::vector<double> volumes = GetVolumes(c, avgVolume);
  951. outfile << "#Cell: " << c+1 << ", pointCount: " << np << ", avgVolume: " << avgVolume << std::endl;
  952. for (int i=0; i<volumes.size(); i++)
  953. {
  954. outfile << volumes[i] << std::endl;;
  955. }
  956. }
  957. outfile.close();
  958. return true;
  959. }
  960. bool CaptureManager::SaveDeformationData(const char* file)
  961. {
  962. FILE *fp;
  963. if(!SaveData_setup(file,fp)) return false;
  964. int numContours=book[0]->contourArray.size();
  965. fprintf(fp, "#width: %d, height: %d, frameCount: %d, fps: %d\n", size.width, size.height, frameCount, numContours, fps);
  966. fprintf(fp, "#cellCount: %d\n", numContours);
  967. for (int c=0; c<numContours; c++)
  968. {
  969. CvSeq *oseq = book[0]->contourArray[c];
  970. int np = oseq->total;
  971. float avgDef;
  972. std::vector<double> defs = GetDeformation(c, avgDef);
  973. fprintf(fp, "#Cell: %d, pointCount: %d, avgDeformation: %f\n", c+1, np, avgDef);
  974. for (int i=0; i<defs.size(); i++)
  975. {
  976. fprintf(fp, "%f\n", defs[i]);
  977. }
  978. }
  979. fclose(fp);
  980. return true;
  981. }
  982. #include <wx/bitmap.h>
  983. #include <wx/dc.h>
  984. bool CaptureManager::SaveTrackImage(wxBitmap &bmp, int start, int end)
  985. {
  986. if (end == -1) end = frameCount;
  987. if (!Access(0,0,false, true)->contourArray.size())
  988. {
  989. wxLogError(_T("No objects in the first frame. Detect/draw boundaries in the first frame and apply tracking first."));
  990. return false;
  991. }
  992. wxRealPoint scale(6, 6);
  993. bmp.Create(scale.x*size.width, scale.y*size.height);
  994. wxMemoryDC dc(bmp);
  995. dc.SetBackground(*wxWHITE_BRUSH);
  996. dc.Clear();
  997. for (int c=0; c<Access(0, 0, false, true)->contourArray.size(); c++)
  998. {
  999. std::vector<CvPoint> traj = GetTrajectory(c);
  1000. std::vector< std::vector<double> > ratios;
  1001. CvPoint lastTraj = traj[start];
  1002. float maxRatio = 0;
  1003. float minRatio = 0;
  1004. for (int i=start+1; i<end && Access(i, 0, false, true)->contourArray.size() > c; i++)
  1005. {
  1006. CvSeq* oseq = Access(i-1, 0, false, true)->contourArray[c];
  1007. CvSeq* seq = Access(i, 0, false, true)->contourArray[c];
  1008. ratios.push_back(std::vector<double>());
  1009. for (int j=0; j<oseq->total; j++)
  1010. {
  1011. CvPoint *lastLoc = (CvPoint*) cvGetSeqElem(oseq, j);
  1012. if(seq->total <= j)
  1013. continue;
  1014. CvPoint *p = (CvPoint*) cvGetSeqElem(seq, j);
  1015. float ptx = p->x - lastLoc->x;
  1016. float pty = p->y - lastLoc->y;
  1017. float trajx = traj[i].x - lastTraj.x;
  1018. float trajy = traj[i].y - lastTraj.y;
  1019. float ratio = (ptx*trajx + pty*trajy)/(trajx*trajx + trajy*trajy);
  1020. if (maxRatio < ratio)
  1021. maxRatio = ratio;
  1022. if (minRatio > ratio)
  1023. minRatio = ratio;
  1024. ratios[i-1-start].push_back(ratio);
  1025. }
  1026. lastTraj = traj[i];
  1027. }
  1028. CvSeq* oseq = Access(start, 0, false, true)->contourArray[c];
  1029. MyCanvas::DrawContour_static(&dc, oseq, wxPoint(0,0), scale);
  1030. for (int i=0; i<oseq->total; i++)
  1031. {
  1032. CvPoint *lastLoc = (CvPoint*) cvGetSeqElem(oseq, i);
  1033. dc.SetPen(wxPen(wxColour(Preferences::GetColorContourPointColor())));
  1034. dc.SetBrush(*wxTRANSPARENT_BRUSH);
  1035. for (int j=start+1; j<end; j++)
  1036. {
  1037. if(Access(j,0,false, true)->contourArray.size() <= c || Access(j,0,false, true)->contourArray[c]->total <= i)
  1038. continue;
  1039. CvPoint *p = (CvPoint*) cvGetSeqElem(Access(j, 0, false, true)->contourArray[c], i);
  1040. dc.DrawLine(scale.x*lastLoc->x, scale.y*lastLoc->y, scale.x*p->x, scale.y*p->y);
  1041. lastLoc = p;
  1042. }
  1043. //dc.DrawCircle(MyPoint((CvPoint*)cvGetSeqElem(Access(start, 0, false, true)->contourArray[c],i))*scale, Preferences::GetColorContourBorderWidth());
  1044. for (int j=start+1; j<end; j++)
  1045. {
  1046. wxColor pointColor(*wxLIGHT_GREY);
  1047. if (ratios[j-1-start][i] > 0)
  1048. pointColor = wxColor(128 + 127*ratios[j-1-start][i]/maxRatio, 128 - 128*ratios[j-1-start][i]/maxRatio, 128 - 128*ratios[j-1-start][i]/maxRatio);
  1049. else
  1050. pointColor = wxColor(128 - 128*ratios[j-1-start][i]/minRatio, 128 - 128*ratios[j-1-start][i]/minRatio, 128 + 127*ratios[j-1-start][i]/minRatio);
  1051. dc.SetPen(wxPen(pointColor));
  1052. dc.SetBrush(pointColor);
  1053. if(Access(j, 0, false, true)->contourArray.size() <= c || Access(j, 0, false, true)->contourArray[c]->total <= i)
  1054. continue;
  1055. CvPoint *p = (CvPoint*) cvGetSeqElem(Access(j, 0, false, true)->contourArray[c], i);
  1056. dc.DrawCircle(MyPoint(*p)*scale, Preferences::GetColorContourBorderWidth()*2);
  1057. }
  1058. }
  1059. lastTraj = traj[start];
  1060. dc.SetBrush(*wxTRANSPARENT_BRUSH);
  1061. for (int i=start+1; i<end/*traj.size()*/; i++)
  1062. {
  1063. if(traj[i].x<0)
  1064. continue;
  1065. if (i>0)
  1066. {
  1067. dc.SetPen(wxPen(wxColour(Preferences::GetColorContourBorderColor()), Preferences::GetColorContourBorderWidth()));
  1068. dc.DrawLine(scale.x*lastTraj.x,scale.y*lastTraj.y, scale.x*traj[i].x,scale.y*traj[i].y);
  1069. }
  1070. lastTraj = traj[i];
  1071. }
  1072. if(c < Access(end-1,0,false, true)->contourArray.size())
  1073. MyCanvas::DrawContour_static(&dc, Access(end-1,0,false, true)->contourArray[c], wxPoint(0,0), scale, true, wxRED);
  1074. }
  1075. return true;
  1076. }
  1077. bool CaptureManager::SaveTrajectoryImage(wxBitmap &bmp)
  1078. {
  1079. if (!Access(0,0, false, true)->contourArray.size())
  1080. {
  1081. wxLogError(_T("No objects in the first frame. Detect/draw boundaries in the first frame and apply tracking first."));
  1082. return false;
  1083. }
  1084. wxRealPoint scale(6,6);
  1085. CvPoint lastLoc;
  1086. bmp.Create(scale.x*size.width,scale.y*size.height);
  1087. wxMemoryDC dc(bmp);
  1088. dc.SetBackground(*wxWHITE_BRUSH);
  1089. dc.Clear();
  1090. for (int c=0; c<Access(0,0,false, true)->contourArray.size(); c++)
  1091. {
  1092. std::vector<CvPoint> traj = GetTrajectory(c);
  1093. lastLoc = traj[0];
  1094. // draw first boundary
  1095. MyCanvas::DrawContour_static(&dc, Access(0,0, false, true)->contourArray[c],wxPoint(0,0),scale);
  1096. // drawing trajectory lines
  1097. dc.SetBrush(*wxTRANSPARENT_BRUSH);
  1098. for (int i=1; i<traj.size(); i++)
  1099. {
  1100. if(traj[i].x<0)
  1101. continue;
  1102. if (i>0)
  1103. {
  1104. dc.SetPen(wxPen(wxColour(Preferences::GetColorContourBorderColor()), Preferences::GetColorContourBorderWidth()));
  1105. dc.DrawLine(scale.x*lastLoc.x,scale.y*lastLoc.y, scale.x*traj[i].x,scale.y*traj[i].y);
  1106. }
  1107. lastLoc = traj[i];
  1108. }
  1109. // drawing trajectory points
  1110. dc.SetBrush(wxBrush(wxColour(Preferences::GetColorContourPointColor())));
  1111. dc.SetPen(wxPen(wxColour(Preferences::GetColorContourPointColor())));
  1112. for (int i=0; i<traj.size(); i++)
  1113. {
  1114. if(traj[i].x<0)
  1115. continue;
  1116. dc.DrawCircle(MyPoint(traj[i])*scale, 2*Preferences::GetColorContourBorderWidth());
  1117. }
  1118. // draw last boundary
  1119. dc.SetBrush(*wxRED_BRUSH);
  1120. dc.SetPen(wxPen(*wxRED));
  1121. if(traj[frameCount-1].x>=0)
  1122. {
  1123. dc.DrawCircle(MyPoint(traj[frameCount-1])*scale, 2*Preferences::GetColorContourBorderWidth());
  1124. MyCanvas::DrawContour_static(&dc, book[(frameCount-1)*offset]->contourArray[c],wxPoint(0,0),scale, true, wxRED);
  1125. }
  1126. }
  1127. return true;
  1128. }
  1129. void CaptureManager::Resize(int width, int height, int method)
  1130. {
  1131. if (MyPoint(width,height) == MyPoint(size))
  1132. return;
  1133. size = cvSize(width,height);
  1134. for (int i=0; i<totalFrameCount; i++)
  1135. {
  1136. book[i]->Resize(width, height, method);
  1137. }
  1138. ReloadCurrentFrame();
  1139. }
  1140. void CaptureManager::Crop(CvPoint topleft, CvSize size_)
  1141. {
  1142. if (size.width == 0)
  1143. return;
  1144. for (int i=0; i<totalFrameCount; i++)
  1145. {
  1146. book[i]->Crop(topleft, size_);
  1147. }
  1148. size = cvSize(size_.width, size_.height);
  1149. ReloadCurrentFrame();
  1150. }