|
@@ -1028,14 +1028,14 @@ namespace OTSIMGPROC
|
|
|
COTSParticleList listParticleEmpty;
|
|
|
listParticleEmpty.clear();
|
|
|
m_pFieldData->SetParticleList(listParticleEmpty);
|
|
|
- //memset(pPixel, 0, nImgSize);
|
|
|
+
|
|
|
|
|
|
- LogInfoTrace(__FILE__, __LINE__, _T("RemoveBSEImageBG: no particle is found."));
|
|
|
+ //LogInfoTrace(__FILE__, __LINE__, _T("RemoveBSEImageBG: no particle is found."));
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
|
|
|
- //memcpy(pTempImg, pPixel, nImgSize);
|
|
|
+
|
|
|
|
|
|
// get the area image
|
|
|
COTSImageProcess::BErode3(pPixel, pTempImg, 5, nHeightImg, nWidthImg);
|
|
@@ -1044,12 +1044,12 @@ namespace OTSIMGPROC
|
|
|
|
|
|
|
|
|
COTSParticleList listParticleOut;
|
|
|
- if (!GetParticles(nWidthImg, nHeightImg, pPixel, listParticleOut))
|
|
|
+ if (!GetParticles(0,0,nWidthImg, nHeightImg, pPixel, listParticleOut))
|
|
|
{
|
|
|
COTSParticleList listParticleEmpty;
|
|
|
listParticleEmpty.clear();
|
|
|
m_pFieldData->SetParticleList(listParticleEmpty);
|
|
|
- //memset(pPixel, 0, nImgSize);
|
|
|
+
|
|
|
|
|
|
}
|
|
|
|
|
@@ -1119,12 +1119,170 @@ namespace OTSIMGPROC
|
|
|
|
|
|
|
|
|
delete[]pTempImg;
|
|
|
- //delete[]pTempImg;
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
+ }
|
|
|
+ BOOL COTSImageProcess::RemoveBGByFindContour(CBSEImgPtr m_pBSEImg, COTSImageProcessParamPtr a_pImageProcessParam, COTSFieldDataPtr m_pFieldData)
|
|
|
+ {
|
|
|
+
|
|
|
+ ASSERT(m_pFieldData);
|
|
|
+
|
|
|
+ ASSERT(m_pBSEImg);
|
|
|
+
|
|
|
+ ASSERT(a_pImageProcessParam);
|
|
|
+
|
|
|
+
|
|
|
+ int nWidthImg = m_pBSEImg->GetWidth();
|
|
|
+ int nHeightImg = m_pBSEImg->GetHeight();
|
|
|
+ m_pFieldData->Width = nWidthImg;
|
|
|
+ m_pFieldData->Height = nHeightImg;
|
|
|
+ long nImgSize = nWidthImg * nHeightImg;
|
|
|
+
|
|
|
+
|
|
|
+ BYTE* pSrcImg = m_pBSEImg->GetImageDataPointer();
|
|
|
+
|
|
|
+ BYTE* pTempImg = new BYTE[nImgSize];
|
|
|
+
|
|
|
+
|
|
|
+ CBSEImgPtr imgNoBGBinary = CBSEImgPtr(new CBSEImg());
|
|
|
+ long nNumParticle = 0;
|
|
|
+ RemoveBackGround(m_pBSEImg, a_pImageProcessParam, imgNoBGBinary, nNumParticle);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ BYTE* pPixel = imgNoBGBinary->GetImageDataPointer();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ long nPtStart = a_pImageProcessParam->GetParticleGray().GetStart();
|
|
|
+ long nPtEnd = a_pImageProcessParam->GetParticleGray().GetEnd();
|
|
|
+
|
|
|
+
|
|
|
+ if (nNumParticle == 0)
|
|
|
+ {
|
|
|
+
|
|
|
+ COTSParticleList listParticleEmpty;
|
|
|
+ listParticleEmpty.clear();
|
|
|
+ m_pFieldData->SetParticleList(listParticleEmpty);
|
|
|
+
|
|
|
+
|
|
|
+ //LogInfoTrace(__FILE__, __LINE__, _T("RemoveBSEImageBG: no particle is found."));
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+
|
|
|
+ // get the area image
|
|
|
+
|
|
|
+
|
|
|
+ Mat cvcopyImg = Mat(nHeightImg, nWidthImg, CV_8UC1, pPixel);
|
|
|
+ Mat blurImg;
|
|
|
+ medianBlur(cvcopyImg, blurImg, 5);//smooth the edge
|
|
|
+
|
|
|
+ vector<vector<Point>>contours;
|
|
|
+
|
|
|
+ findContours(cvcopyImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
|
|
|
+
|
|
|
+ COTSParticleList listParticleOut;
|
|
|
+ for (size_t i = 0; i < contours.size(); i++)
|
|
|
+ {
|
|
|
+
|
|
|
+ Rect rectMax = boundingRect(contours[i]);
|
|
|
+ Mat rectROI = cvcopyImg(rectMax).clone();
|
|
|
+
|
|
|
+
|
|
|
+ //exclude the point which intersect into this bounding box but is not in this contour.
|
|
|
+ for (int nX = 0; nX < rectROI.rows; nX++)
|
|
|
+ {
|
|
|
+ for (int nY = 0; nY < rectROI.cols; nY++)
|
|
|
+ {
|
|
|
+ double localPos = pointPolygonTest(contours[i], Point2f(nX + rectMax.x, nY + rectMax.y), false);
|
|
|
+ if (localPos == -1)
|
|
|
+ {
|
|
|
+ rectROI.data[nX, nY] = 0;//set the value to 0,so we won't consider it when we find segment and feature in this ROI.
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ GetParticles(rectMax.x, rectMax.y, rectMax.width, rectMax.height, rectROI.data, listParticleOut);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // form a image only have particles on
|
|
|
+ COTSSegmentsList listImage;
|
|
|
+ for (auto pParticle : listParticleOut)
|
|
|
+ {
|
|
|
+ COTSFeaturePtr pFeature = pParticle->GetFeature();
|
|
|
+ COTSSegmentsList listSegment = pFeature->GetSegmentsList();
|
|
|
+
|
|
|
+ long nPixelNum = 0;
|
|
|
+ long nPixelAll = 0;
|
|
|
+ int nStartS = 0;
|
|
|
+ int nHeightS = 0;
|
|
|
+ int nLengthS = 0;
|
|
|
+ for (auto pSegment : listSegment)
|
|
|
+ {
|
|
|
+ // update image list
|
|
|
+ COTSSegmentPtr pSegNew = COTSSegmentPtr(new COTSSegment(*pSegment.get()));
|
|
|
+ listImage.push_back(pSegNew);
|
|
|
+
|
|
|
+
|
|
|
+ // get particle average gray
|
|
|
+ nStartS = pSegment->GetStart();
|
|
|
+ nHeightS = pSegment->GetHeight();
|
|
|
+ nLengthS = pSegment->GetLength();
|
|
|
+ nPixelNum += (long)nLengthS;
|
|
|
+
|
|
|
+
|
|
|
+ if (nHeightS > nHeightImg)
|
|
|
+ {
|
|
|
+ //LogErrorTrace(__FILE__, __LINE__, _T("seg height is wrong."));
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ if ((nStartS + nLengthS - 1) > nWidthImg)
|
|
|
+ {
|
|
|
+ //LogErrorTrace(__FILE__, __LINE__, _T("seg starst and length is wrong."));
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (unsigned int i = 0; i < nLengthS; i++)
|
|
|
+ {
|
|
|
+ if ((nStartS + i) > nWidthImg)
|
|
|
+ {
|
|
|
+ //LogErrorTrace(__FILE__, __LINE__, _T("seg start is wrong."));
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+ else if (nHeightS > nHeightImg)
|
|
|
+ {
|
|
|
+ //LogErrorTrace(__FILE__, __LINE__, _T("seg height is wrong."));
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ long nValueTemp = (long)*(pSrcImg + nHeightS * nWidthImg + nStartS + i);
|
|
|
+ nPixelAll += nValueTemp;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ BYTE nAveGray = (BYTE)(nPixelAll / nPixelNum);
|
|
|
+ pParticle->SetAveGray(nAveGray);
|
|
|
+ pParticle->SetArea(nPixelNum);
|
|
|
+
|
|
|
+ }
|
|
|
+ m_pFieldData->SetParticleList(listParticleOut);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ delete[]pTempImg;
|
|
|
+
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
}
|
|
|
CIntRangePtr COTSImageProcess::CalBackground(CBSEImgPtr m_pBSEImg)
|
|
|
{
|
|
@@ -1203,8 +1361,7 @@ namespace OTSIMGPROC
|
|
|
auto s = downEdgeSeries.rbegin()->second;
|
|
|
pRangeFirst->SetEnd((long)(s[s.size() - 1]));
|
|
|
}
|
|
|
- /*delete[] nBSEChart;
|
|
|
- delete[] n_aBSEChart;*/
|
|
|
+
|
|
|
return pRangeFirst;
|
|
|
}
|
|
|
void COTSImageProcess::RemoveBackGround(CBSEImgPtr a_pImgIn, COTSImageProcessParamPtr a_pImageProcessParam, CBSEImgPtr a_pBinImgOut,long& foundedPixelNum)
|
|
@@ -1219,36 +1376,31 @@ namespace OTSIMGPROC
|
|
|
|
|
|
long nImgSize = nWidthImg * nHeightImg;
|
|
|
|
|
|
- BYTE* pTempImg = new BYTE[nImgSize];
|
|
|
- BYTE* pTempImg2 = new BYTE[nImgSize];
|
|
|
+ BYTE* pTempImg = new BYTE[nImgSize];
|
|
|
|
|
|
BYTE* pSrcImg = a_pImgIn->GetImageDataPointer();
|
|
|
- //memcpy(pTempImg2, pSrcImg, nImgSize);
|
|
|
-
|
|
|
- //cv::blur(pSrcImg, pTempImg2, nImgSize);
|
|
|
-
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
BYTE* pPixel = new byte[nImgSize];
|
|
|
|
|
|
|
|
|
|
|
|
long nBGStart;
|
|
|
long nBGEnd;
|
|
|
-
|
|
|
+ long nPartStart;
|
|
|
+ long nPartEnd;
|
|
|
long nNumParticle = 0;
|
|
|
if (a_pImageProcessParam->GetBGRemoveType() == OTS_BGREMOVE_TYPE::MANUAL)
|
|
|
{
|
|
|
nBGStart = a_pImageProcessParam->GetBGGray().GetStart();
|
|
|
nBGEnd = a_pImageProcessParam->GetBGGray().GetEnd();
|
|
|
+ nPartStart = a_pImageProcessParam->GetParticleGray().GetStart();
|
|
|
+ nPartEnd = a_pImageProcessParam->GetParticleGray().GetEnd();
|
|
|
|
|
|
// delete background
|
|
|
for (unsigned int i = 0; i < nImgSize; i++)
|
|
|
{
|
|
|
- if (pTempImg2[i] >= nBGStart && pTempImg2[i] <= nBGEnd)
|
|
|
+ if (pSrcImg[i] >= nBGStart && pSrcImg[i] <= nBGEnd)
|
|
|
{
|
|
|
pPixel[i] = 0;
|
|
|
}
|
|
@@ -1257,14 +1409,17 @@ namespace OTSIMGPROC
|
|
|
pPixel[i] = 255;
|
|
|
nNumParticle++;
|
|
|
}
|
|
|
+ if (pSrcImg[i]<nPartStart || pSrcImg[i]>nPartEnd)
|
|
|
+ {
|
|
|
+ pPixel[i] = 0;
|
|
|
+ }
|
|
|
}
|
|
|
COTSImageProcess::BErode3(pPixel, pTempImg, 5, nHeightImg, nWidthImg);
|
|
|
COTSImageProcess::BDilate3(pTempImg, pPixel, 5, nHeightImg, nWidthImg);
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- /*CBSEImgPtr srcImg2 = CBSEImgPtr(new CBSEImg());
|
|
|
- srcImg2->SetImageData(a_pImgIn, nWidthImg, nHeightImg);*/
|
|
|
+
|
|
|
auto range = CalBackground(a_pImgIn);
|
|
|
nBGStart = range->GetStart();
|
|
|
|
|
@@ -1276,7 +1431,7 @@ namespace OTSIMGPROC
|
|
|
case OTS_AUTOBGREMOVE_TYPE::DOWNWARD:
|
|
|
for (unsigned int i = 0; i < nImgSize; i++)
|
|
|
{
|
|
|
- if (pTempImg2[i] <= nBGEnd)
|
|
|
+ if (pSrcImg[i] <= nBGEnd)
|
|
|
{
|
|
|
pPixel[i] = 0;
|
|
|
}
|
|
@@ -1290,7 +1445,7 @@ namespace OTSIMGPROC
|
|
|
case OTS_AUTOBGREMOVE_TYPE::UPWARD:
|
|
|
for (unsigned int i = 0; i < nImgSize; i++)
|
|
|
{
|
|
|
- if (pTempImg2[i] >= nBGStart)
|
|
|
+ if (pSrcImg[i] >= nBGStart)
|
|
|
{
|
|
|
pPixel[i] = 0;
|
|
|
}
|
|
@@ -1304,7 +1459,7 @@ namespace OTSIMGPROC
|
|
|
case OTS_AUTOBGREMOVE_TYPE::MIDDLE:
|
|
|
for (unsigned int i = 0; i < nImgSize; i++)
|
|
|
{
|
|
|
- if (pTempImg2[i] >= nBGStart && pTempImg2[i] <= nBGEnd)
|
|
|
+ if (pSrcImg[i] >= nBGStart && pSrcImg[i] <= nBGEnd)
|
|
|
{
|
|
|
pPixel[i] = 0;
|
|
|
}
|
|
@@ -1325,36 +1480,30 @@ namespace OTSIMGPROC
|
|
|
|
|
|
foundedPixelNum = nNumParticle;
|
|
|
delete[] pTempImg;
|
|
|
- delete[] pTempImg2;
|
|
|
+ //delete[] pTempImg2;
|
|
|
return ;
|
|
|
}
|
|
|
- BOOL COTSImageProcess::GetParticles(long a_nWidth, long a_nHeight, const BYTE* a_pPixel, COTSParticleList& a_listParticles)
|
|
|
+ BOOL COTSImageProcess::GetParticles(long left, long top, long a_nWidth, long a_nHeight, const BYTE* a_pPixel, COTSParticleList& a_listParticles)
|
|
|
{
|
|
|
-
|
|
|
ASSERT(a_pPixel);
|
|
|
if (!a_pPixel)
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("GetParticles: there is no image data"));
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
- a_listParticles.clear();
|
|
|
-
|
|
|
+ //a_listParticles.clear();
|
|
|
+ COTSParticleList findedParts;
|
|
|
COTSSegmentsList listSegment;
|
|
|
listSegment.clear();
|
|
|
|
|
|
|
|
|
//1. get segment line by line
|
|
|
- if (!GetSegmentList(a_nWidth, a_nHeight, a_pPixel, listSegment))
|
|
|
+ if (!GetSegmentList(left, top, a_nWidth, a_nHeight, a_pPixel, listSegment))
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("GetParticles:failed to get segments."));
|
|
|
return FALSE;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
if ((int)listSegment.size() == 0)
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("no particle is found."));
|
|
|
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -1363,38 +1512,36 @@ namespace OTSIMGPROC
|
|
|
//2. save the temp feature
|
|
|
COTSFeatureList listFeature;
|
|
|
listFeature.clear();
|
|
|
- if (!GetFeatureList1(listSegment, listFeature))
|
|
|
+ if (!GetFeatureList(listSegment, listFeature))//get every feature for all the particle,the complete feature.
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("GetParticles:failed to get up down segment list."));
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
|
|
|
if ((int)listFeature.size() == 0)
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("no particle is found."));
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
COTSParticleList listParticles;
|
|
|
listParticles.clear();
|
|
|
- if (!ChangeFeaturelist(listFeature, a_listParticles))
|
|
|
+ if (!ChangeFeaturelist(listFeature, findedParts))
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("can't change feature to particle."));
|
|
|
return FALSE;
|
|
|
}
|
|
|
-
|
|
|
+ for (auto f : findedParts)
|
|
|
+ {
|
|
|
+ a_listParticles.push_back(f);
|
|
|
+ }
|
|
|
|
|
|
return TRUE;
|
|
|
-
|
|
|
-
|
|
|
}
|
|
|
- BOOL COTSImageProcess::GetSegmentList(long a_nWidth, long a_nHeight, const BYTE* a_pPixel, COTSSegmentsList& a_listSegments)
|
|
|
+ BOOL COTSImageProcess::GetSegmentList(long left, long top, long a_nWidth, long a_nHeight, const BYTE* a_pPixel, COTSSegmentsList& a_listSegments)
|
|
|
{
|
|
|
ASSERT(a_pPixel);
|
|
|
if (!a_pPixel)
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("GetSegments: there is no image data"));
|
|
|
+ //LogErrorTrace(__FILE__, __LINE__, _T("GetSegments: there is no image data"));
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
@@ -1404,7 +1551,7 @@ namespace OTSIMGPROC
|
|
|
|
|
|
//1. get segment line by line
|
|
|
long nLine, nm, nn;
|
|
|
- long nStart, nLength;
|
|
|
+ long nStart = 0, nLength = 0;
|
|
|
for (nLine = 0; nLine < a_nHeight; nLine++)
|
|
|
{
|
|
|
for (nm = 0; nm < a_nWidth; nm += (nLength + 1))
|
|
@@ -1432,7 +1579,7 @@ namespace OTSIMGPROC
|
|
|
}
|
|
|
|
|
|
// generate segment
|
|
|
- COTSSegmentPtr pSegment = COTSSegmentPtr(new COTSSegment(nLine, nStart, nLength));
|
|
|
+ COTSSegmentPtr pSegment = COTSSegmentPtr(new COTSSegment(nLine + top, nStart + left, nLength));
|
|
|
a_listSegments.push_back(pSegment);
|
|
|
|
|
|
}
|
|
@@ -1445,13 +1592,13 @@ namespace OTSIMGPROC
|
|
|
|
|
|
if ((int)a_listSegments.size() == 0)
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("no particle is found."));
|
|
|
+ //LogErrorTrace(__FILE__, __LINE__, _T("no particle is found."));
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
return TRUE;
|
|
|
}
|
|
|
- BOOL COTSImageProcess::GetFeatureList1(COTSSegmentsList& a_listSegments, COTSFeatureList& a_listFeatures)
|
|
|
+ BOOL COTSImageProcess::GetFeatureList(COTSSegmentsList& a_listSegments, COTSFeatureList& a_listFeatures)
|
|
|
{
|
|
|
COTSSegmentsList listSegmentNew;
|
|
|
std::map<long, COTSSegmentsList > mapOneLineSegments;
|
|
@@ -1553,7 +1700,6 @@ namespace OTSIMGPROC
|
|
|
{
|
|
|
if (a_listFeatures.size() == 0)
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("ChangeFeaturelist: there is no feature in the list."));
|
|
|
return FALSE;
|
|
|
}
|
|
|
// compute Rect
|
|
@@ -1563,7 +1709,6 @@ namespace OTSIMGPROC
|
|
|
pParticle->SetFeature(pFeature);
|
|
|
if (!pParticle->CalCoverRect())
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("ChangeFeaturelist: failed to get particle rect."));
|
|
|
return FALSE;
|
|
|
}
|
|
|
a_listParticle.push_back(pParticle);
|
|
@@ -1571,7 +1716,6 @@ namespace OTSIMGPROC
|
|
|
|
|
|
if ((int)a_listParticle.size() == 0)
|
|
|
{
|
|
|
- LogErrorTrace(__FILE__, __LINE__, _T("Can't get particle."));
|
|
|
return FALSE;
|
|
|
}
|
|
|
|