123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 |
- #pragma once
- #include "math.h"
- #include "stdafx.h"
- #include "GBImgPropCal.h"
- #include <opencv2/core/core.hpp>
- #include <opencv2/highgui/highgui.hpp>
- #include <opencv2/opencv.hpp>
- #include "OTSImageProcess.h"
- // calculate image properties
- namespace OTSIMGPROC {
- using namespace OTSDATA;
- using namespace cv;
-
- using namespace std;
- //make matrix filled with 255
- const int nBlackColor = 255;
- // construct
- CGBImgPropCal::CGBImgPropCal()
- {
- Init();
- }
- // destruct
- CGBImgPropCal::~CGBImgPropCal()
- {
- Clear();
- }
-
- // get particle ferret diameter
- BOOL CGBImgPropCal::GetParticleFTD(COTSParticlePtr a_pOTSPart, double a_PixelSize , double &dPartFTD, double &dMinWidth, double &dMaxLength, double &dRatio)
- {
- // safety check
- ASSERT(a_pOTSPart);
-
- // 1. convert particle data to image data
- // get the segment list
- COTSSegmentsList listSegment = a_pOTSPart->GetFeature()->GetSegmentsList();
- // get rectangle of the particle
- CRect rect = a_pOTSPart->GetParticleRect();
- // calculate image data size, expand 1 pixel at the edge
- int nWidth = rect.Width() + 1 + nExpand_Size*2;
- int nHeight = rect.Height() + 1 + nExpand_Size*2;
- // define the image data
- Mat cvImageData = Mat::ones(nHeight, nWidth, CV_8U) * nWhiteColor;
- // go through segment list
- for (auto pSegment : listSegment)
- {
- int nStart = pSegment->GetStart() - rect.left + nExpand_Size;
- int nEnd = pSegment->GetStart() + pSegment->GetLength() - rect.left - 1 + nExpand_Size;
- int nHeight = pSegment->GetHeight() - rect.top + nExpand_Size;
- line(cvImageData, Point(nStart, nHeight), Point(nEnd, nHeight), Scalar(nBlackColor), nThickness, nLineType);
- }
-
- // 2. draw the contours
- Mat cvcopyImg = cvImageData.clone();
- //cvImageData.release();
- // contours
- threshold(cvcopyImg, cvcopyImg, nWhiteColor, 100, CV_THRESH_BINARY_INV);
- Canny(cvcopyImg, cvcopyImg, 20, 20 * 2, 3);
- // find contours
- vector<vector<Point>> contours;
- findContours(cvcopyImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
- //Mat cvcopyImg1 = cvcopyImg.clone();
- //drawContours(cvcopyImg1, contours, -1, Scalar(nWhiteColor), 1, 8);
- //cvcopyImg = cvcopyImg - cvcopyImg1;
- //findContours(cvcopyImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
-
- vector<Point> listEdge;
- for (auto listcont : contours)
- {
- for (auto pt : listcont)
- {
- auto itr = std::find_if(listEdge.begin(), listEdge.end(), [pt](Point p)
- {
- return (p.x == pt.x)&&(p.y == pt.y);
- });
- if (itr == listEdge.end())
- {
- listEdge.push_back(pt);
- }
- }
- }
- double nx = 0, ny = 0;
- for (auto pt : listEdge)
- {
- nx = nx + pt.x*pt.x;
- ny = ny + pt.y*pt.y;
- }
- nx = sqrt(nx / (double)listEdge.size());
- ny = sqrt(ny / (double)listEdge.size());
- // 3. calculate the center point
- // find the center point
- /*Moments edgeMoments = moments(listEdge, true);
- Point2f CenterPoint = Point2f(float(edgeMoments.m10 / edgeMoments.m00), float(edgeMoments.m01 / edgeMoments.m00));
- Point ptCenter = (Point)CenterPoint;
- */
- Point ptCenter = Point((int)nx, (int)ny);
- // 4. sort contours into 4 quadrant
- vector<CPoint> QuaOnelist;
- vector<CPoint> QuaTwolist;
- vector<CPoint> QuaThreelist;
- vector<CPoint> QuaFourlist;
- vector<CPoint> Xaxislist;
- vector<CPoint> XaxisUplist;
- vector<CPoint> XaxisDownlist;
- vector<CPoint> Yaxislist;
- vector<CPoint> YaxisRightlist;
- vector<CPoint> YaxisLeftlist;
-
- int Xmax = 0;
- int Ymax = 0;
- // coordinate transformation
- Point ptPosition;
- for (auto pt : listEdge)
- {
- // for touch the contour
- if (pt.x > Xmax)
- Xmax = pt.x;
- if (pt.y > Ymax)
- Ymax = pt.y;
- ptPosition.x = pt.x - ptCenter.x;
- ptPosition.y = ptCenter.y - pt.y;
-
- if (ptPosition.x >0 && ptPosition.y>0)
- {
- QuaOnelist.push_back(CPoint(ptPosition.x,ptPosition.y));
- }
- else if (ptPosition.x <0 && ptPosition.y>0)
- {
- QuaTwolist.push_back(CPoint(ptPosition.x, ptPosition.y));
- }
- else if (ptPosition.x <0 && ptPosition.y<0)
- {
- QuaThreelist.push_back(CPoint(ptPosition.x, ptPosition.y));
- }
- else if (ptPosition.x >0 && ptPosition.y<0)
- {
- QuaFourlist.push_back(CPoint(ptPosition.x, ptPosition.y));
- }
- else if (pt.x == ptCenter.x)
- {
- Yaxislist.push_back(CPoint(ptPosition.x, ptPosition.y));
- }
- else if (pt.y == ptCenter.y)
- {
- Xaxislist.push_back(CPoint(ptPosition.x, ptPosition.y));
- }
- if (ptPosition.y == 1)
- {
- XaxisUplist.push_back(CPoint(ptPosition.x, ptPosition.y));
- }
- else if (ptPosition.y == -1)
- {
- XaxisDownlist.push_back(CPoint(ptPosition.x, ptPosition.y));
- }
- if (ptPosition.x == 1)
- {
- YaxisRightlist.push_back(CPoint(ptPosition.x, ptPosition.y));
- }
- else if (ptPosition.x == -1)
- {
- YaxisLeftlist.push_back(CPoint(ptPosition.x, ptPosition.y));
- }
- }
- // get ferret diameter
- vector<double> FltDiameter;
- if ((Yaxislist.size() == 2) && Xmax >= ptCenter.x)
- {
- double d = (double)abs(Yaxislist[0].y - Yaxislist[1].y);
- FltDiameter.push_back(d);
- }
- else if (Yaxislist.size() > 2)
- {
- double d = GetDisFromRLNeigbor(Yaxislist, YaxisRightlist, YaxisLeftlist);
- FltDiameter.push_back(d);
- }
- if ((Xaxislist.size() == 2) && Ymax >= ptCenter.y)
- {
- double d = (double)abs(Xaxislist[0].x - Xaxislist[1].x);
- FltDiameter.push_back(d);
- }
- else if (Xaxislist.size() > 2)
- {
- double d = GetDisFromUDNeigbor(Xaxislist, XaxisUplist, XaxisDownlist);
- FltDiameter.push_back(d);
- }
- if ((int)QuaOnelist.size() <= ANGLE_MAX || (int)QuaThreelist.size() <= ANGLE_MAX)
- {
- if (!GetDisFrom2list(QuaOnelist, QuaThreelist, FltDiameter))
- {
- return FALSE;
- }
- }
- else
- {
- if (!GetDisFrom13list(QuaOnelist, QuaThreelist, FltDiameter))
- {
- return FALSE;
- }
- }
-
- if ((int)QuaTwolist.size() <= ANGLE_MAX || (int)QuaFourlist.size() <= ANGLE_MAX)
- {
- if (!GetDisFrom2list(QuaTwolist, QuaFourlist, FltDiameter))
- {
- return FALSE;
- }
- }
- else
- {
- if (!GetDisFrom24list(QuaTwolist,QuaFourlist, FltDiameter))
- {
- return FALSE;
- }
- }
- double dSum = 0;
- double dMax = 0;
- double dMin = 0;
- double a_dAveDia = 0;
- GetSuperParticleSize(a_pOTSPart, dMin, dMax, a_dAveDia);
- for (auto d : FltDiameter)
- {
- dSum = dSum + d;
- if (d > dMax)
- dMax = d;
- if (d < dMin && d >0)
- dMin = d;
- }
-
- //calculate the distance
- dPartFTD = a_PixelSize * dSum / (int)FltDiameter.size();
- if ((dSum == 0) || (int)FltDiameter.size() == 0)
- {
- dPartFTD = a_PixelSize * a_dAveDia;
- }
- dMaxLength = a_PixelSize * dMax;
- dMinWidth = a_PixelSize * dMin;
- if (dMin != 0)
- {
- dRatio = dMax / dMin;
- }
- //cvcopyImg.release();
- return TRUE;
- }
-
- // initialization
- void CGBImgPropCal::Init()
- {
- }
- // clear
- void CGBImgPropCal::Clear()
- {
- }
- double CGBImgPropCal::GetDisFrom3(double a_s1, double a_s2, double a_s3)
- {
- double d = 0;
- if (a_s1*a_s2 > 0)
- {
- d = (double)abs(a_s2 - a_s1);
- }
- else if (a_s2*a_s3 > 0)
- {
- d = (double)abs(a_s2 - a_s3);
- }
- else if (a_s2*a_s3 > 0)
- {
- d = (double)abs(a_s3 - a_s1);
- }
- return d;
- }
- BOOL CGBImgPropCal::GetDisFrom2list(std::vector<CPoint> a_list1, std::vector<CPoint> a_list2, std::vector<double>& a_listFlt)
- {
-
- if ((int)a_list1.size() < (int)a_list2.size())
- {
- if (a_list1.empty())
- {
- for (auto pt : a_list2)
- {
- double d = sqrt(pt.x*pt.x + pt.y *pt.y);
- a_listFlt.push_back(d);
- }
- }
- else
- {
- for (auto pt : a_list1)
- {
- double r1 = sqrt(pt.x*pt.x + pt.y *pt.y);
- double k = (double)pt.y / (double)pt.x;
- double kmin = 100;
- for (auto pot : a_list2)
- {
- double kThree = (double)pot.y / (double)pot.x;
- if (abs(kThree - k) < kmin)
- {
- kmin = abs(kThree - k);
- }
- }
- double r2;
- for (auto pot : a_list2)
- {
- double kThree = (double)pot.y / (double)pot.x;
- if (abs(kThree - k) == kmin)
- {
- r2 = sqrt(pot.x * pot.x + pot.y *pot.y);
- break;
- }
- }
- a_listFlt.push_back((r1 + r2));
- }
- }
- }
- else
- {
- if (a_list2.empty())
- {
- for (auto pt : a_list1)
- {
- double d = sqrt(pt.x*pt.x + pt.y *pt.y);
- a_listFlt.push_back(d);
- }
- }
- else
- {
- for (auto pt : a_list2)
- {
- double r1 = sqrt(pt.x*pt.x + pt.y *pt.y);
- double k = (double)pt.y / (double)pt.x;
- double kmin = 100;
- for (auto pot : a_list1)
- {
- double kThree = (double)pot.y / (double)pot.x;
- if (abs(kThree - k) < kmin)
- {
- kmin = abs(kThree - k);
- }
- }
- double r2;
- for (auto pot : a_list1)
- {
- double kThree = (double)pot.y / (double)pot.x;
- if (abs(kThree - k) == kmin)
- {
- r2 = sqrt(pot.x * pot.x + pot.y *pot.y);
- break;
- }
- }
- a_listFlt.push_back((r1 + r2));
- }
- }
- }
- return TRUE;
- }
- BOOL CGBImgPropCal::GetDisFrom4list(std::vector<CPoint> a_list1, std::vector<CPoint> a_list2,
- std::vector<CPoint> a_list3, std::vector<CPoint> a_list4, std::vector<double>& a_listFlt)
- {
- if ((int)a_list1.size() < ANGLE_MAX ||
- (int)a_list2.size() < ANGLE_MAX ||
- (int)a_list3.size() < ANGLE_MAX ||
- (int)a_list4.size() < ANGLE_MAX)
- {
- return FALSE;
- }
- //there should be enough radius in one and two quadrant
- for (int i = 0; i < ANGLE_MAX; i++)
- {
- // one and three
- double k = TAN_VALUES[i];
- double r1 = 0;
- double r2 = 0;
- r1 = GetRadiusAsK(a_list1, k);
- r2 = GetRadiusAsK(a_list3, k);
- if(r1!=0 && r2!=0)
- a_listFlt.push_back((r1 + r2));
- // two and four
- k = -TAN_VALUES[i];
- r1 = GetRadiusAsK(a_list2, k);
- r2 = GetRadiusAsK(a_list4, k);
- if (r1 != 0 && r2 != 0)
- a_listFlt.push_back((r1 + r2));
-
- }
- return TRUE;
- }
- BOOL CGBImgPropCal::GetDisFrom13list(std::vector<CPoint> a_list1,
- std::vector<CPoint> a_list3,std::vector<double>& a_listFlt)
- {
- if ((int)a_list1.size() < ANGLE_MAX ||
- (int)a_list3.size() < ANGLE_MAX )
- {
- return FALSE;
- }
- //there should be enough radius in one and two quadrant
- for (int i = 0; i < ANGLE_MAX; i++)
- {
- // one and three
- double k = TAN_VALUES[i];
- double r1 = 0;
- double r2 = 0;
- r1 = GetRadiusAsK(a_list1, k);
- r2 = GetRadiusAsK(a_list3, k);
- if (r1 != 0 && r2 != 0)
- a_listFlt.push_back((r1 + r2));
- }
- return TRUE;
- }
- BOOL CGBImgPropCal::GetDisFrom24list(std::vector<CPoint> a_list2,
- std::vector<CPoint> a_list4, std::vector<double>& a_listFlt)
- {
- if ((int)a_list2.size() < ANGLE_MAX ||
- (int)a_list4.size() < ANGLE_MAX)
- {
- return FALSE;
- }
- //there should be enough radius in one and two quadrant
- for (int i = 0; i < ANGLE_MAX; i++)
- {
-
- // two and four
- double k = -TAN_VALUES[i];
- double r1 = GetRadiusAsK(a_list2, k);
- double r2 = GetRadiusAsK(a_list4, k);
- if (r1 != 0 && r2 != 0)
- a_listFlt.push_back((r1 + r2));
- }
- return TRUE;
- }
- BOOL CGBImgPropCal::GetSuperParticleSize(COTSParticlePtr a_pOTSPart, double &a_dMinWidth, double &a_dMaxLength, double &a_dAveDia)
- {
- // safety check
- ASSERT(a_pOTSPart);
-
- // 1. convert particle data to image data
- // get the segment list
- COTSSegmentsList listSegment = a_pOTSPart->GetFeature()->GetSegmentsList();
- // get rectangle of the particle
- CRect rect = a_pOTSPart->GetParticleRect();
- //get the particle rectangle size
- a_dMinWidth = rect.Width();
- a_dMaxLength = rect.Height();
- a_dAveDia = (a_dMinWidth + a_dMaxLength) / 2;
- if (a_dMinWidth > a_dMaxLength)
- {
- a_dMaxLength = a_dMinWidth;
- }
- return TRUE;
- }
- // note: this not include touch
- double CGBImgPropCal::GetDisFromRLNeigbor(std::vector<CPoint> a_Yaxislist, std::vector<CPoint> a_YaxisRightlist, std::vector<CPoint> a_YaxisLeftlist)
- {
- double d = 0;
- int nXMax,nXMin;
- GetMaxMin(a_Yaxislist, AXIAS_DIRECTION::XAX, nXMax, nXMin);
- int nXRMax, nXRMin;
- GetMaxMin(a_YaxisRightlist, AXIAS_DIRECTION::XAX, nXRMax, nXRMin);
- int nXLMax, nXLMin;
- GetMaxMin(a_YaxisLeftlist, AXIAS_DIRECTION::XAX, nXLMax, nXLMin);
- if (nXMax*nXMin<0 && (nXLMax*nXLMin < 0 || nXRMax*nXLMin < 0))
- {
- d = abs(nXMax - nXMin);
- }
- return d;
-
- }
-
- double CGBImgPropCal::GetDisFromUDNeigbor(std::vector<CPoint> a_Xaxislist, std::vector<CPoint> a_XaxisUplist, std::vector<CPoint> a_XaxisDownlist)
- {
- double d = 0;
- int nYMax, nYMin;
- GetMaxMin(a_Xaxislist, AXIAS_DIRECTION::YAX, nYMax, nYMin);
- int nYUMax, nYUMin;
- GetMaxMin(a_XaxisUplist, AXIAS_DIRECTION::YAX, nYUMax, nYUMin);
- int nYDMax, nYDMin;
- GetMaxMin(a_XaxisDownlist, AXIAS_DIRECTION::YAX, nYDMax, nYDMin);
- if (nYMax*nYMin<0 && (nYUMax*nYUMin < 0 || nYDMax*nYDMin < 0))
- {
- d = abs(nYMax - nYMin);
- }
- return d;
- }
- BOOL CGBImgPropCal::GetMaxMin(std::vector<CPoint> a_Xaxislist, AXIAS_DIRECTION a_nDirection, int& a_nMax, int& a_nMin)
- {
- int nMax = 0;
- int nMin = 100;
- if (a_nDirection == AXIAS_DIRECTION::YAX)
- {
- for (auto pt : a_Xaxislist)
- {
- if (pt.x > nMax)
- nMax = pt.x;
- if (pt.x < nMin)
- nMin = pt.x;
- }
- }
- else if (a_nDirection == AXIAS_DIRECTION::XAX)
- {
- for (auto pt : a_Xaxislist)
- {
- if (pt.y > nMax)
- nMax = pt.y;
- if (pt.y < nMin)
- nMin = pt.y;
- }
- }
- a_nMax = nMax;
- a_nMin = nMin;
- return TRUE;
- }
- double CGBImgPropCal::GetRadiusAsK(std::vector<CPoint> a_Ptlist, double a_k)
- {
-
- double r1 = 0;
-
- vector<CPoint> ptLengthList;
- for (auto pt : a_Ptlist)
- {
- if (abs(pt.x * a_k - pt.y) < VALUE_MIN)
- {
- ptLengthList.push_back(pt);
- }
- }
- if (ptLengthList.empty())
- return 0;
- double rAve = 0;
- for (auto len : ptLengthList)
- {
- double r = sqrt(len.x * len.x + len.y *len.y);
- rAve += r;
- }
- rAve = rAve / (double)ptLengthList.size();
- return rAve;
- }
- }
|