OTSFieldMgr.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033
  1. #include "stdafx.h"
  2. #include "OTSFieldMgr.h"
  3. #include "OTSImageProcess.h"
  4. #include "otsdataconst.h"
  5. #include "BSEImgFileMgr.h"
  6. #include "SmplMsrResultFile.h"
  7. #include "PosXrayFileMgr.h"
  8. #include "IncAFileMgr.h"
  9. namespace OTSMODEL {
  10. using namespace OTSIMGPROC;
  11. COTSFieldMgr::COTSFieldMgr()
  12. : m_pFieldData(nullptr)
  13. {
  14. }
  15. COTSFieldMgr::~COTSFieldMgr()
  16. {
  17. }
  18. // init
  19. BOOL COTSFieldMgr::Init(COTSFieldDataPtr a_pFieldData, CBSEImgPtr a_pBSEImg)
  20. {
  21. ASSERT(a_pFieldData);
  22. if (!a_pFieldData)
  23. {
  24. // invalid field data.
  25. LogErrorTrace(__FILE__, __LINE__, _T("Init: invalid field data."));
  26. return FALSE;
  27. }
  28. ASSERT(a_pBSEImg);
  29. if (!a_pBSEImg)
  30. {
  31. // invalid BSE image.
  32. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEImage: invalid BSE image."));
  33. return FALSE;
  34. }
  35. // keep the original field data pointer
  36. m_pFieldData = a_pFieldData;
  37. // make a copy of the BSE image
  38. //m_pBSEImg = CBSEImgPtr(new CBSEImg(a_pBSEImg.get()));
  39. m_pBSEImg = a_pBSEImg;
  40. // create measure result
  41. m_pMsrResults = CMsrResultsPtr(new CMsrResults());
  42. // ok, return TRUE
  43. return TRUE;
  44. }
  45. // field data
  46. void COTSFieldMgr::SetOTSFieldData(COTSFieldDataPtr a_pOTSFieldData)
  47. {
  48. ASSERT(a_pOTSFieldData);
  49. if (!a_pOTSFieldData)
  50. {
  51. // invalid field data.
  52. LogErrorTrace(__FILE__, __LINE__, _T("SetOTSFieldData: invalid field data."));
  53. return;
  54. }
  55. m_pFieldData = a_pOTSFieldData;
  56. }
  57. // BSE image
  58. void COTSFieldMgr::SetBSEImage(CBSEImgPtr a_pBSEImg)
  59. {
  60. ASSERT(a_pBSEImg);
  61. if (!a_pBSEImg)
  62. {
  63. // invalid BSE image.
  64. LogErrorTrace(__FILE__, __LINE__, _T("SetBSEImage: invalid BSE image."));
  65. return;
  66. }
  67. m_pBSEImg = a_pBSEImg;
  68. }
  69. void COTSFieldMgr::SetSearchPosXayList(CPosXraysList& a_listPosXray, BOOL a_bClear)
  70. {
  71. if (a_bClear)
  72. {
  73. m_listSearchPosXray.clear();
  74. }
  75. for (auto pPosXray : a_listPosXray)
  76. {
  77. m_listSearchPosXray.push_back(pPosXray);
  78. }
  79. }
  80. void COTSFieldMgr::SetAnalysisPosXayList(CPosXraysList& a_listPosXray, BOOL a_bClear)
  81. {
  82. if (a_bClear)
  83. {
  84. m_listAnalysisPosXray.clear();
  85. }
  86. for (auto pPosXray : a_listPosXray)
  87. {
  88. m_listAnalysisPosXray.push_back(pPosXray);
  89. }
  90. }
  91. // remove BSE image BackGround
  92. BOOL COTSFieldMgr::RemoveBSEImageBG(COTSImageProcessParamPtr a_pImageProcessParam)
  93. {
  94. ASSERT(m_pFieldData);
  95. if (!m_pFieldData)
  96. {
  97. LogErrorTrace(__FILE__, __LINE__, _T("RemoveBSEImageBG: there is no field data"));
  98. return FALSE;
  99. }
  100. ASSERT(m_pBSEImg);
  101. if (!m_pBSEImg)
  102. {
  103. LogErrorTrace(__FILE__, __LINE__, _T("RemoveBSEImageBG: there is no image data"));
  104. return FALSE;
  105. }
  106. ASSERT(a_pImageProcessParam);
  107. if (!a_pImageProcessParam)
  108. {
  109. LogErrorTrace(__FILE__, __LINE__, _T("RemoveBSEImageBG: there is no image process data"));
  110. return FALSE;
  111. }
  112. int nWidthImg = m_pBSEImg->GetWidth();
  113. int nHeightImg = m_pBSEImg->GetHeight();
  114. long nImgSize = nWidthImg * nHeightImg;
  115. BYTE* pPixel = new BYTE[nImgSize];
  116. BYTE* pSrcImg = m_pBSEImg->GetImageDataPointer();
  117. BYTE* pTargetImg = new BYTE[nImgSize];
  118. BYTE* pTempImg = new BYTE[nImgSize];
  119. memset(pPixel, 0, sizeof(BYTE)*nImgSize);
  120. memset(pTargetImg, 0, sizeof(BYTE)*nImgSize);
  121. memset(pTempImg, 0, sizeof(BYTE)*nImgSize);
  122. long nBGStart = a_pImageProcessParam->GetBGGray().GetStart();
  123. long nBGEnd = a_pImageProcessParam->GetBGGray().GetEnd();
  124. long nPtStart = a_pImageProcessParam->GetParticleGray().GetStart();
  125. long nPtEnd = a_pImageProcessParam->GetParticleGray().GetEnd();
  126. // delete background and not not particle ones
  127. long nNumParticle = 0;
  128. for (int i = 0; i < nImgSize; i++)
  129. {
  130. if (pSrcImg[i] >= nBGStart && pSrcImg[i] <= nBGEnd)
  131. {
  132. pPixel[i] = 0;
  133. }
  134. else
  135. {
  136. pPixel[i] = 255;
  137. nNumParticle++;
  138. }
  139. }
  140. if (nNumParticle == 0)
  141. {
  142. COTSParticleList listParticleEmpty;
  143. listParticleEmpty.clear();
  144. m_pFieldData->SetParticleList(listParticleEmpty);
  145. memset(pPixel, 0, nImgSize);
  146. LogInfoTrace(__FILE__, __LINE__, _T("RemoveBSEImageBG: no particle is found."));
  147. }
  148. else
  149. {
  150. memcpy(pTempImg, pPixel, nImgSize);
  151. // get the area image
  152. memcpy(pPixel, pTempImg, nImgSize);
  153. COTSImageProcess::BErode3(pPixel, pTargetImg, 5, nHeightImg, nWidthImg);
  154. COTSImageProcess::BDilate3(pTargetImg, pPixel, 5, nHeightImg, nWidthImg);
  155. memcpy(pPixel, pTargetImg, nImgSize);
  156. COTSParticleList listParticleOut;
  157. if (!GetParticles(nWidthImg, nHeightImg, pPixel, listParticleOut))
  158. {
  159. COTSParticleList listParticleEmpty;
  160. listParticleEmpty.clear();
  161. m_pFieldData->SetParticleList(listParticleEmpty);
  162. memset(pPixel, 0, nImgSize);
  163. }
  164. else
  165. {
  166. // form a image only have particles on
  167. COTSSegmentsList listImage;
  168. for (auto pParticle : listParticleOut)
  169. {
  170. COTSFeaturePtr pFeature = pParticle->GetFeature();
  171. COTSSegmentsList listSegment = pFeature->GetSegmentsList();
  172. long nPixelNum = 0;
  173. long nPixelAll = 0;
  174. int nStartS = 0;
  175. int nHeightS = 0;
  176. int nLengthS = 0;
  177. for (auto pSegment : listSegment)
  178. {
  179. // update image list
  180. COTSSegmentPtr pSegNew = COTSSegmentPtr(new COTSSegment(*pSegment.get()));
  181. listImage.push_back(pSegNew);
  182. // get particle average gray
  183. nStartS = pSegment->GetStart();
  184. nHeightS = pSegment->GetHeight();
  185. nLengthS = pSegment->GetLength();
  186. nPixelNum += (long)nLengthS;
  187. if (nHeightS > nHeightImg)
  188. {
  189. LogErrorTrace(__FILE__, __LINE__, _T("seg height is wrong."));
  190. return FALSE;
  191. }
  192. if ((nStartS + nLengthS - 1) > nWidthImg)
  193. {
  194. LogErrorTrace(__FILE__, __LINE__, _T("seg starst and length is wrong."));
  195. return FALSE;
  196. }
  197. for (int i = 0; i < nLengthS; i++)
  198. {
  199. if ((nStartS + i) > nWidthImg)
  200. {
  201. LogErrorTrace(__FILE__, __LINE__, _T("seg start is wrong."));
  202. return FALSE;
  203. }
  204. else if (nHeightS > nHeightImg)
  205. {
  206. LogErrorTrace(__FILE__, __LINE__, _T("seg height is wrong."));
  207. return FALSE;
  208. }
  209. long nValueTemp = (long)*(pSrcImg + nHeightS * nWidthImg + nStartS + i);
  210. nPixelAll += nValueTemp;
  211. }
  212. }
  213. BYTE nAveGray = (BYTE)(nPixelAll / nPixelNum);
  214. pParticle->SetAveGray(nAveGray);
  215. pParticle->SetArea(nPixelNum);
  216. }
  217. m_pFieldData->SetParticleList(listParticleOut);
  218. memset(pPixel, 0, nImgSize);
  219. int nS, nH, nL;
  220. for (auto pSegment : listImage)
  221. {
  222. nS = pSegment->GetStart();
  223. nH = pSegment->GetHeight();
  224. nL = pSegment->GetLength();
  225. memcpy((pPixel + nH * nWidthImg + nS), (pSrcImg + nH * nWidthImg + nS), nL);
  226. }
  227. // only used to show clearly.
  228. for (int i = 0; i < nImgSize; i++)
  229. {
  230. if (*(pPixel + i) == 0)
  231. {
  232. *(pPixel + i) = 255;
  233. }
  234. else
  235. {
  236. continue;
  237. }
  238. }
  239. }
  240. }
  241. delete[]pPixel;
  242. delete[]pTargetImg;
  243. delete[]pTempImg;
  244. return TRUE;
  245. }
  246. // remove oversize particles and small particles and get analysis particles list
  247. BOOL COTSFieldMgr::ProcessParticles(COTSImageProcessParamPtr a_pImageProcessParam, double a_dPixelSize, COTSParticleList& a_listParticlesOut)
  248. {
  249. // safety check
  250. ASSERT(a_pImageProcessParam);
  251. if (!a_pImageProcessParam)
  252. {
  253. // invalid image process parameter pointer
  254. LogErrorTrace(__FILE__, __LINE__, _T("ProcessParticles: invalid image process parameter pointer."));
  255. return FALSE;
  256. }
  257. if (a_dPixelSize <= 0)
  258. {
  259. LogErrorTrace(__FILE__, __LINE__, _T("ProcessParticles: invalid pixel size data."));
  260. return FALSE;
  261. }
  262. // get area range
  263. CDoubleRange oAreaRange = a_pImageProcessParam->GetIncArea();
  264. double nAreaLow = (oAreaRange.GetStart()/2) * (oAreaRange.GetStart()/2) * 3.14159;
  265. double nAreaHigh = (oAreaRange.GetEnd()/2) * (oAreaRange.GetEnd()/2) * 3.14159;
  266. // gray level range
  267. CIntRange oParticleGrayRange = a_pImageProcessParam->GetParticleGray();
  268. int nGrayLow = oParticleGrayRange.GetStart();
  269. int nGrayHigh = oParticleGrayRange.GetEnd();
  270. // get particles list
  271. COTSParticleList listParticles = m_pFieldData->GetParticleList();
  272. // go through each particles
  273. a_listParticlesOut.clear();
  274. int nTagId = 0;
  275. //int nSearchPartId = 0;
  276. int nAnalysisPartId = 0;
  277. for (auto pParticle : listParticles)
  278. {
  279. // get particle area
  280. double dPartArea = pParticle->GetArea();
  281. dPartArea = dPartArea * a_dPixelSize * a_dPixelSize;
  282. pParticle->SetArea(dPartArea);
  283. // get average gray level
  284. int nAveGrayLevel = pParticle->GetAveGray();
  285. // set particle tag id
  286. pParticle->SetTagId(nTagId++);
  287. // set field id
  288. pParticle->SetFieldId(m_pFieldData->GetId());
  289. // oversize particles
  290. if (dPartArea > (double)nAreaHigh)
  291. {
  292. pParticle->SetType((int)OTS_PARTCLE_TYPE::OVERSIZE);
  293. LogInfoTrace(__FILE__, __LINE__, _T("ProcessParticles: oversize particle, particle size is %f"), dPartArea);
  294. continue;
  295. }
  296. // too small to measure
  297. else if (dPartArea < (double)nAreaLow)
  298. {
  299. pParticle->SetType((int)OTS_PARTCLE_TYPE::SMALL);
  300. LogInfoTrace(__FILE__, __LINE__, _T("ProcessParticles: samll particle, particle size is %f"), dPartArea);
  301. continue;
  302. }
  303. // gray level is not in the measurement range
  304. else if (nGrayLow > nAveGrayLevel || nAveGrayLevel > nGrayHigh)
  305. {
  306. pParticle->SetType((int)OTS_PARTCLE_TYPE::AVE_GRAY_NOT_INRANRE);
  307. LogInfoTrace(__FILE__, __LINE__, _T("ProcessParticles: gray not interested particle, particle gray is %d, gray range(%d, %d)"), nAveGrayLevel, nGrayLow, nGrayHigh);
  308. continue;
  309. }
  310. // add the particle into the output particles list
  311. pParticle->SetType((int)OTS_PARTCLE_TYPE::NOT_IDENTIFIED);
  312. pParticle->SetAnalysisId(nAnalysisPartId);
  313. a_listParticlesOut.push_back(pParticle);
  314. ++nAnalysisPartId;
  315. }
  316. // ok, return TRUE
  317. return TRUE;
  318. }
  319. BOOL COTSFieldMgr::IdentifyParticle(COTSImageProcessParamPtr a_pImageProcessParam, CPosXraysList& a_listXRay)
  320. {
  321. ASSERT(a_pImageProcessParam);
  322. if (!a_pImageProcessParam)
  323. {
  324. LogErrorTrace(__FILE__, __LINE__, _T("IdentifyParticle: there is no image process data"));
  325. return FALSE;
  326. }
  327. CDoubleRange oAreaRange = a_pImageProcessParam->GetIncArea();
  328. double nAreaLow = oAreaRange.GetStart();
  329. double nAreaHigh = oAreaRange.GetEnd();
  330. CIntRange oParticleGrayRange = a_pImageProcessParam->GetParticleGray();
  331. int nGrayLow = oParticleGrayRange.GetStart();
  332. int nGrayHigh = oParticleGrayRange.GetEnd();
  333. COTSParticleList listParticle = m_pFieldData->GetParticleList();
  334. a_listXRay.clear();
  335. int nSearchPartId = 0;
  336. int nXrayIndex = 0;
  337. for (auto pParticle : listParticle)
  338. {
  339. if (!pParticle->CalArea())
  340. {
  341. LogErrorTrace(__FILE__, __LINE__, _T("IdentifyParticle: failed to calculate particle area."));
  342. return FALSE;
  343. }
  344. double dArea = pParticle->GetArea();
  345. BYTE nAveGray = pParticle->GetAveGray();
  346. if (dArea > (double)nAreaHigh)
  347. {
  348. pParticle->SetType((int)OTS_PARTCLE_TYPE::OVERSIZE);
  349. }
  350. else if (dArea < (double)nAreaLow)
  351. {
  352. pParticle->SetType((int)OTS_PARTCLE_TYPE::SMALL);
  353. }
  354. else
  355. {
  356. if (nAveGray <= nGrayHigh && nAveGray >= nGrayLow)
  357. {
  358. pParticle->SetType((int)OTS_PARTCLE_TYPE::SEARCH_X_RAY);
  359. if (!pParticle->CalXRayPos())
  360. {
  361. LogErrorTrace(__FILE__, __LINE__, _T("IdentifyParticle: failed to calculate x-ray position."));
  362. return FALSE;
  363. }
  364. CPoint pt = pParticle->GetXRayPos();
  365. CPosXrayPtr pPosXray = CPosXrayPtr(new CPosXray());
  366. nXrayIndex++;
  367. pPosXray->SetIndex(nXrayIndex);
  368. pPosXray->SetPartTagId(nSearchPartId);
  369. pPosXray->SetPosition(pt);
  370. pPosXray->SetScanFieldId(m_pFieldData->GetId());
  371. pPosXray->SetFeatureId(nSearchPartId);
  372. a_listXRay.push_back(pPosXray);
  373. }
  374. }
  375. nSearchPartId++;
  376. }
  377. return TRUE;
  378. }
  379. // create x-ray list for a set of particles
  380. BOOL COTSFieldMgr::CreateXrayList(COTSParticleList& a_listParticles, CPosXraysList& a_listPosXRay)
  381. {
  382. // go through particles list
  383. a_listPosXRay.clear();
  384. int nXrayIndex = 0;
  385. for (auto pPart : a_listParticles)
  386. {
  387. if (!pPart->CalXRayPos())
  388. {
  389. LogErrorTrace(__FILE__, __LINE__, _T("CreateXrayList: failed to calculate x-ray position."));
  390. return FALSE;
  391. }
  392. // get xray position
  393. CPoint poi = pPart->GetXRayPos();
  394. // create a x-ray
  395. CPosXrayPtr pPosXray = CPosXrayPtr(new CPosXray());
  396. // set x-ray position
  397. pPosXray->SetPosition(poi);
  398. // set particle tag id
  399. pPosXray->SetPartTagId(pPart->GetTagId());
  400. pPosXray->SetIndex(nXrayIndex++);
  401. // set field id
  402. pPosXray->SetScanFieldId(pPart->GetFieldId());
  403. // add the x-ray into the list
  404. a_listPosXRay.push_back(pPosXray);
  405. }
  406. return TRUE;
  407. }
  408. // field on-line classification
  409. BOOL COTSFieldMgr::OnLineClassification()
  410. {
  411. // safety check
  412. ASSERT(m_pFieldData);
  413. if (!m_pFieldData)
  414. {
  415. // invalid field data pointer
  416. LogErrorTrace(__FILE__, __LINE__, _T("OnLineClassification: invalid field data pointer."));
  417. return FALSE;
  418. }
  419. ASSERT(m_pMsrResults);
  420. if (!m_pMsrResults)
  421. {
  422. // invalid measure results pointer
  423. LogErrorTrace(__FILE__, __LINE__, _T("OnLineClassification: invalid measure results pointer."));
  424. return FALSE;
  425. }
  426. // get particles list of the field data
  427. COTSParticleList& listParticles = m_pFieldData->GetParticleList();
  428. // go through the particles list
  429. for (auto pParticle : listParticles)
  430. {
  431. // create a measure result item
  432. CMsrResultItemPtr pMsrResultItem = CMsrResultItemPtr(new CMsrResultItem());
  433. pMsrResultItem->SetTypeId(pParticle->GetType());
  434. pMsrResultItem->SetArea((int)(pParticle->GetArea() + 0.5));
  435. pMsrResultItem->SetNumber(1);
  436. pMsrResultItem->SetName(pParticle->TypeName());
  437. m_pMsrResults->CumulateMeasureResults(pMsrResultItem);
  438. }
  439. return TRUE;
  440. }
  441. void COTSFieldMgr::SetMsrResult(CMsrResultsPtr a_pMsrResults)
  442. {
  443. ASSERT(a_pMsrResults);
  444. if (!a_pMsrResults)
  445. {
  446. LogErrorTrace(__FILE__, __LINE__, _T("SetMsrResult: invalid pointer."));
  447. return;
  448. }
  449. m_pMsrResults = a_pMsrResults;
  450. }
  451. // save field files
  452. BOOL COTSFieldMgr::SaveFieldFiles()
  453. {
  454. ASSERT(m_pFieldData);
  455. if (!m_pFieldData)
  456. {
  457. LogErrorTrace(__FILE__, __LINE__, _T("SaveFieldFiles: invalid field data pointer."));
  458. return FALSE;
  459. }
  460. CString strFieldFileFolder = m_pFieldData->GetFieldFileFolder();
  461. ASSERT(m_pBSEImg);
  462. if (!m_pBSEImg)
  463. {
  464. LogErrorTrace(__FILE__, __LINE__, _T("SaveFieldFiles: invalid BSE data pointer."));
  465. return FALSE;
  466. }
  467. CBSEImgFileMgrPtr pBSEImgFileMgr = CBSEImgFileMgrPtr(new CBSEImgFileMgr());
  468. pBSEImgFileMgr->SetBSEImg(m_pBSEImg);
  469. int nId = m_pFieldData->GetId();
  470. CString sFieldId;
  471. sFieldId.Format(_T("%d"), nId);
  472. // get field BSE file pathname
  473. CString strBSEFilePathname = strFieldFileFolder + SMPL_MSR_RESULT_FIELDS_BSE + sFieldId + BMP_IMG_FILE_EXT;
  474. if (!pBSEImgFileMgr->SaveIntoBitmap(strBSEFilePathname))
  475. {
  476. LogErrorTrace(__FILE__, __LINE__, _T("SaveFieldFiles: save BSE file failed."));
  477. return FALSE;
  478. }
  479. // analysis x ray list
  480. CString strXRayAnalysisFilename = strFieldFileFolder + _T("\\") + SMPL_MSR_RESULT_ANALYSIS_X_RAY_FILE;
  481. CPosXrayFileMgrPtr pPosAnalysisXrayFileMgr = CPosXrayFileMgrPtr(new CPosXrayFileMgr(strXRayAnalysisFilename));
  482. pPosAnalysisXrayFileMgr->SetPosXrayList(m_listAnalysisPosXray, TRUE);
  483. pPosAnalysisXrayFileMgr->SetHasElement(TRUE);
  484. if (!pPosAnalysisXrayFileMgr->Save(strXRayAnalysisFilename))
  485. {
  486. LogErrorTrace(__FILE__, __LINE__, _T("SaveFieldFiles: save analysis x-ray failed."));
  487. return FALSE;
  488. }
  489. // IncA Data list
  490. CString strIncAFilename = strFieldFileFolder + _T("\\") + SMPL_MSR_RESULT_INCLUSION_FILE;
  491. CIncAFileMgrPtr pIncAFileMgr = CIncAFileMgrPtr(new CIncAFileMgr(strIncAFilename));
  492. pIncAFileMgr->SetPosXrayList(m_listAnalysisPosXray, TRUE);
  493. COTSParticleList listIncAParticle=m_pFieldData->GetParticleList();
  494. pIncAFileMgr->SetParticleList(listIncAParticle, TRUE);
  495. pIncAFileMgr->SetFieldPos(m_pFieldData->GetPosition());
  496. pIncAFileMgr->SetMsrStatus(this->GetMsrStatus());
  497. if (!pIncAFileMgr->Save(strIncAFilename))
  498. {
  499. LogErrorTrace(__FILE__, __LINE__, _T("SaveFieldFiles: save inclusion file failed."));
  500. return FALSE;
  501. }
  502. // ok, return TRUE
  503. return TRUE;
  504. }
  505. BOOL COTSFieldMgr::DoSearchXRayAnalysis(COTSXRayParamPtr a_pXrayParam, std::vector<std::vector<BrukerSegment>>& a_listFeatures, CPosXraysList& a_listXRay)
  506. {
  507. ASSERT(a_pXrayParam);
  508. if (!a_pXrayParam)
  509. {
  510. LogErrorTrace(__FILE__, __LINE__, _T("DoSearchXRayAnalysis: there is no image process data"));
  511. return FALSE;
  512. }
  513. long nSearchCount = a_pXrayParam->GetXRaySearchCount();
  514. ASSERT(m_pFieldData);
  515. if (!m_pFieldData)
  516. {
  517. LogErrorTrace(__FILE__, __LINE__, _T("DoSearchXRayAnalysis: there is no field data"));
  518. return FALSE;
  519. }
  520. COTSParticleList listParticle = m_pFieldData->GetParticleList();
  521. if (listParticle.empty())
  522. {
  523. LogErrorTrace(__FILE__, __LINE__, _T("DoSearchXRayAnalysis: there is no particles"));
  524. return FALSE;
  525. }
  526. if (listParticle.size() < m_listSearchPosXray.size())
  527. {
  528. LogErrorTrace(__FILE__, __LINE__, _T("DoSearchXRayAnalysis: there is no enough particles"));
  529. return FALSE;
  530. }
  531. // x-ray data
  532. //DWORD* pXrayData = new DWORD[GENERALXRAYCHANNELS];
  533. DWORD* pXrayData;
  534. for (auto pPosXray : m_listSearchPosXray)
  535. {
  536. pXrayData = pPosXray->GetXrayData();
  537. //compute count
  538. long nPosCurCount = 0;
  539. for (int i = 0; i < GENERALXRAYCHANNELS; i++)
  540. {
  541. nPosCurCount += pXrayData[i];
  542. }
  543. //if this particle should do x-ray analysis
  544. if (nPosCurCount >= nSearchCount)
  545. {
  546. long nPartTagId = pPosXray->GetPartTagId();
  547. COTSParticlePtr pParticle = listParticle[nPartTagId];
  548. pParticle->SetType((int)OTS_PARTCLE_TYPE::NO_ANALYSIS_X_RAY);
  549. COTSFeaturePtr pFeature = pParticle->GetFeature();
  550. COTSSegmentsList listSegment = pFeature->GetSegmentsList();
  551. std::vector<BrukerSegment> listBrukSegment;
  552. for (auto Segment : listSegment)
  553. {
  554. BrukerSegment BrukSeg;
  555. BrukSeg.XCount = Segment->GetLength();
  556. BrukSeg.Y = Segment->GetHeight();
  557. BrukSeg.XStart = Segment->GetStart();
  558. listBrukSegment.push_back(BrukSeg);
  559. }
  560. a_listFeatures.push_back(listBrukSegment);
  561. CPosXrayPtr pPosXrayNewPtr = CPosXrayPtr(new CPosXray(*pPosXray.get()));
  562. a_listXRay.push_back(pPosXrayNewPtr);
  563. }
  564. }
  565. return TRUE;
  566. }
  567. // Check if is there any particles
  568. BOOL COTSFieldMgr::NoParticle()
  569. {
  570. ASSERT(m_pFieldData);
  571. if (!m_pFieldData)
  572. {
  573. // invalid field data.
  574. LogErrorTrace(__FILE__, __LINE__, _T("Init: invalid field data."));
  575. // return TRUE means NO particles
  576. return TRUE;
  577. }
  578. return m_pFieldData->GetParticleList().empty();
  579. }
  580. BOOL COTSFieldMgr::GetSegmentList(long a_nWidth, long a_nHeight, const BYTE* a_pPixel, COTSSegmentsList& a_listSegments)
  581. {
  582. ASSERT(a_pPixel);
  583. if (!a_pPixel)
  584. {
  585. LogErrorTrace(__FILE__, __LINE__, _T("GetSegments: there is no image data"));
  586. return FALSE;
  587. }
  588. long nImgSize = a_nWidth * a_nHeight;
  589. a_listSegments.clear();
  590. //1. get segment line by line
  591. long nLine, nm, nn;
  592. long nStart, nLength;
  593. for (nLine = 0; nLine < a_nHeight; nLine++)
  594. {
  595. for (nm = 0; nm < a_nWidth; nm += (nLength + 1))
  596. {
  597. nLength = 0;
  598. // get start
  599. if (*(a_pPixel + nLine*a_nWidth + nm) != 0)
  600. {
  601. nStart = nm;
  602. nLength++;
  603. //get length
  604. for (nn = nm + 1; nn < a_nWidth; nn++)
  605. {
  606. // check if segment is over, break
  607. if (nLength != 0)
  608. {
  609. if (*(a_pPixel + nLine*a_nWidth + nn) == 0)
  610. break;
  611. }
  612. if (*(a_pPixel + nLine*a_nWidth + nn) != 0)
  613. {
  614. nLength++;
  615. }
  616. }
  617. // generate segment
  618. COTSSegmentPtr pSegment = COTSSegmentPtr(new COTSSegment(nLine, nStart, nLength));
  619. a_listSegments.push_back(pSegment);
  620. }
  621. else
  622. {
  623. continue;
  624. }
  625. }
  626. }
  627. if ((int)a_listSegments.size() == 0)
  628. {
  629. LogErrorTrace(__FILE__, __LINE__, _T("no particle is found."));
  630. return FALSE;
  631. }
  632. return TRUE;
  633. }
  634. BOOL COTSFieldMgr::GetFeatureList1(COTSSegmentsList& a_listSegments, COTSFeatureList& a_listFeatures)
  635. {
  636. COTSSegmentsList listSegmentNew;
  637. std::map<long, COTSSegmentsList > mapOneLineSegments;
  638. for each(auto s in a_listSegments)
  639. {
  640. mapOneLineSegments[s->GetHeight()].push_back(s);//sorting all the segments base on the line number.
  641. }
  642. std::map<long, COTSSegmentsList >::iterator lineItr = mapOneLineSegments.begin();//find the highest line
  643. while (lineItr != mapOneLineSegments.end())
  644. {
  645. for (auto s = lineItr->second.begin(); s < lineItr->second.end(); )//find one segment of this line.
  646. {
  647. COTSSegmentPtr bottomSeg = *s;
  648. listSegmentNew.clear();
  649. listSegmentNew.push_back(*s);
  650. s = lineItr->second.erase(s);
  651. std::map<long, COTSSegmentsList >::iterator tempItr = lineItr;
  652. tempItr++;
  653. for (; tempItr != mapOneLineSegments.end(); tempItr++)//find all other lines of segments
  654. {
  655. if (tempItr->first - bottomSeg->GetHeight() > 1)
  656. {
  657. break;
  658. }
  659. for (auto nextLineSegment = tempItr->second.begin(); nextLineSegment < tempItr->second.end();)//find next line's all segments
  660. {
  661. if (((*nextLineSegment)->GetStart() - (bottomSeg->GetStart() + bottomSeg->GetLength())) > 1)
  662. {
  663. break;
  664. }
  665. if (bottomSeg->UpDownConection(**nextLineSegment))
  666. {
  667. listSegmentNew.push_back(*nextLineSegment);
  668. bottomSeg = *nextLineSegment;
  669. nextLineSegment = tempItr->second.erase(nextLineSegment);
  670. break;
  671. }
  672. if (tempItr->second.size() > 0)
  673. {
  674. nextLineSegment++;
  675. }
  676. else
  677. {
  678. break;
  679. }
  680. }
  681. }
  682. COTSFeaturePtr pFeature = COTSFeaturePtr(new COTSFeature());
  683. pFeature->SetSegmentsList(listSegmentNew);
  684. //check if this new feature is connected with other found feature.
  685. COTSSegmentPtr topSeg = listSegmentNew[0];//find the toppest segment of this new feature.
  686. COTSSegmentPtr bottomSegment = listSegmentNew[listSegmentNew.size() - 1];//find the lowest segment of this new feature.
  687. bool haveMerged = false;
  688. for each(auto f in a_listFeatures)
  689. {
  690. for (auto seg : f->GetSegmentsList())
  691. {
  692. if (bottomSegment->UpDownConection(*seg) || topSeg->UpDownConection(*seg))
  693. {
  694. COTSSegmentsList segs = f->GetSegmentsList();
  695. for (auto s : listSegmentNew)
  696. {
  697. segs.push_back(s);
  698. }
  699. f->SetSegmentsList(segs);
  700. haveMerged = true;
  701. break;
  702. }
  703. }
  704. if (haveMerged)
  705. {
  706. break;
  707. }
  708. }
  709. if (!haveMerged)
  710. {
  711. a_listFeatures.push_back(pFeature);
  712. }
  713. if (lineItr->second.size() == 0)
  714. {
  715. break;
  716. }
  717. }
  718. lineItr++;
  719. }
  720. return true;
  721. }
  722. BOOL COTSFieldMgr::ChangeFeaturelist(COTSFeatureList& a_listFeatures, COTSParticleList& a_listParticle)
  723. {
  724. if (a_listFeatures.size() == 0)
  725. {
  726. LogErrorTrace(__FILE__, __LINE__, _T("ChangeFeaturelist: there is no feature in the list."));
  727. return FALSE;
  728. }
  729. // compute Rect
  730. for (auto pFeature : a_listFeatures)
  731. {
  732. COTSParticlePtr pParticle = COTSParticlePtr(new COTSParticle());
  733. pParticle->SetFeature(pFeature);
  734. if(!pParticle->CalCoverRect())
  735. {
  736. LogErrorTrace(__FILE__, __LINE__, _T("ChangeFeaturelist: failed to get particle rect."));
  737. return FALSE;
  738. }
  739. a_listParticle.push_back(pParticle);
  740. }
  741. if ((int)a_listParticle.size() == 0)
  742. {
  743. LogErrorTrace(__FILE__, __LINE__, _T("Can't get particle."));
  744. return FALSE;
  745. }
  746. return TRUE;
  747. }
  748. BOOL COTSFieldMgr::GetParticles(long a_nWidth, long a_nHeight, const BYTE* a_pPixel, COTSParticleList& a_listParticles)
  749. {
  750. ASSERT(a_pPixel);
  751. if (!a_pPixel)
  752. {
  753. LogErrorTrace(__FILE__, __LINE__, _T("GetParticles: there is no image data"));
  754. return FALSE;
  755. }
  756. a_listParticles.clear();
  757. COTSSegmentsList listSegment;
  758. listSegment.clear();
  759. //1. get segment line by line
  760. if(!GetSegmentList(a_nWidth, a_nHeight, a_pPixel, listSegment))
  761. {
  762. LogErrorTrace(__FILE__, __LINE__, _T("GetParticles:failed to get segments."));
  763. return FALSE;
  764. }
  765. if ((int)listSegment.size() == 0)
  766. {
  767. LogErrorTrace(__FILE__, __LINE__, _T("no particle is found."));
  768. return FALSE;
  769. }
  770. //2. save the temp feature
  771. COTSFeatureList listFeature;
  772. listFeature.clear();
  773. if (!GetFeatureList1(listSegment, listFeature))
  774. {
  775. LogErrorTrace(__FILE__, __LINE__, _T("GetParticles:failed to get up down segment list."));
  776. return FALSE;
  777. }
  778. if ((int)listFeature.size() == 0)
  779. {
  780. LogErrorTrace(__FILE__, __LINE__, _T("no particle is found."));
  781. return FALSE;
  782. }
  783. COTSParticleList listParticles;
  784. listParticles.clear();
  785. if (!ChangeFeaturelist(listFeature, a_listParticles))
  786. {
  787. LogErrorTrace(__FILE__, __LINE__, _T("can't change feature to particle."));
  788. return FALSE;
  789. }
  790. return TRUE;
  791. }
  792. BOOL COTSFieldMgr::GetIncAParticleList(COTSParticleList& a_listParticleOut)
  793. {
  794. // field data
  795. ASSERT(m_pFieldData);
  796. if (!m_pFieldData)
  797. {
  798. LogErrorTrace(__FILE__, __LINE__, _T("GetIncAParticleList: empty filed data pointer."));
  799. return FALSE;
  800. }
  801. COTSParticleList listParticleIn = m_pFieldData->GetParticleList();
  802. a_listParticleOut.clear();
  803. for (auto pParticle : listParticleIn)
  804. {
  805. int nType = pParticle->GetType();
  806. if (nType > (int)OTS_PARTCLE_TYPE::NO_ANALYSIS_X_RAY)
  807. {
  808. a_listParticleOut.push_back(pParticle);
  809. }
  810. }
  811. return TRUE;
  812. }
  813. BOOL COTSFieldMgr::CalIncAParticleImageProp(double a_pixelSize)
  814. {
  815. // field data
  816. ASSERT(m_pFieldData);
  817. if (!m_pFieldData)
  818. {
  819. LogErrorTrace(__FILE__, __LINE__, _T("CalIncAParticleImageProp: empty filed data pointer."));
  820. return FALSE;
  821. }
  822. COTSParticleList& listParticleIn = m_pFieldData->GetParticleList();
  823. for (auto pParticle : listParticleIn)
  824. {
  825. OTSIMGPROC::COTSImageProcess::CalcuParticleImagePropertes(pParticle, a_pixelSize);
  826. }
  827. return TRUE;
  828. }
  829. BOOL COTSFieldMgr::CalMergedParticleImageProp(COTSParticleList mergedParticles, double a_pixelSize)
  830. {
  831. for (auto pParticle : mergedParticles)
  832. {
  833. OTSIMGPROC::COTSImageProcess::CalcuParticleImagePropertes(pParticle, a_pixelSize);
  834. }
  835. return TRUE;
  836. }
  837. }