浏览代码

add watershed image process algorithm

gsp 11 月之前
父节点
当前提交
6a6214dfc2

+ 3 - 3
Bin/x64/Debug/Config/SysData/OTSProgMgrParam.pmf

@@ -1,9 +1,9 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <XMLData RunMode="ProfessionalMode" SysType="IncA">
   <Member RegName="GenParam" DefaultArea="100" DefaultSampleName="Sample" DefaultShape="0" MeasParamFileFolderName=".\Config\ProData\" MeasSwitch="true" PartSTDLibFolderName=".\Config\SysData\" PropertyDisplayMode="0" StdLibFileName="OTS_TC_Axia_per" SteelTechnology="0" UseSysSTD="true" />
-  <Member RegName="ImageProcParam" AutoBGRemoveType="0:MIDDLE" BGRemoveType="1:MANUAL" MatrixStep="50" OverlapParam="0" ParticleSelectionCondition="">
-    <Member RegName="BGGray" end="102" start="0" />
-    <Member RegName="IncArea" end="500" start="5" />
+  <Member RegName="ImageProcParam" AutoBGRemoveType="0:MIDDLE" BGRemoveType="3:WaterShed" MatrixStep="50" OverlapParam="0" ParticleSelectionCondition="">
+    <Member RegName="BGGray" end="60" start="0" />
+    <Member RegName="IncArea" end="500" start="30" />
     <Member RegName="ParticleGray" end="255" start="0" />
   </Member>
   <Member RegName="ImageScanParam" ImageResolution="4:_1536_1024" SatrtImageMode="1:Snake" ScanImageSpeed="0:low" StopMode="0:CoverMode" StopParamArea="10" StopParamFields="100" StopParamMeasTime="360" StopParamParticles="5000" />

+ 1 - 1
Bin/x64/Debug/Resources/XMLData/ResourceForMeasureSourceGrid-EN.xml

@@ -32,7 +32,7 @@
 		</collection>
 
 		<collection RegName="ResGrp" grpKey="2" text="ImageProcess" description="">
-            <member itemKey="20026" itemName="" itemText="ImageProcessType" comboContent="Manual Mode,Auto Mode,Matrix" description=""/>		
+            <member itemKey="20026" itemName="" itemText="ImageProcessType" comboContent="Manual Mode,Auto Mode,Matrix,Watershed" description=""/>		
 			<member itemKey="20027" itemName="" itemText="Auto Mode" comboContent="Middle,Downward,Upward" description=""/>
 			<member itemKey="20028" itemName="" itemText="Manual Mode" description=""/>			
 			

+ 1 - 1
Bin/x64/Debug/Resources/XMLData/ResourceForMeasureSourceGrid-ZH.xml

@@ -32,7 +32,7 @@
 		</collection>
 
 		<collection RegName="ResGrp" grpKey="2" text="图像处理参数" description="">
-            <member itemKey="20026" itemName="" itemText="图像处理方式" comboContent="自动方式,手动方式,阵列" description=""/>		
+            <member itemKey="20026" itemName="" itemText="图像处理方式" comboContent="自动方式,手动方式,阵列,分水岭" description=""/>		
 			<member itemKey="20027" itemName="" itemText="自动方式" comboContent="取中,向下,向上" description=""/>
 			<member itemKey="20028" itemName="" itemText="手动方式" description=""/>		
 			<member itemKey="20022" itemName="" itemText="背景灰度最小值" description="输入背景灰度最小值(0~255)。"/>

+ 7 - 3
OTSCPP/OTSClrInterface/ImageProClr/ImageProForClr.cpp

@@ -19,6 +19,10 @@ namespace OTSCLRINTERFACE
 		{
 			 ret = imgProEngine->SplitFieldImageIntoMatricsParticle(bseImg->GetBSEImgPtr(), a_PixelSize, fieldData->GetOTSFieldDataPtr());
 		}
+		else if (param->GetBGRemoveType() == OTS_BGREMOVE_TYPE::WaterShed)
+		{
+			ret = imgProEngine->SplitRawImageIntoParticlesByWaterShed(bseImg->GetBSEImgPtr(), a_PixelSize, fieldData->GetOTSFieldDataPtr());
+		}
 		else
 		{
 			 ret = imgProEngine->RemoveBGByCVconnectivities(bseImg->GetBSEImgPtr(), a_PixelSize, fieldData->GetOTSFieldDataPtr());
@@ -63,11 +67,11 @@ namespace OTSCLRINTERFACE
 
 		return ret;
 	}
-	void ImageProForClr::RemoveBackGround(CBSEImgClr^ a_pImgIn, COTSImgProcPrmClr^ a_pImageProcessParam, CBSEImgClr^ a_pImgOut/*, long% foundedPixelNum*/)
+	void ImageProForClr::ExecuteBinaryProcess(CBSEImgClr^ a_pImgIn, COTSImgProcPrmClr^ a_pImageProcessParam, CBSEImgClr^ a_pImgOut/*, long% foundedPixelNum*/)
 	{
 		// the background  pixel will be 0,and the other part will be 255.
 		//long num = 0;
-		imgProEngine->RemoveBackGround(a_pImgIn->GetBSEImgPtr(), a_pImageProcessParam->GetImgPrcPrmPtr(), a_pImgOut->GetBSEImgPtr()/*, num*/);
+		imgProEngine->BinaryProcess(a_pImgIn->GetBSEImgPtr(), a_pImageProcessParam->GetImgPrcPrmPtr(), a_pImgOut->GetBSEImgPtr()/*, num*/);
 		//foundedPixelNum = num;
 		return;
 	}
@@ -75,7 +79,7 @@ namespace OTSCLRINTERFACE
 	{
 
 		long num = 0;
-		imgProEngine->GetSpecialGrayRangeImage(a_pImgIn->GetBSEImgPtr(), a_SpecialGrayRange->GetCIntRangePtr(), a_pBinImgOut->GetBSEImgPtr(), num);
+		imgProEngine->GetSpecialGrayRangeImage(a_pImgIn->GetBSEImgPtr(), *a_SpecialGrayRange->GetCIntRangePtr(), a_pBinImgOut->GetBSEImgPtr(), num);
 		foundedPixelNum = num;
 	}
 

+ 1 - 1
OTSCPP/OTSClrInterface/ImageProClr/ImageProForClr.h

@@ -23,7 +23,7 @@ namespace OTSCLRINTERFACE
 
 			BOOL MergeBigBoundaryParticles(System::Collections::Generic::List<COTSFieldDataClr^>^ allFields, double pixelSize, int scanFieldSize, Size ResolutionSize, System::Collections::Generic::List<COTSParticleClr^>^ mergedParts);
 
-			void RemoveBackGround(CBSEImgClr^ a_pImgIn, COTSImgProcPrmClr^ a_pImageProcessParam, CBSEImgClr^ a_pImgOut/*, long% foundedPixelNum*/);
+			void ExecuteBinaryProcess(CBSEImgClr^ a_pImgIn, COTSImgProcPrmClr^ a_pImageProcessParam, CBSEImgClr^ a_pImgOut/*, long% foundedPixelNum*/);
 		  
 		    void GetSpecialGrayRangeImage(CBSEImgClr^ a_pImgIn, CIntRangeClr^ a_SpecialGrayRange, CBSEImgClr^ a_pBinImgOut, long% foundedPixelNum);
 	private:

+ 4 - 0
OTSCPP/OTSData/OTSFeature.cpp

@@ -121,7 +121,11 @@ namespace OTSDATA {
 			m_listSegments.push_back(pSegment);
 		}
 	}
+	void COTSFeature::AddSegment(COTSSegmentPtr seg)
+	{
+		m_listSegments.push_back(seg);
 
+	}
 	COTSSegmentPtr COTSFeature::GetSegmentByIndex(int a_nIndex)
 	{
 		if (a_nIndex < 0 || a_nIndex >= (int)m_listSegments.size())

+ 1 - 1
OTSCPP/OTSData/OTSFeature.h

@@ -27,7 +27,7 @@ namespace OTSDATA {
 		COTSSegmentsList& GetSegmentsList() { return m_listSegments; }
 		void SetSegmentsList(COTSSegmentsList& a_plistSegment, BOOL a_bClear = TRUE);
 		COTSSegmentPtr GetSegmentByIndex(int a_nIndex);				
-
+		void AddSegment(COTSSegmentPtr seg);
 	protected:
 
 		// cleanup

+ 16 - 0
OTSCPP/OTSData/OTSParticle.cpp

@@ -534,6 +534,22 @@ namespace OTSDATA {
 
 	}
 
+	BOOL COTSParticle::IfContain(CPoint pos)
+	{
+		CRect rec = m_rectParticle;
+		if (pos.x<rec.left || pos.x>rec.right) return false;
+		if (pos.y<rec.top || pos.y>rec.bottom) return false;
+		auto segs = m_pFeature->GetSegmentsList();
+		for (auto seg : segs)
+		{
+			if (pos.x >= seg->GetStart() && pos.x <= seg->GetEnd() && pos.y == seg->GetHeight())
+			{
+				return true;
+			}
+		}
+		return false;
+	}
+
 	// cleanup
 	void COTSParticle::Cleanup()
 	{		

+ 1 - 1
OTSCPP/OTSData/OTSParticle.h

@@ -192,7 +192,7 @@ const double Pi = 3.14159;
 	
 
 		BOOL IsConnected(COTSParticle* a_p, int fldwidth, int fldheight, int direction);
-
+		BOOL IfContain(CPoint pos);//determine if the point is in the region of this particle.
 	    
 		int GetGroupId() { return (int)m_grpId; }
 		void SetGroupId(int a_grpId) { m_grpId = (IDENTIFIED_INC_GRP_ID)a_grpId; }

+ 2 - 1
OTSCPP/OTSData/otsdataconst.h

@@ -135,7 +135,8 @@ namespace OTSDATA
 		AUTO= 0,
 		MANUAL = 1,		
 		Matrics=2,
-		MAX = 2
+		WaterShed = 3,
+		MAX = 3
 	} OTS_BGREMOVE_TYPE;
 	typedef enum class __declspec(dllexport) OTS_AUTOBGREMOVE_TYPE
 	{

+ 132 - 0
OTSCPP/OTSImagePro/GreyPeak.cpp

@@ -0,0 +1,132 @@
+#include "stdafx.h"
+#include "GreyPeak.h"
+namespace OTSIMGPROC
+{
+		
+
+		BOOL MyGreyPeak::MergeGreyPeaks(MyGreyPeak* firstRng)
+		{
+
+			auto curRange = firstRng;
+
+			while (curRange != NULL)
+			{
+				int pt = curRange->GetPeakType();
+
+				if (pt == GrayPeakType::normalPeak)//normal peak
+				{
+					curRange = curRange->nextRng;
+					continue;
+				}
+
+				auto preRng = curRange->preRng;
+				auto nextRng = curRange->nextRng;
+
+
+				if (pt == GrayPeakType::leftBias)//left bias
+				{
+					if (preRng != NULL)
+					{
+						int curPeak = curRange->peakValue;
+						int prePeak = preRng->peakValue;
+
+						if (prePeak > curPeak)
+						{
+							preRng->MergePeak(curRange);
+							curRange = preRng;
+							continue;
+						}
+
+					}
+
+				}
+				else if (pt == GrayPeakType::rightBias)//right bias
+				{
+
+					if (nextRng != NULL)
+					{
+						int curPeak = curRange->peakValue;
+
+						int nextPeak = nextRng->peakValue;
+
+						if (nextPeak > curPeak)
+						{
+							if (curRange->preRng == NULL)
+							{
+								firstRng = nextRng;
+							}
+							nextRng->MergePeak(curRange);
+
+							curRange = nextRng;
+							continue;
+						}
+
+					}
+
+				}
+				else if (pt == GrayPeakType::smallPeak)
+				{
+
+					if (preRng != NULL && nextRng != NULL)
+					{
+						int curPeak = curRange->peakValue;
+						int prePeak = preRng->peakValue;
+						int nextPeak = nextRng->peakValue;
+
+						if (prePeak > curPeak && nextPeak > curPeak)
+						{
+							if (preRng->peakValue >= nextRng->peakValue)
+							{
+								preRng->MergePeak(curRange);
+								curRange = preRng;
+								continue;
+							}
+							else
+							{
+								nextRng->MergePeak(curRange);
+								curRange = nextRng;
+								continue;
+							}
+						}
+						else if (prePeak > curPeak && nextPeak < curPeak)
+						{
+							preRng->MergePeak(curRange);
+							curRange = preRng;
+							continue;
+						}
+						else if (nextPeak > curPeak && prePeak < curPeak)
+						{
+							nextRng->MergePeak(curRange);
+							curRange = nextRng;
+							continue;
+						}
+
+					}
+					else if (preRng != NULL && nextRng == NULL)
+					{
+
+						preRng->MergePeak(curRange);
+						curRange = preRng;
+						continue;
+
+
+					}
+					else if (preRng == NULL && nextRng != NULL)
+					{
+						nextRng->MergePeak(curRange);
+						firstRng = nextRng;
+						curRange = nextRng;
+						continue;
+					}
+
+
+
+				}
+
+				curRange = curRange->nextRng;
+
+			}
+			return true;
+		}
+
+}

+ 129 - 0
OTSCPP/OTSImagePro/GreyPeak.h

@@ -0,0 +1,129 @@
+#pragma once
+#include "afx.h"
+namespace OTSIMGPROC 
+{
+	enum GrayPeakType
+	{
+		leftBias = 1,
+		peakInMiddle=2,
+		rightBias=3,
+		normalPeak=4,
+		smallPeak=5
+
+	};
+	class MyGreyPeak
+	{
+
+	public:
+		int start;
+		int end;
+		int peakPos;
+		int peakValue;
+		int valleyValue;
+		int allNoneZeroGreyLevelNum;//valid grey level number
+		int maxPeakvalue;//max peak of all the peak
+		long area;
+		MyGreyPeak* nextRng;
+		MyGreyPeak* preRng;
+		int GetSpan()
+		{
+			return end - start;
+		}
+		int GetDvalue()
+		{
+			return peakValue - valleyValue;
+		}
+		GrayPeakType GetPeakType()
+		{
+			GrayPeakType peakType;//1:left bias 2:peak in middle 3:right bias.4:big peak,5:small peak
+			double leftBias = peakPos - start;
+			double rightBias = end - peakPos;
+			double proportion = leftBias / rightBias;
+			double dvalue = (double)GetDvalue();
+			double span = (double)GetSpan();
+			double spanProportion = span / allNoneZeroGreyLevelNum;
+			double dpeak = peakValue;
+			double peakProportion = dpeak / maxPeakvalue;
+			double dvalueProportion = dvalue / maxPeakvalue;
+			if (nextRng == NULL)
+			{
+				 peakType=GrayPeakType::normalPeak;
+			}
+
+			if (peakProportion < 0.1 && spanProportion < 0.05)
+			{
+				peakType = GrayPeakType::smallPeak;
+			}
+
+
+			if (proportion > 0.66 && rightBias <= 1)
+			{
+				peakType =GrayPeakType::rightBias;
+			}
+			else if (proportion < 0.33 && leftBias <= 1)
+			{
+				peakType = GrayPeakType::leftBias;
+			}
+			else
+			{
+				peakType = GrayPeakType::peakInMiddle;
+
+
+			}
+			if (dvalueProportion >= 0.1 && peakType == 2)
+			{
+				peakType=GrayPeakType::normalPeak;
+			}
+			if (spanProportion >= 0.1 && peakType == 2)
+			{
+				peakType=GrayPeakType::normalPeak;
+			}
+			return peakType;
+
+
+		}
+		void MergePeak(MyGreyPeak* curRange)//merge the invalid range into adjacent range.
+		{
+			area += curRange->area;
+			if (curRange->peakValue > peakValue)
+			{
+				peakValue = curRange->peakValue;
+				peakPos = curRange->peakPos;
+
+			}
+			if (curRange->valleyValue < valleyValue)
+			{
+				valleyValue = curRange->valleyValue;
+			}
+			if (curRange->end > end)//curRange is on the right of this range.
+			{
+				end = curRange->end;
+				nextRng = curRange->nextRng;
+				if (nextRng != NULL)
+				{
+					nextRng->preRng = this;
+				}
+
+				delete curRange;
+
+			}
+			else//curRange is on the left of this range.
+			{
+				start = curRange->start;
+				preRng = curRange->preRng;
+				if (preRng != NULL)
+				{
+					preRng->nextRng = curRange->nextRng;
+				}
+
+				delete  curRange;
+			}
+
+
+		}
+
+		static BOOL MergeGreyPeaks(MyGreyPeak* firstRng);
+
+	};
+	
+}

+ 2 - 0
OTSCPP/OTSImagePro/OTSImagePro.vcxproj

@@ -1053,6 +1053,7 @@
       <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='CleannessRelease|Win32'">false</CompileAsManaged>
       <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='LithiumCleanness|Win32'">false</CompileAsManaged>
     </ClCompile>
+    <ClCompile Include="GreyPeak.cpp" />
     <ClCompile Include="ImageProDll.cpp">
       <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</CompileAsManaged>
       <CompileAsManaged Condition="'$(Configuration)|$(Platform)'=='Release_oxford50|Win32'">false</CompileAsManaged>
@@ -1109,6 +1110,7 @@
     <ClInclude Include="BaseFunction.h" />
     <ClInclude Include="FieldMgr.h" />
     <ClInclude Include="GBImgPropCal.h" />
+    <ClInclude Include="GreyPeak.h" />
     <ClInclude Include="ImageProDll.h" />
     <ClInclude Include="OTSImageProcess.h" />
     <ClInclude Include="OTSImageProcessParam.h" />

+ 2 - 0
OTSCPP/OTSImagePro/OTSImagePro.vcxproj.filters

@@ -10,6 +10,7 @@
     <ClCompile Include="OTSMorphology.cpp" />
     <ClCompile Include="OTSImageProcess.cpp" />
     <ClCompile Include="BaseFunction.cpp" />
+    <ClCompile Include="GreyPeak.cpp" />
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="GBImgPropCal.h" />
@@ -23,6 +24,7 @@
     <ClInclude Include="OTSMorphology.h" />
     <ClInclude Include="OTSImageProcess.h" />
     <ClInclude Include="BaseFunction.h" />
+    <ClInclude Include="GreyPeak.h" />
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="ImageProDll.rc" />

+ 633 - 14
OTSCPP/OTSImagePro/OTSImageProcess.cpp

@@ -10,6 +10,7 @@
 #include "../OTSLog/COTSUtilityDllFunExport.h"
 #include "FieldMgr.h"
 #include "BaseFunction.h"
+#include "GreyPeak.h"
 
 
 namespace OTSIMGPROC
@@ -18,6 +19,45 @@ namespace OTSIMGPROC
 	using namespace std;
 
 	const int nBlackColor = 255;
+	namespace
+	{
+	
+		cv::Mat GetMatDataFromParticles(COTSParticleList parts, int width, int height)
+		{
+			int rows, cols;
+			cols = width;
+			rows = height;
+			BYTE* pPixel = new BYTE[width * height];
+			Mat cvcopyImg = Mat(rows, cols, CV_8UC1, pPixel);
+			cvcopyImg = Scalar::all(0);
+			for (auto p : parts)
+			{
+				auto area = p->GetPixelArea();
+				if (area > 100)
+				{
+					auto fea = p->GetFeature();
+					auto segs = fea->GetSegmentsList();
+					for (auto seg : segs)
+					{
+						auto row = seg->GetHeight();
+						for (int i = 0; i < seg->GetLength(); i++)
+						{
+							auto col = seg->GetStart() + i;
+							cvcopyImg.at<char>(row, col) = 255;
+						}
+
+					}
+			    }
+			}
+
+
+
+			return cvcopyImg;
+		}
+	
+	
+	}
+	
 
 	
 
@@ -57,7 +97,7 @@ namespace OTSIMGPROC
 		CRect r = CRect(0, 0, nWidthImg, nHeightImg);
 		CBSEImgPtr imgNoBGBinary = CBSEImgPtr(new CBSEImg(r));
 		
-		RemoveBackGround(inBSEImg, m_imageProcessParam, imgNoBGBinary/*, nNumParticle*/);
+		BinaryProcess(inBSEImg, m_imageProcessParam, imgNoBGBinary/*, nNumParticle*/);
 
 
 
@@ -240,7 +280,7 @@ namespace OTSIMGPROC
 		
 		long nNumParticle = 0;
 
-		GetSpecialGrayRangeImage(a_pBSEImg, a_grayRange, imgNoBGBinary, nNumParticle);
+		GetSpecialGrayRangeImage(a_pBSEImg, *a_grayRange, imgNoBGBinary, nNumParticle);
 
 
 
@@ -490,6 +530,185 @@ namespace OTSIMGPROC
 		//-----------
 	}
 	
+	BOOL COTSImageProcess::SplitRawImageIntoParticlesByWaterShed(CBSEImgPtr fieldImg, double a_PixelSize, COTSFieldDataPtr outFldData)
+	{
+		int nWidthImg = fieldImg->GetWidth();
+		int nHeightImg = fieldImg->GetHeight();
+		outFldData->Width = nWidthImg;
+		outFldData->Height = nHeightImg;
+
+		CRect r = CRect(0, 0, nWidthImg, nHeightImg);
+		CBSEImgPtr imgNoBGBinary = CBSEImgPtr(new CBSEImg(r));
+		
+		COTSParticleList listMainParticle;
+		BinaryProcess(fieldImg, m_imageProcessParam, imgNoBGBinary);
+
+		
+		CDoubleRange areaRng = m_imageProcessParam->GetIncArea();
+		GetParticlesFromBinaryImage(imgNoBGBinary, areaRng, a_PixelSize, listMainParticle);
+
+		outFldData->SetParticleList(listMainParticle);
+		
+
+		
+		CBSEImgPtr noBgImg = CBSEImgPtr(new CBSEImg(fieldImg->GetImageRect()));
+		RemoveBackGround(fieldImg, noBgImg);
+
+		BlurImage(noBgImg);
+
+		std::vector<CPoint> seeds;
+		seeds.clear();
+		FindSeedsByGrayScale(noBgImg, a_PixelSize, seeds);
+
+		Mat matImg = GetMatDataFromBseImg(noBgImg);
+
+		Mat marks(matImg.size(), CV_32S);
+
+		marks = Scalar::all(0);
+
+		for (int index = 0; index < seeds.size(); index++)
+		{
+
+			auto p = seeds[index];
+
+			marks.at<INT32>(p.y, p.x) = index + 10;
+
+		}
+
+		Mat imageGray3;
+
+	
+		cv::cvtColor(matImg, imageGray3, cv::COLOR_GRAY2RGB);//灰度转换 opencv4
+		cv::watershed(imageGray3, marks);
+
+
+		auto matBinNobg = GetMatDataFromParticles(listMainParticle, nWidthImg, nHeightImg);
+
+		//the first "long" is the index of particle,the second "long" is the row number of the segment, the third "long" is the sequence of the pixel.
+		std::map<long, std::map<long, std::set<long>>> pixelMap;
+
+		for (int i = 0; i < marks.rows; i++)
+		{
+			for (int j = 0; j < marks.cols; j++)
+			{
+				if (matBinNobg.at<char>(i, j) == 0)
+				{
+					marks.at<int>(i, j) = 0;
+					continue;
+				}
+
+				long index = marks.at<int>(i, j);
+
+				if (index == -1)//if this pixel is on the border,then it will be absorbed by it's neighbor.
+				{
+					if (i + 1 < marks.rows && marks.at<int>(i + 1, j) != -1 && matBinNobg.at<char>(i + 1, j) != 0)
+					{
+						index = marks.at<int>(i + 1, j);
+					}
+					else if (j + 1 < marks.cols && marks.at<int>(i, j + 1) != -1 && matBinNobg.at<char>(i, j + 1) != 0)
+					{
+						index = marks.at<int>(i, j + 1);
+					}
+					else if (i > 0 && marks.at<int>(i - 1, j) != -1 && matBinNobg.at<char>(i - 1, j) != 0)
+					{
+						index = marks.at<int>(i - 1, j);
+					}
+					else if (j > 0 && marks.at<int>(i, j - 1) != -1 && matBinNobg.at<char>(i, j - 1) != 0)
+					{
+						index = marks.at<int>(i, j - 1);
+					}
+					marks.at<int>(i, j) = index;
+				}
+
+				pixelMap[index][i].insert(j);
+
+			}
+		}
+
+		COTSParticleList listParticleOut;
+		for (auto it = pixelMap.begin(); it != pixelMap.end(); it++)
+		{
+			if (it->first == -1) continue;
+			if (it->first == 0) continue;
+			auto pixelsegs = it->second;
+			COTSParticlePtr newGrain = COTSParticlePtr(new COTSParticle());
+			COTSFeaturePtr newFea = COTSFeaturePtr(new COTSFeature());
+			for (auto pixelseg : pixelsegs)
+			{
+				auto start = (*pixelseg.second.begin());
+				for (auto pix = pixelseg.second.begin(); pix != pixelseg.second.end(); pix++)
+				{
+					auto curNode = pix;
+					++curNode;
+					if ((curNode) != pixelseg.second.end())
+					{
+						if (*curNode - *pix > 1)
+						{
+							COTSSegmentPtr  seg = COTSSegmentPtr(new COTSSegment());
+
+							seg->SetStart(start);
+							seg->SetEnd(*pix);
+							seg->SetHeight(pixelseg.first);
+							newFea->AddSegment(seg);
+
+							start = *curNode;
+						}
+					}
+					else
+					{
+						COTSSegmentPtr  seg = COTSSegmentPtr(new COTSSegment());
+
+						seg->SetStart(start);
+						seg->SetEnd(*pix);
+						seg->SetHeight(pixelseg.first);
+						newFea->AddSegment(seg);
+					}
+
+				}
+
+			}
+			newGrain->SetFeature(newFea);
+
+
+			newGrain->CalXRayPos();
+
+			CPoint pos = newGrain->GetXRayPos();
+
+			for (auto mp : listMainParticle)
+			{
+			
+				auto fieldOTSRect = outFldData->GetOTSRect();
+				CPoint leftTop = fieldOTSRect.GetTopLeft();
+
+				CRect rectInSinglefld = mp->GetParticleRect();
+				CPoint OTSLeftTop = CPoint(leftTop.x + rectInSinglefld.left * a_PixelSize, leftTop.y - rectInSinglefld.top * a_PixelSize);
+				CPoint OTSRightBottom = CPoint(leftTop.x + rectInSinglefld.right * a_PixelSize, leftTop.y - rectInSinglefld.bottom * a_PixelSize);
+
+				COTSRect recInOTSCord = COTSRect(OTSLeftTop, OTSRightBottom);
+				mp->SetOTSRect(recInOTSCord);
+				mp->SetFieldId(outFldData->GetId());
+				if (mp->IfContain(pos))
+				{
+					CRect rectInSinglefld = newGrain->GetParticleRect();
+					CPoint OTSLeftTop = CPoint(leftTop.x + rectInSinglefld.left * a_PixelSize, leftTop.y - rectInSinglefld.top * a_PixelSize);
+					CPoint OTSRightBottom = CPoint(leftTop.x + rectInSinglefld.right * a_PixelSize, leftTop.y - rectInSinglefld.bottom * a_PixelSize);
+
+					COTSRect recInOTSCord = COTSRect(OTSLeftTop, OTSRightBottom);
+					newGrain->SetFieldId(mp->GetFieldId());
+					newGrain->SetOTSRect(recInOTSCord);
+					mp->AddSubParticle(newGrain);
+					break;
+				}
+
+			}
+
+
+
+		}
+
+		return true;
+	}
+	
 	CIntRangePtr COTSImageProcess::CalBackground(CBSEImgPtr m_pBSEImg)
 	{
 		auto ranges = CalcuGrayLevelRange(m_pBSEImg);
@@ -600,7 +819,7 @@ namespace OTSIMGPROC
 		return ranges;
 	
 	}
-	void COTSImageProcess::GetSpecialGrayRangeImage(CBSEImgPtr a_pImgIn, CIntRangePtr a_SpecialGrayRange, CBSEImgPtr a_pBinImgOut, long& foundedPixelNum)
+	void COTSImageProcess::GetSpecialGrayRangeImage(CBSEImgPtr a_pImgIn, CIntRange a_SpecialGrayRange, CBSEImgPtr a_pBinImgOut, long& foundedPixelNum)
 	{
 		// the background  pixel will be 0,and the other part will be 255.
 		ASSERT(a_pImgIn);
@@ -626,8 +845,8 @@ namespace OTSIMGPROC
 	
 		long nNumParticle = 0;
 	
-			nBGStart = a_SpecialGrayRange->GetStart();
-			nBGEnd = a_SpecialGrayRange->GetEnd();
+			nBGStart = a_SpecialGrayRange.GetStart();
+			nBGEnd = a_SpecialGrayRange.GetEnd();
 			
 
 			// delete background 
@@ -658,7 +877,7 @@ namespace OTSIMGPROC
 
 		return;
 	}
-	void COTSImageProcess::RemoveBackGround(CBSEImgPtr a_pImgIn, COTSImageProcessParamPtr a_pImageProcessParam, CBSEImgPtr a_pBinImgOut/*,long& foundedPixelNum*/)
+	void COTSImageProcess::BinaryProcess(CBSEImgPtr a_pImgIn, COTSImageProcessParamPtr a_pImageProcessParam, CBSEImgPtr a_pBinImgOut/*,long& foundedPixelNum*/)
 	{
 		// the background  pixel will be 0,and the other part will be 255.
 		ASSERT(a_pImgIn);
@@ -685,7 +904,7 @@ namespace OTSIMGPROC
 		long nPartStart;
 		long nPartEnd;
 		long nNumParticle = 0;
-		if (a_pImageProcessParam->GetBGRemoveType() == OTS_BGREMOVE_TYPE::MANUAL)
+		if (a_pImageProcessParam->GetBGRemoveType() == OTS_BGREMOVE_TYPE::MANUAL || a_pImageProcessParam->GetBGRemoveType() == OTS_BGREMOVE_TYPE::WaterShed)
 		{
 			nBGStart = a_pImageProcessParam->GetBGGray().GetStart();
 			nBGEnd = a_pImageProcessParam->GetBGGray().GetEnd();
@@ -706,11 +925,7 @@ namespace OTSIMGPROC
 		else
 		{
 		
-			/*auto range = CalBackground(a_pImgIn);
-			nBGStart = range->GetStart();
-
-			nBGEnd = range->GetEnd();*/
-
+		
 
 			switch (a_pImageProcessParam->GetAutoBGRemoveType())
 			{
@@ -741,12 +956,78 @@ namespace OTSIMGPROC
 		}
 		a_pBinImgOut->SetImageData(pPixel,nWidthImg,nHeightImg);
 		
-		//foundedPixelNum = nNumParticle;
-		//foundedPixelNum = 100;
+		
 		
 		
 		return ;
 	}
+	void COTSImageProcess::RemoveBackGround(CBSEImgPtr a_pImgIn,  CBSEImgPtr a_pBinImgOut)
+	{
+		// the background  pixel will be 0,and the other part will be 255.
+		ASSERT(a_pImgIn);
+
+
+		ASSERT(m_imageProcessParam);
+		int nWidthImg = a_pImgIn->GetWidth();
+		int nHeightImg = a_pImgIn->GetHeight();
+
+		long nImgSize = nWidthImg * nHeightImg;
+
+		BYTE* pTempImg = new BYTE[nImgSize];
+
+		BYTE* pSrcImg = a_pImgIn->GetImageDataPointer();
+
+
+		BYTE* pPixel = new byte[nImgSize];
+
+
+
+		long nBGStart;
+		long nBGEnd;
+		long nPartStart;
+		long nPartEnd;
+		long nNumParticle = 0;
+		if (m_imageProcessParam->GetBGRemoveType() == OTS_BGREMOVE_TYPE::MANUAL|| m_imageProcessParam->GetBGRemoveType() == OTS_BGREMOVE_TYPE::WaterShed)
+		{
+			nBGStart = m_imageProcessParam->GetBGGray().GetStart();
+			nBGEnd = m_imageProcessParam->GetBGGray().GetEnd();
+			nPartStart = m_imageProcessParam->GetParticleGray().GetStart();
+			nPartEnd = m_imageProcessParam->GetParticleGray().GetEnd();
+
+			// delete background 
+			for (unsigned int i = 0; i < nImgSize; i++)
+			{
+				if (pSrcImg[i] >= nBGStart && pSrcImg[i] <= nBGEnd)
+				{
+					pPixel[i] = 0;
+				}
+				else
+				{
+					
+						pPixel[i] = pSrcImg[i];
+						nNumParticle++;
+					
+
+				}
+				if (pSrcImg[i]<nPartStart || pSrcImg[i]>nPartEnd)
+				{
+					pPixel[i] = 0;
+				}
+			}
+			
+
+
+
+
+		}
+		
+		a_pBinImgOut->SetImageData(pPixel, nWidthImg, nHeightImg);
+
+		
+		delete[] pTempImg;
+
+		return;
+	}
 	BOOL COTSImageProcess::GetParticles(long left, long top, long a_nWidth, long a_nHeight, const BYTE* a_pPixel, COTSParticleList& a_listParticles)
 	{
 		ASSERT(a_pPixel);
@@ -1026,6 +1307,344 @@ namespace OTSIMGPROC
 
 		return TRUE;
 	}
+
+	BOOL COTSImageProcess::GetParticlesFromBinaryImage(CBSEImgPtr m_pBSEImg, CDoubleRange a_diameterRange, double a_pixelSize, COTSParticleList& listParticleOut)
+	{
+		int height, width;
+		height = m_pBSEImg->GetHeight();
+		width = m_pBSEImg->GetWidth();
+
+		BYTE* pPixel = m_pBSEImg->GetImageDataPointer();
+		Mat nobgMat = Mat(height, width, CV_8UC1, pPixel);
+
+
+		Mat labels = Mat::zeros(nobgMat.size(), CV_32S);
+		Mat  stats, centroids;
+		int number = connectedComponentsWithStats(nobgMat, labels, stats, centroids, 8, CV_32S);
+
+		double rStart = a_diameterRange.GetStart()/2.0;
+		double rEnd = a_diameterRange.GetEnd()/2.0;
+		double areaStart =  rStart* rStart * 3.14159;
+		double areaEnd =  rEnd* rEnd * 3.14159;
+
+		//COTSParticleList listParticleOut;
+		for (size_t i = 1; i < number; i++)
+		{
+			int center_x = centroids.at<double>(i, 0);
+			int center_y = centroids.at<double>(i, 1);
+			//矩形边框
+			int x = stats.at<int>(i, CC_STAT_LEFT);
+			int y = stats.at<int>(i, CC_STAT_TOP);
+			int w = stats.at<int>(i, CC_STAT_WIDTH);
+			int h = stats.at<int>(i, CC_STAT_HEIGHT);
+			int area = stats.at<int>(i, CC_STAT_AREA);
+
+			double actualArea = area * a_pixelSize * a_pixelSize;
+
+
+
+			if (actualArea >= areaStart && actualArea < areaEnd)
+			{
+				Rect rectMax = Rect(x, y, w, h);
+
+				Mat  rectROI = labels(rectMax).clone();
+				Mat imageROI = Mat::zeros(rectMax.size(), nobgMat.type());
+
+				//exclude the point which  intersect into this bounding box but is not in this group.
+				int label = i;
+				for (int row = 0; row < rectROI.rows; row++)
+				{
+					for (int col = 0; col < rectROI.cols; col++)
+					{
+						int v = rectROI.at<int>(row, col);
+
+						if (v == label)
+						{
+							imageROI.at<uchar>(row, col) = 255;
+						}
+
+
+					}
+
+				}
+
+				COTSParticleList roiParts;
+				if (!GetOneParticleFromROI(rectMax.x, rectMax.y, rectMax.width, rectMax.height, imageROI.data, roiParts))
+				{
+					continue;
+				}
+
+				if (roiParts.size() > 0)
+				{
+					COTSParticlePtr roiPart = roiParts[0];
+					roiPart->SetXRayPos(CPoint(center_x, center_y));
+					CRect r = CRect(x, y, x + w, y + h);
+					roiPart->SetParticleRect(r);
+					roiPart->SetActualArea(actualArea);
+					roiPart->SetPixelArea(area);
+					listParticleOut.push_back(roiPart);
+
+				}
+
+
+
+			}
+
+
+		}
+
+		return TRUE;
+	}
+	void  COTSImageProcess::findPeakAndValley(const vector<int>& v, vector<int>& peakPositions, vector<int>& valleyPositions)
+	{
+		vector<int> diff_v(v.size() - 1, 0);
+		// 计算V的一阶差分和符号函数trend
+		for (vector<int>::size_type i = 0; i != diff_v.size(); i++)
+		{
+			if (v[i + 1] - v[i] > 0)
+				diff_v[i] = 1;
+			else if (v[i + 1] - v[i] < 0)
+				diff_v[i] = -1;
+			else
+				diff_v[i] = 0;
+		}
+		// 对Trend作了一个遍历
+		for (int i = diff_v.size() - 1; i >= 0; i--)
+		{
+			if (diff_v[i] == 0 && i == diff_v.size() - 1)
+			{
+				diff_v[i] = 1;
+			}
+			else if (diff_v[i] == 0)
+			{
+				if (diff_v[i + 1] >= 0)
+					diff_v[i] = 1;
+				else
+					diff_v[i] = -1;
+			}
+		}
+
+		for (vector<int>::size_type i = 0; i != diff_v.size() - 1; i++)
+		{
+			if (diff_v[i + 1] - diff_v[i] == -2)
+				peakPositions.push_back(i + 1);
+			if (diff_v[i + 1] - diff_v[i] == 2)
+				valleyPositions.push_back(i + 1);
+		}
+	}
+	std::vector<CIntRange> COTSImageProcess::GetValidGreyLevelRanges(CBSEImgPtr pBSEImg)
+	{
+
+
+		WORD originChartData[MAXBYTE];
+
+
+		//1. get chart data
+		pBSEImg->SetChartData();
+
+		memcpy(originChartData, pBSEImg->GetBSEChart(), sizeof(WORD) * MAXBYTE);
+		originChartData[0] = 0;
+
+		std::vector<int> greyChart;
+		for (int i = 0; i < MAXBYTE; i++)
+		{
+			greyChart.push_back((int)originChartData[i]);
+		}
+		std::vector<int> peaks;
+		std::vector<int> valleys;
+		findPeakAndValley(greyChart, peaks, valleys);
+
+		if ((peaks.size() - valleys.size()) == 1)
+		{
+			valleys.push_back(254);
+		}
+
+
+
+
+		std::map<int, MyGreyPeak*> peakMap;// hold all the peaks in this spectrum which are sorted by there area.
+
+		MyGreyPeak* lastRng = NULL;
+		MyGreyPeak* firstRng = NULL;
+
+		for (int i = 0; i < peaks.size(); i++)
+		{
+			MyGreyPeak* gr = new MyGreyPeak();
+			if (i == 0)
+			{
+				gr->start = 0;
+			}
+			else
+			{
+				gr->start = valleys[i - 1];
+			}
+
+			gr->end = valleys[i];
+			for (int j = gr->start; j < gr->end; j++)
+			{
+				gr->area += originChartData[j];
+			}
+
+			gr->peakPos = peaks[i];
+			gr->peakValue = originChartData[peaks[i]];
+			gr->valleyValue = valleys[i];
+			if (firstRng == NULL)
+			{
+				firstRng = gr;
+				lastRng = gr;
+			}
+			else
+			{
+				gr->preRng = lastRng;
+				lastRng->nextRng = gr;
+			}
+
+			lastRng = gr;
+
+			peakMap[gr->start] = gr;
+
+		}
+		int validGreyLevelNum = 0;//statistic the none zero grey level number
+		long partArea = 0;
+		for (int i = 0; i < 255; i++)
+		{
+			if (originChartData[i] != 0)
+			{
+				validGreyLevelNum += 1;
+				partArea += originChartData[i];
+			}
+		}
+
+
+		auto curRange = firstRng;
+		int maxPeakValue = curRange->peakValue;
+		while (curRange != NULL)
+		{
+			if (curRange->peakValue > maxPeakValue)
+			{
+				maxPeakValue = curRange->peakValue;
+			}
+			curRange = curRange->nextRng;
+		}
+		curRange = firstRng;
+		while (curRange != NULL)
+		{
+			curRange->maxPeakvalue = maxPeakValue;
+			curRange->allNoneZeroGreyLevelNum = validGreyLevelNum;
+			curRange = curRange->nextRng;
+		}
+
+
+		MyGreyPeak::MergeGreyPeaks(firstRng);
+
+		std::vector<CIntRange> ranges;
+		auto curRange1 = firstRng;
+		while (curRange1 != NULL)
+		{
+
+			CIntRange pRange;
+			pRange.SetStart(curRange1->start);
+			pRange.SetEnd(curRange1->end);
+			ranges.push_back(pRange);
+			curRange1 = curRange1->nextRng;
+		}
+
+		return ranges;
+
+	}
+	BOOL COTSImageProcess::FindSeedsByGrayScale(CBSEImgPtr fieldImg, double a_PixelSize, std::vector<CPoint>& OutSeeds)
+	{
+		ASSERT(fieldImg);
+
+
+		ASSERT(m_imageProcessParam);
+		int nWidthImg = fieldImg->GetWidth();
+		int nHeightImg = fieldImg->GetHeight();
+
+		long nImgSize = nWidthImg * nHeightImg;
+
+		std::vector<CIntRange> validPeaks = GetValidGreyLevelRanges(fieldImg);
+
+
+
+		CRect r = CRect(0, 0, nWidthImg, nHeightImg);
+
+		CBSEImgPtr imgNoBGBinary = CBSEImgPtr(new CBSEImg(r));
+
+		for (int i = 0; i < validPeaks.size(); i++)
+		{
+			CIntRange pRange = validPeaks[i];
+			if (pRange.GetStart() == 0)//prevent the 0 grey pixels being recognized as particle.
+			{
+				pRange.SetStart(3);
+			}
+
+
+
+			long nNumParticle = 0;
+
+			GetSpecialGrayRangeImage(fieldImg, pRange, imgNoBGBinary, nNumParticle);
+
+
+
+			if (nNumParticle == 0)
+			{
+
+				continue;
+
+
+			}
+			else
+			{
+
+				// get the area image
+
+
+				Mat matImg = GetMatDataFromBseImg(imgNoBGBinary);
+				Mat labels = Mat::zeros(matImg.size(), CV_32S);
+				Mat  stats, centroids;
+				int number = connectedComponentsWithStats(matImg, labels, stats, centroids, 8, CV_32S);
+				auto incsize = m_imageProcessParam->GetIncArea();
+				double rStart = incsize.GetStart() / 2.0;
+				double rEnd = incsize.GetEnd() / 2.0;
+				double pixelarea = a_PixelSize * a_PixelSize;
+				double areaStart = rStart* rStart * 3.14159*pixelarea;
+				double areaEnd =  rEnd* rEnd * 3.14159*pixelarea;
+				/*double areaStart = 0;
+				double areaEnd = 1000;*/
+
+
+				for (size_t i = 1; i < number; i++)
+				{
+					int center_x = centroids.at<double>(i, 0);
+					int center_y = centroids.at<double>(i, 1);
+
+					int area = stats.at<int>(i, CC_STAT_AREA);
+
+					double actualArea = area * a_PixelSize * a_PixelSize;
+
+
+
+					if (actualArea >= areaStart && actualArea < areaEnd)
+					{
+
+
+						CPoint seed = CPoint(center_x, center_y);
+						OutSeeds.push_back(seed);
+					}
+				}
+
+
+
+			}
+
+		}
+
+
+
+
+		return true;
+	}
 	
 	 BOOL COTSImageProcess::CalcuParticleImagePropertes(COTSParticlePtr a_pOTSPart, double a_PixelSize)
 	{	

+ 13 - 3
OTSCPP/OTSImagePro/OTSImageProcess.h

@@ -6,7 +6,7 @@
 
 namespace OTSIMGPROC {
 	using namespace OTSDATA;
-
+	
 	class __declspec(dllexport) COTSImageProcess
 	{
 	public:
@@ -18,11 +18,14 @@ namespace OTSIMGPROC {
 
 		 BOOL GetParticlesBySpecialGrayRange(CBSEImgPtr m_pBSEImg, CIntRangePtr a_grayRange, CDoubleRangePtr a_diameterRange, double a_pixelSize, COTSFieldDataPtr m_pFieldData);
 		 BOOL SplitFieldImageIntoMatricsParticle(CBSEImgPtr fieldImg, double a_PixelSize, COTSFieldDataPtr outFldData);
+		 
+		 BOOL SplitRawImageIntoParticlesByWaterShed(CBSEImgPtr fieldImg, double a_PixelSize, COTSFieldDataPtr outFldData);
 
 		 CIntRangePtr CalBackground(CBSEImgPtr m_pBSEImg);
 		 std::vector<CIntRangePtr> CalcuGrayLevelRange(CBSEImgPtr m_pBSEImg);
-		 void GetSpecialGrayRangeImage(CBSEImgPtr a_pImgIn, CIntRangePtr a_SpecialGrayRange, CBSEImgPtr a_pBinImgOut, long& foundedPixelNum);
-		 void RemoveBackGround(CBSEImgPtr a_pImgIn, COTSImageProcessParamPtr a_pImageProcessParam, CBSEImgPtr a_pImgOut/*,long& foundedPixelNum*/);
+		 void GetSpecialGrayRangeImage(CBSEImgPtr a_pImgIn, CIntRange a_SpecialGrayRange, CBSEImgPtr a_pBinImgOut, long& foundedPixelNum);
+		 void BinaryProcess(CBSEImgPtr a_pImgIn, COTSImageProcessParamPtr a_pImageProcessParam, CBSEImgPtr a_pImgOut/*,long& foundedPixelNum*/);
+		 void RemoveBackGround(CBSEImgPtr a_pImgIn,  CBSEImgPtr a_pBinImgOut);
 		 BOOL CalcuParticleImagePropertes(COTSParticlePtr part, double a_PixelSize);	
 
 		 BOOL MergeBigBoundaryParticles(COTSFieldDataList allFields, double pixelSize, int scanFieldSize, CSize ResolutionSize, COTSParticleList& mergedParts);
@@ -33,6 +36,13 @@ namespace OTSIMGPROC {
 		 BOOL GetSegmentList(long left, long top, long a_nWidth, long a_nHeight, const BYTE* a_pPixel, COTSSegmentsList& a_listSegments);
 		 BOOL GetFeatureList(COTSSegmentsList& a_listSegments, COTSFeatureList& a_listFeatures);
 		 BOOL ChangeFeaturelist(COTSFeatureList& a_listFeatures, COTSParticleList& a_listParticle);
+		 BOOL GetParticlesFromBinaryImage(CBSEImgPtr m_pBSEImg, CDoubleRange a_diameterRange, double a_pixelSize, COTSParticleList& listParticleOut);
+
+		 void findPeakAndValley(const std::vector<int>& v, std::vector<int>& peakPositions, std::vector<int>& valleyPositions);
+		 //void findPeakAndValley(const vector<int>& v, vector<int>& peakPositions, vector<int>& valleyPositions, int minPeakDistance);
+		 std::vector<CIntRange> GetValidGreyLevelRanges(CBSEImgPtr pBSEImg);
+		 BOOL FindSeedsByGrayScale(CBSEImgPtr fieldImg, double a_PixelSize, std::vector<CPoint>& OutSeeds);
+		
 		 void ImshowImage(CBSEImgPtr img);
 		 void ImshowChartData(CBSEImgPtr img);
 		

+ 3 - 2
OTSIncAMeasureApp/0-OTSModel/OTSDataType/otsdataconst.cs

@@ -247,8 +247,9 @@ namespace OTSDataType
             //MIN = 0,
             AUTO = 0,
             MANUAL = 1,
-            MATRIX=2
-           
+            MATRIX=2,
+            WaterShed = 3
+
         }
 
         public enum OTS_AUTOBGREMOVE_TYPE

+ 11 - 16
OTSIncAMeasureApp/1-OTSMeasure/Measure/ParamData/frmReclassifyCondition.Designer.cs

@@ -28,24 +28,17 @@
         /// </summary>
         private void InitializeComponent()
         {
-            this.panelControl1 = new DevExpress.XtraEditors.PanelControl();
+         
             this.button2 = new System.Windows.Forms.Button();
             this.button1 = new System.Windows.Forms.Button();
             this.checkBox1 = new System.Windows.Forms.CheckBox();
-            ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).BeginInit();
-            this.panelControl1.SuspendLayout();
+            
+          
             this.SuspendLayout();
             // 
             // panelControl1
             // 
-            this.panelControl1.Controls.Add(this.button2);
-            this.panelControl1.Controls.Add(this.button1);
-            this.panelControl1.Controls.Add(this.checkBox1);
-            this.panelControl1.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.panelControl1.Location = new System.Drawing.Point(0, 0);
-            this.panelControl1.Name = "panelControl1";
-            this.panelControl1.Size = new System.Drawing.Size(269, 167);
-            this.panelControl1.TabIndex = 0;
+           
             // 
             // button2
             // 
@@ -84,20 +77,22 @@
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
             this.ClientSize = new System.Drawing.Size(269, 167);
-            this.Controls.Add(this.panelControl1);
+            this.Controls.Add(checkBox1);
+            this.Controls.Add(button1);
+            this.Controls.Add(button2);
             this.Name = "frmReclassifyCondition";
             this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
             this.Text = "重新分类";
-            ((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit();
-            this.panelControl1.ResumeLayout(false);
-            this.panelControl1.PerformLayout();
+            //((System.ComponentModel.ISupportInitialize)(this.panelControl1)).EndInit();
+            //this.panelControl1.ResumeLayout(false);
+            //this.panelControl1.PerformLayout();
             this.ResumeLayout(false);
 
         }
 
         #endregion
 
-        private DevExpress.XtraEditors.PanelControl panelControl1;
+     
         private System.Windows.Forms.Button button2;
         private System.Windows.Forms.Button button1;
         private System.Windows.Forms.CheckBox checkBox1;

+ 96 - 3
OTSIncAMeasureApp/3-OTSDisplaySourceGridData/OTSSampleVisualPropertyInfo.cs

@@ -1068,15 +1068,58 @@ namespace OTSMeasureApp
                                     break;
                                 case OTS_BGREMOVE_TYPE.MATRIX:
 
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.MATRIXSTEP;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.DOUBLE, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
 
-                                    
+                                    break;
+                                case OTS_BGREMOVE_TYPE.WaterShed:
+                                    // BG gray level min
 
                                     poPropItem = new CPropItem();
-                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.MATRIXSTEP;
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.BG_GRAY_MIN;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.INT, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+
+                                    // BG gray level max
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.BG_GRAY_MAX;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.INT, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+
+                                    // Eigen gray level min
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.PARTICLE_GRAY_MIN;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.INT, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+
+                                    // Eigen gray level max
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.PARTICLE_GRAY_MAX;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.INT, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+                                    // particle area min
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.PARTICLE_AREA_MIN;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.DOUBLE, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+
+                                    // particle area max
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.PARTICLE_AREA_MAX;
                                     poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.DOUBLE, false, bShow);
                                     a_listPropItems.Add(poPropItem);
 
-                                   
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.OtherSelection;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.BUTTON, true, bShow);
+                                    a_listPropItems.Add(poPropItem);
 
 
                                     break;
@@ -1569,6 +1612,56 @@ namespace OTSMeasureApp
                                     a_listPropItems.Add(poPropItem);
 
                                     break;
+                                case OTS_BGREMOVE_TYPE.WaterShed:
+
+                                    // BG gray level min
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.BG_GRAY_MIN;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.INT, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+
+                                    // BG gray level max
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.BG_GRAY_MAX;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.INT, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+                                    // Eigen gray level min
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.PARTICLE_GRAY_MIN;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.INT, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+
+                                    // Eigen gray level max
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.PARTICLE_GRAY_MAX;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.INT, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+
+                                    // particle area min
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.PARTICLE_AREA_MIN;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.DOUBLE, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+
+                                    // particle area max
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.PARTICLE_AREA_MAX;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.DOUBLE, false, bShow);
+                                    a_listPropItems.Add(poPropItem);
+
+
+
+                                    poPropItem = new CPropItem();
+                                    nItemId = OTS_SAMPLE_PROP_GRID_ITEMS.OtherSelection;
+                                    poPropItem.InitialSmplParameter(a_nId, nItemId, OTS_ITEM_TYPES.BUTTON, true, bShow);
+                                    a_listPropItems.Add(poPropItem);
+                                    break;
 
                             }
                         }

+ 7 - 7
OTSIncAMeasureApp/5-OTSMeasureStatuImageFun/OTSMeasureStatusWindow.Designer.cs

@@ -31,7 +31,7 @@
             this.components = new System.ComponentModel.Container();
             this.picBox = new System.Windows.Forms.PictureBox();
             this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components);
-            this.SampleParaLock = new System.Windows.Forms.ToolStripMenuItem();
+            this.AcquireBSEImageMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.VisualAdjustingMenu = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
             this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
@@ -72,7 +72,7 @@
             // 
             this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(24, 24);
             this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.SampleParaLock,
+            this.AcquireBSEImageMenuItem,
             this.VisualAdjustingMenu,
             this.toolStripMenuItem1,
             this.toolStripSeparator1,
@@ -91,10 +91,10 @@
             // 
             // SampleParaLock
             // 
-            this.SampleParaLock.Name = "SampleParaLock";
-            this.SampleParaLock.Size = new System.Drawing.Size(242, 22);
-            this.SampleParaLock.Text = "获取BSE图";
-            this.SampleParaLock.Click += new System.EventHandler(this.AcquireBSEImage_Click);
+            this.AcquireBSEImageMenuItem.Name = "SampleParaLock";
+            this.AcquireBSEImageMenuItem.Size = new System.Drawing.Size(242, 22);
+            this.AcquireBSEImageMenuItem.Text = "获取BSE图";
+            this.AcquireBSEImageMenuItem.Click += new System.EventHandler(this.AcquireBSEImage_Click);
             // 
             // VisualAdjustingMenu
             // 
@@ -236,7 +236,7 @@
 
         #endregion
         private System.Windows.Forms.ContextMenuStrip contextMenuStrip1;
-        private System.Windows.Forms.ToolStripMenuItem SampleParaLock;
+        private System.Windows.Forms.ToolStripMenuItem AcquireBSEImageMenuItem;
         private System.Windows.Forms.ToolStripMenuItem ToolStripMenuItem;
        
         private System.Windows.Forms.ToolStripMenuItem MenuItemLineScan;

+ 5 - 1
OTSIncAMeasureApp/5-OTSMeasureStatuImageFun/OTSMeasureStatusWindow.cs

@@ -661,7 +661,7 @@ namespace OTSMeasureApp
 
             if (bfResult)
             {
-                SampleParaLock.Enabled = true;
+                AcquireBSEImageMenuItem.Enabled = true;
                 ToolStripMenuItem.Enabled = true;
 
                 toolStripMenuItem2.Enabled = true;
@@ -693,6 +693,9 @@ namespace OTSMeasureApp
                 COTSSample WSample = m_MeasureAppForm.m_ProjRstData.GetWorkingSample();
                 COTSImageProcParam ImgProcPrm = WSample.GetMsrParams().GetImageProcessParam();
                 if (ImgProcPrm.GetBGRemoveType() == otsdataconst.OTS_BGREMOVE_TYPE.MANUAL)
+                {
+                    VisualAdjustingMenu.Enabled = true;
+                }else if (ImgProcPrm.GetBGRemoveType() == otsdataconst.OTS_BGREMOVE_TYPE.WaterShed)
                 {
                     VisualAdjustingMenu.Enabled = true;
                 }
@@ -700,6 +703,7 @@ namespace OTSMeasureApp
                 {
                     VisualAdjustingMenu.Enabled = false;
                 }
+               
             }
             else
             {

+ 0 - 5
OTSIncAMeasureApp/OTSIncAMeasureApp.csproj

@@ -214,11 +214,6 @@
     <Prefer32Bit>true</Prefer32Bit>
   </PropertyGroup>
   <ItemGroup>
-    <Reference Include="DevExpress.Data.Desktop.v24.1, Version=24.1.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
-    <Reference Include="DevExpress.Data.v24.1, Version=24.1.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
-    <Reference Include="DevExpress.Drawing.v24.1, Version=24.1.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
-    <Reference Include="DevExpress.Printing.v24.1.Core, Version=24.1.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a" />
-    <Reference Include="DevExpress.Utils.v24.1, Version=24.1.5.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
     <Reference Include="FEIApiControl">
       <HintPath>..\OpenDll\FEIAPI\FEIApiControl.dll</HintPath>
       <Private>False</Private>

+ 24 - 5
OTSIncAMeasureApp/ServiceCenter/CImageHandler.cs

@@ -632,19 +632,38 @@ namespace OTSModelSharp.ServiceCenter
             {
                 return false;
             }
-            
-            parts = flddataclr.GetParticleList();
-            
+            List<COTSParticleClr> originalParts = flddataclr.GetParticleList();
            
+            if(a_pImgProcessParam.GetBGRemoveType() == OTS_BGREMOVE_TYPE.WaterShed)
+            {
+                foreach(var p in originalParts)
+                {
+                    if (p.GetSubParticles().Count > 0)
+                    {
+                        parts.AddRange(p.GetSubParticles());
+                    }
+                    else
+                    {
+                        parts.Add(p);
+                    }
+                  
+                }
+                currentField.SetListAnalysisParticles(parts);
+            }
+            else
+            {
+                parts = originalParts;
+            }
+
             currentField.SetListAnalysisParticles(parts);
           
-            parts = currentField.GetListAnalysisParticles();
+          
             return true;
 
         }
         public bool GetParticlesBySpecialGray(CBSEImgClr img, CIntRangeClr grayrange, CDoubleRangeClr diameterRange,double a_pixelSize, ref List<COTSParticleClr> parts)
         {
-            //ImageProForClr imgpro = new ImageProForClr();
+          
 
             COTSFieldDataClr flddataclr = new COTSFieldDataClr();
             imgProEngine.GetParticlesBySpecialPartGrayRange(img, grayrange,diameterRange,a_pixelSize, flddataclr);