#include "stdafx.h" #include "OTSParticle.h" #include "Element.h" #include "Convert.h" namespace OTSDATA { // COTSParticle // constructor COTSParticle::COTSParticle() // constructor { Init(); //headerParticle = NULL; } COTSParticle::COTSParticle(const COTSParticle& a_oSource) // copy constructor { // can't copy itself if (&a_oSource == this) { return; } // copy data over Duplicate(a_oSource); } COTSParticle::COTSParticle(COTSParticle* a_poSource) // copy constructor { // can't copy itself if (a_poSource == this) { return; } // copy data over Duplicate(*a_poSource); } COTSParticle& COTSParticle::operator=(const COTSParticle& a_oSource) // =operator { // cleanup Cleanup(); // copy the class data over Duplicate(a_oSource); // return class return *this; } BOOL COTSParticle::operator==(const COTSParticle& a_oSource) // ==operator { // return FASLE, if the two segments list are in different size return ( m_nTagId == a_oSource.m_nTagId && //m_nSearchId == a_oSource.m_nSearchId && m_nAnalysisId == a_oSource.m_nAnalysisId && m_nFieldId == a_oSource.m_nFieldId && m_dArea == a_oSource.m_dArea && m_cAveGray == a_oSource.m_cAveGray && m_classifyId == a_oSource.m_classifyId && m_poiXRayPos == a_oSource.m_poiXRayPos && *(m_pFeature.get()) == *(a_oSource.m_pFeature.get())); } COTSParticle::~COTSParticle() // destructor { Cleanup(); } void COTSParticle::Serialize(bool isStoring, tinyxml2::XMLDocument * classDoc, tinyxml2::XMLElement * rootNode) { xmls::xInt xTagId; xmls::xInt xnSearchId; xmls::xInt xnAnalysisId; xmls::xInt xnFieldId; xmls::xDouble xdArea; xmls::xRect xrectParticle; xmls::xInt xcAveGray; xmls::xInt xType; xmls::xPoint xpoiXRayPos; xmls::Slo slo; slo.Register("TagId", &xTagId); slo.Register("SearchId", &xnSearchId); slo.Register("AnalysisId", &xnAnalysisId); slo.Register("FieldId", &xnFieldId); slo.Register("Area", &xdArea); slo.Register("rectParticle", &xrectParticle); slo.Register("AveGray", &xcAveGray); slo.Register("Type", &xType); slo.Register("poiXRayPos", &xpoiXRayPos); slo.Register("Feature", m_pFeature.get()); if (isStoring) { xTagId = m_nTagId; //xnSearchId = m_nSearchId; xnAnalysisId = m_nAnalysisId; xnFieldId = m_nFieldId; xdArea = m_dArea; xrectParticle = m_rectParticle; xcAveGray = m_cAveGray; xType = m_classifyId; xpoiXRayPos = m_poiXRayPos; slo.Serialize(true, classDoc, rootNode); } else { slo.Serialize(false, classDoc, rootNode); m_nTagId = xTagId.value(); //m_nSearchId = xnSearchId.value(); m_nAnalysisId = xnAnalysisId.value(); m_nFieldId = xnFieldId.value(); m_dArea = xdArea.value(); m_rectParticle = xrectParticle.value(); m_cAveGray = xcAveGray.value(); m_classifyId = xType.value(); m_poiXRayPos = xpoiXRayPos.value(); } } double COTSParticle::GetImgPropertyValueByName(CString propertyName) { //double pvalue; if (propertyName == "Dmax") return this->GetDMax(); if (propertyName == "Dmin") return this->GetDMin(); if (propertyName == "Area") return this->GetActualArea(); if (propertyName == "Dferet") return this->GetFeretDiameter(); if (propertyName == "With") return this->GetMinWidth(); if (propertyName == "Height") return this->GetMinHeight(); if (propertyName == "Perimeter") return this->GetPerimeter(); if (propertyName == "Dperp") return this->GetDPerp(); if (propertyName == "Dinscr") return this->GetDInscr(); if (propertyName == "Dmean") return this->GetDMean(); if (propertyName == "Orientation") return this->GetOrientation(); if (propertyName == "Delong") return this->GetDElong(); if (propertyName == "AspectElong") return this->GetAspectElong(); if (propertyName == "Dequalcircle") return this->GetEqualCircleDiameter(); if (propertyName == "Aspect") return this->GetAspectRatio(); if (propertyName == "Vedio") return this->GetVideo(); if (propertyName == "X") return this->GetXRayPos().x; if (propertyName == "Y") return this->GetXRayPos().y; //return pvalue; } std::string COTSParticle::GetImgPortraitString() { CString str; CString dmax = Convert::MFC::ToString(this->GetDMax()); CString dmin = Convert::MFC::ToString(this->GetDMin()); CString dmean = Convert::MFC::ToString(this->GetDMean()); CString dinsc = Convert::MFC::ToString(this->GetDInscr()); CString dferet = Convert::MFC::ToString(this->GetFeretDiameter()); CString dperp = Convert::MFC::ToString(this->GetDPerp()); CString delong = Convert::MFC::ToString(this->GetDElong()); CString aspect = Convert::MFC::ToString(this->GetAspectRatio()); CString area = Convert::MFC::ToString(this->GetActualArea()); CString video = Convert::MFC::ToString(this->GetVideo()); CString width = Convert::MFC::ToString(this->GetOTSRect().GetWidth()); CString height = Convert::MFC::ToString(this->GetOTSRect().GetHeight()); CString orientation = Convert::MFC::ToString(this->GetOrientation()); str = _T("Area:")+ area + _T(" ") + _T("Gray:")+video + _T(" ") +_T("Dmax:")+ dmax + _T(" ") + _T("Dmin:")+ dmin + _T(" ") + dmean + _T(" ") + dinsc + _T(" ") +_T("Dfere:")+ dferet + _T(" ") + dperp + _T(" ") + delong + _T(" ") + _T("Aspect:")+aspect + _T(" ") + width + _T(" ") + height + _T(" ") +_T("orientation:")+ orientation; return Convert::MFC::CStringToString(str); } double COTSParticle::CalculateSimilarity(COTSParticlePtr part) { //estimate the area first---------- double arearatio = 0; if (this->GetActualArea() <= part->GetActualArea()) { arearatio = this->GetActualArea() / part->GetActualArea(); } else { arearatio = part->GetActualArea() / this->GetActualArea(); } if (arearatio < 0.85) { return 0; } //------------------------- auto data1 = this->GetMorphData(); auto data2 = part->GetMorphData(); // 公式: (x1y1+x2y2+x3y3+...x2000y2000) / (sqrt(x1^2 + x2^2 + ...x2000^2) * sqrt(y1^2 + y2^2 + ...y2000^2)) double dotProduct = 0; double d1 = 0; double d2 = 0; for (int i = 0; i < data1.size(); i++) { double r1 = data1[i]; double r2 = data2[i]; r1 *= r2; dotProduct = dotProduct + r1; } d1 =this->GetMorphologyVectorNorm(); d2 = part->GetMorphologyVectorNorm(); return (0 == d1 || 0 == d2) ? 0 : dotProduct / (d1 * d2); } BOOL COTSParticle::CalCoverRectFromSegment() { ASSERT(m_pFeature); if (!m_pFeature) { return FALSE; } COTSSegmentsList a_listSegment = m_pFeature->GetSegmentsList(); // height is most height - lowest + 1 // width is the widest - thinnest + 1 int nSize = (int)a_listSegment.size(); // no segment, no need to compute if (nSize <= 0) { return FALSE; } // get the most highest, lowest, widest, thinness int nHmin = a_listSegment[0]->GetHeight(); int nHmax = a_listSegment[0]->GetHeight(); int nWmin = a_listSegment[0]->GetStart(); int nWmax = a_listSegment[0]->GetStart() + a_listSegment[0]->GetLength() - 1; // loop segment list for (auto pSegement : a_listSegment) { int nHt = pSegement->GetHeight(); if (nHt < nHmin) { nHmin = nHt; } if (nHt > nHmax) { nHmax = nHt; } int nSt = pSegement->GetStart(); int nEd = pSegement->GetStart() + pSegement->GetLength() - 1; if (nSt < nWmin) { nWmin = nSt; } if (nEd > nWmax) { nWmax = nEd; } } if (nHmin > nHmax || nWmin > nWmax) { return FALSE; } // get the rect m_rectParticle.top = nHmin; m_rectParticle.left = nWmin; m_rectParticle.bottom = nHmax; m_rectParticle.right = nWmax; return TRUE; } BOOL COTSParticle::CalPixelArea() { ASSERT(m_pFeature); if (!m_pFeature) { return FALSE; } COTSSegmentsList a_listSegment = m_pFeature->GetSegmentsList(); // Area is all the segment's length add. int nSize = (int)a_listSegment.size(); m_dPixelArea = 0; // no segment, no need to compute if (nSize <= 0) { return FALSE; } // loop segment list for (auto pSegement : a_listSegment) { m_dPixelArea += (double)pSegement->GetLength(); } return TRUE; } BOOL COTSParticle::CalXRayPos() { ASSERT(m_pFeature); if (!m_pFeature) { return FALSE; } COTSSegmentsList a_listSegment = m_pFeature->GetSegmentsList(); // all the pixels add int nSize = (int)a_listSegment.size(); // no segment, no need to compute if (nSize <= 0) { return FALSE; } // get the 1/3 high part, the longest if(m_rectParticle.IsRectNull()) { if (!CalCoverRectFromSegment()) return FALSE; } COTSSegmentsList listSegmentLength; listSegmentLength.clear(); int nHMax = a_listSegment[0]->GetHeight(); int nHMin = a_listSegment[0]->GetHeight(); for (auto pSegment : a_listSegment) { int nH = pSegment->GetHeight(); if (nH < nHMin) { nHMin = nH; } if (nH > nHMax) { nHMax = nH; } } int nHeight = m_rectParticle.Height(); int nHStart = (int)(nHeight / 3 + nHMin + 0.5); int nHEnd = (int)(2 * nHeight / 3 + nHMax + 0.5); for (auto pSegment : a_listSegment) { int nH = pSegment->GetHeight(); if (nH >= nHStart && nH <= nHEnd) { COTSSegmentPtr pSegmentNew = COTSSegmentPtr(new COTSSegment(*pSegment.get())); listSegmentLength.push_back(pSegmentNew); } } // get the longest length in the middle 1/3 part if ((int)listSegmentLength.size() < 0) { return FALSE; } int nLMax = listSegmentLength[0]->GetLength(); for (auto pSegment : listSegmentLength) { int nL = pSegment->GetLength(); if (nL > nLMax) { nLMax = nL; } } COTSSegmentsList listSegmentMaxLength; listSegmentMaxLength.clear(); // find the segment has the longest length for (auto pSegment : listSegmentLength) { if (pSegment->GetLength() == nLMax) { COTSSegmentPtr pSegmentNew = COTSSegmentPtr(new COTSSegment(*pSegment.get())); listSegmentMaxLength.push_back(pSegmentNew); } } // get the middle longest length if ((int)listSegmentMaxLength.size() < 0) { return FALSE; } COTSSegmentPtr pSegCur = listSegmentMaxLength[0]; int nSegStart = pSegCur->GetStart(); int nSegHeight = pSegCur->GetHeight(); int nSegLength = pSegCur->GetLength(); CPoint ptSegCenter; ptSegCenter.x = (int)(nSegStart + nSegLength / 2 + 0.5); ptSegCenter.y = nSegHeight; CPoint ptPartCenter = m_rectParticle.CenterPoint(); double nHToMMin = sqrt((ptSegCenter.x - ptPartCenter.x)*(ptSegCenter.x - ptPartCenter.x) + (ptSegCenter.y - ptPartCenter.y)*(ptSegCenter.y - ptPartCenter.y)); for (auto pSegment : listSegmentMaxLength) { nSegStart = pSegment->GetStart(); nSegHeight = pSegment->GetHeight(); nSegLength = pSegment->GetLength(); ptSegCenter.x = (int)(nSegStart + nSegLength / 2 + 0.5); ptSegCenter.y = nSegHeight; double nHToM = sqrt((ptSegCenter.x - ptPartCenter.x)*(ptSegCenter.x - ptPartCenter.x) + (ptSegCenter.y - ptPartCenter.y)*(ptSegCenter.y - ptPartCenter.y)); if (nHToM < nHToMMin) { nHToMMin = nHToM; } } // get the middle longest segment for (auto pSegment : listSegmentMaxLength) { nSegStart = pSegment->GetStart(); nSegHeight = pSegment->GetHeight(); nSegLength = pSegment->GetLength(); ptSegCenter.x = (int)(nSegStart + nSegLength / 2 + 0.5); ptSegCenter.y = nSegHeight; double nHToM = sqrt((ptSegCenter.x - ptPartCenter.x)*(ptSegCenter.x - ptPartCenter.x) + (ptSegCenter.y - ptPartCenter.y)*(ptSegCenter.y - ptPartCenter.y)); if (nHToM == nHToMMin) { m_poiXRayPos = ptPartCenter; break; } } return TRUE; } void COTSParticle::SetFeature(COTSFeaturePtr a_pFeature) { ASSERT(a_pFeature); if (!a_pFeature) { return; } //m_pFeature = COTSFeaturePtr(new COTSFeature(*a_pFeature.get())); m_pFeature = a_pFeature; } BOOL COTSParticle::IsConnected(COTSParticle* a_p, int fldwidth, int fldheight, int direction) { //decide if two on boundary particles are connected. typedef enum class SORTING_DIRECTION { LEFT = 1, DOWN = 2, RIGHT = 3, UP = 4 }SORTING_DIRECTION; SORTING_DIRECTION di = (SORTING_DIRECTION)direction; for (auto s : m_pFeature->GetSegmentsList()) { for (auto a_seg : a_p->GetFeature()->GetSegmentsList()) { if (di == SORTING_DIRECTION::LEFT || di == SORTING_DIRECTION::RIGHT) { if (s->GetHeight() == a_seg->GetHeight()) { if ((s->GetStart() + s->GetLength()) == fldwidth && a_seg->GetStart() == 0) { return true;//left connected to neighbor's right. } if ((a_seg->GetStart() + a_seg->GetLength()) == fldwidth && s->GetStart() == 0) { return true;// } } } if (di == SORTING_DIRECTION::UP || di == SORTING_DIRECTION::DOWN) { if (s->GetHeight() == 0 && a_seg->GetHeight() == fldheight - 1)//the lowest height of the segment is the height of the field minus 1. { if (s->GetStart() >= a_seg->GetStart() && s->GetStart() <= a_seg->GetStart() + a_seg->GetLength()) { return true; } if (a_seg->GetStart() >= s->GetStart() && a_seg->GetStart() <= s->GetStart() + s->GetLength()) { return true; } } if (a_seg->GetHeight() == 0 && s->GetHeight() == fldheight - 1) { if (s->GetStart() >= a_seg->GetStart() && s->GetStart() <= a_seg->GetStart() + a_seg->GetLength()) { return true; } if (a_seg->GetStart() >= s->GetStart() && a_seg->GetStart() <= s->GetStart() + s->GetLength()) { return true; } } } } } return false; } // cleanup void COTSParticle::Cleanup() { } // initialization void COTSParticle::Init() { // id and tag id m_nTagId = -1; //m_nSearchId = -1; m_nAnalysisId = -1; m_nFieldId = -1; m_nType = OTS_PARTICLE_TYPE::UNCLASSIFY; // type m_classifyId = 0; // area m_dArea = 0; // gray m_cAveGray = 0; // feature m_pFeature = COTSFeaturePtr(new COTSFeature()); m_dFeretDiameter=0; //最小外接矩形的宽度 m_Width=0; //最小外接矩形的长度 m_Height=0; // STD chemical type m_Perimeter=0; m_DMax=0; m_DMin=0; m_Dp=0; m_Di=0; m_Dm=0; m_De=0; m_Orientation=0; GB_CHEMICAL_TYPE m_nChemical= GB_CHEMICAL_TYPE::INVALID; m_pXRayInfo = nullptr; } // duplication void COTSParticle::Duplicate(const COTSParticle& a_oSource) { // initialization Init(); // copy data over // id and tag id m_nTagId = a_oSource.m_nTagId; //m_nSearchId = a_oSource.m_nSearchId; m_nAnalysisId = a_oSource.m_nAnalysisId; m_nFieldId = a_oSource.m_nFieldId; // type m_classifyId = a_oSource.m_classifyId; // area m_dArea = a_oSource.m_dArea; // rectangle m_rectParticle = a_oSource.m_rectParticle; // gray m_cAveGray = a_oSource.m_cAveGray; // x-ray position m_poiXRayPos = a_oSource.m_poiXRayPos; m_Width = a_oSource.m_Width; m_Height = a_oSource.m_Height; m_classifyName = a_oSource.m_classifyName; m_TypeColor = a_oSource.m_TypeColor; // feature m_pFeature = COTSFeaturePtr(new COTSFeature(*a_oSource.m_pFeature.get())); } double COTSParticle::GetMorphologyVectorNorm() { if (m_vectorNorm == 0) { auto data = GetMorphData(); double d1 = 0; double sumOfchannelPower = 0; for (int i = 0; i < data.size(); i++) { double r1 = data[i]; r1 *= r1; sumOfchannelPower = sumOfchannelPower + r1; } d1 = sqrt(sumOfchannelPower); m_vectorNorm = d1; return m_vectorNorm; } else { return m_vectorNorm; } } std::vector COTSParticle::GetMorphData() { std::vector morphData; morphData.push_back(m_OTSRect.GetWidth()); morphData.push_back(m_OTSRect.GetHeight()); morphData.push_back(m_cAveGray); morphData.push_back(this->GetActualArea()); morphData.push_back(m_DMax); morphData.push_back(m_DMin); morphData.push_back(this->GetDMean()); morphData.push_back(this->GetDElong()); morphData.push_back(this->GetDPerp()); morphData.push_back(this->GetFeretDiameter()); morphData.push_back(this->GetOrientation()); morphData.push_back(this->GetPerimeter()); morphData.push_back(this->GetDInscr()); morphData.push_back(this->GetAspectRatio()); return morphData; } }