Explorar o código

添加图像拼接代码

zty %!s(int64=2) %!d(string=hai) anos
pai
achega
61bac9ff5a

+ 5 - 0
Bin/x64/Debug/Resources/XMLData/AppResource_EN.xml

@@ -877,6 +877,7 @@
 	  <Control name="另存选择颗粒ToolStripMenuItem" text="SaveAs" />
 	  <Control name="ToolStripMenuItem_movesempoint" text="Move SEM to the Particle Horizon Position" />
 	  <Control name="toolStripMenuItem_copyimage" text="Duplicate image" />
+	  <control name="ToolStripMenuItem_split" text="Split particle"/>
 	  <Control name="str1" text="Start loading sort graph information" />
 	  <Control name="str2" text="Loading completed" />
 	  <Control name="str3" text="SEM location:" />
@@ -887,6 +888,10 @@
 	  <Control name="str8" text="Gray scale#" />
 	  <Control name="str9" text="Move SEM to current position" />
 	  <Control name="str10" text="Move SEM to particle view position" />
+	  <Control name="str11" text="Confirm split?" />
+	  <Control name="str12" text="Too many divisions!" />
+	  <Control name="str13" text="Split failed!" />
+	  <Control name="str14" text="No intersection!" />
           <Control name="partcletype9" text="NOT_IDENTIFIED" />
 	  <Control name="partcletype10" text="Analytical Particles" />
     </Controls>

+ 5 - 0
Bin/x64/Debug/Resources/XMLData/AppResource_ZH.xml

@@ -886,6 +886,7 @@
 	  <Control name="ToolStripMenuItem_movesempoint" text="移动SEM到当前位置" />
 	  <Control name="toolStripMenuItem_copyimage" text="导出原图拼接图" />
 	  <control name="ExportoriginalspliceToolStripMenuItem" text="导出原图拼接分类图"/>
+	  <control name="ToolStripMenuItem_split" text="分割颗粒"/>
 	  <Control name="str1" text="开始加载分布图信息" />
 	  <Control name="str2" text="已完成加载" />
 	  <Control name="str3" text="SEM位置:" />
@@ -896,6 +897,10 @@
 	  <Control name="str8" text="复制当前屏幕图像" />
 	  <Control name="str9" text="移动SEM到当前位置" />
 	  <Control name="str10" text="移动SEM到颗粒视域位置" />
+	  <Control name="str11" text="确认分割?" />
+	  <Control name="str12" text="分割数量过多!" />
+	  <Control name="str13" text="分割失败!" />
+	  <Control name="str14" text="没有相交点!" />
 	  
 	  <Control name="MouseMove1" text="颗粒SEM位置:" />
 	  <Control name="MouseMove2" text="灰度#" />

+ 6 - 6
OTSCPP/OTSImagePro/FieldMgr.cpp

@@ -394,8 +394,8 @@ namespace OTSIMGPROC {
 		OTS_GET_IMAGE_MODE nStartMode = (OTS_GET_IMAGE_MODE)m_fieldStartMode;
 			
 			// calculate total columns, rows and make sure the domain area be covered
-			int nTotalCols = (int)(ceil((double)rectMeasureDomain.Width() / (dScanFiledSizeX - 2 * dOverLapSizeX)));
-			int nTotalRows = (int)(ceil((double)rectMeasureDomain.Height() / (dScanFiledSizeY - 2 * dOverLapSizeY)));
+			int nTotalCols = (int)(ceil((double)rectMeasureDomain.Width() / (dScanFiledSizeX - dOverLapSizeX)));
+			int nTotalRows = (int)(ceil((double)rectMeasureDomain.Height() / (dScanFiledSizeY - dOverLapSizeY)));
 
 			// calculate column on the left of the centre point
 			int nLeftCols = nTotalCols / 2;
@@ -408,16 +408,16 @@ namespace OTSIMGPROC {
 			nTotalRows = nRowsOnTop * 2 + 1;
 
 			// calculate left, right field column position (x only
-			int nLeftMostColX = poiDomainCentre.x - nLeftCols * ((int)dScanFiledSizeX - 2 * (int)dOverLapSizeX);
-			int nUpMostRowY = poiDomainCentre.y - nRowsOnTop * ((int)dScanFiledSizeY - 2* (int)dOverLapSizeY);
+			int nLeftMostColX = poiDomainCentre.x - nLeftCols * ((int)dScanFiledSizeX - (int)dOverLapSizeX);
+			int nUpMostRowY = poiDomainCentre.y - nRowsOnTop * ((int)dScanFiledSizeY - (int)dOverLapSizeY);
 				
 				std::vector <std::vector <CPoint>> pointMatrics(nTotalRows, std::vector<CPoint>(nTotalCols));
 				for (int i = 0; i < nTotalRows; i++)
 				{
 					for (int j = 0; j < nTotalCols; j++)
 					{
-						pointMatrics[i][j].x = nLeftMostColX + j * ((int)dScanFiledSizeX - 2 * (int)dOverLapSizeX);
-						pointMatrics[i][j].y = nUpMostRowY + i * ((int)dScanFiledSizeY - 2 * (int)dOverLapSizeY);
+						pointMatrics[i][j].x = nLeftMostColX + j * ((int)dScanFiledSizeX - (int)dOverLapSizeX);
+						pointMatrics[i][j].y = nUpMostRowY + i * ((int)dScanFiledSizeY - (int)dOverLapSizeY);
 					}
 				}
 				std::vector <std::vector <int>> sequenceMat; //construct an matrics map to the pointMatrics,but the content is the sequence number.

+ 9 - 1
OTSIncAMeasureApp/0-OTSModel/Measure/3-MeasureFlow/CSmplMeasure.cs

@@ -856,7 +856,15 @@ namespace OTSModelSharp
             //Repeated particle treatment
             if (theSample.GetMsrParams().GetImageProcessParam().GetPartCombin())
             {
-                imgpro.RepeatedParticleTreatment(theSample.GetFieldsData(), theSample, m_pSampleRstFile.m_strdbPathName);
+                log.Info("begin repeated particle treatment...");
+                if (imgpro.RepeatedParticleTreatment(theSample.GetFieldsData(), theSample, m_pSampleRstFile.m_strdbPathName))
+                {
+                    log.Info("success...");
+                }
+                else
+                {
+                    log.Info("faild...");
+                }
             }
 
             imgpro.MergeBigBoundaryParticles(theSample.GetFieldsData(), pixelSize, scanfldsize, theSample.GetResolutionSize(), ref mergedParticles);

+ 401 - 119
OTSIncAMeasureApp/ServiceCenter/CImageHandler.cs

@@ -397,10 +397,9 @@ namespace OTSModelSharp.ServiceInterface
             System.Drawing.Size resolutionSize = theSample.GetResolutionSize();
             int scanFieldSizeX = theSample.GetSEMDataMsr().GetScanFieldSize();
             int scanFieldSizeY = scanFieldSizeX * resolutionSize.Height / resolutionSize.Width;
-            int offsetX = scanFieldSizeX - (int)(2 * overlap * pixelSize);
-            int offsetY = scanFieldSizeY - (int)(2 * overlap * pixelSize);
+            int offsetX = scanFieldSizeX - (int)(overlap * pixelSize);
+            int offsetY = scanFieldSizeY - (int)(overlap * pixelSize);
             List<COTSParticleClr> deletePartList = new List<COTSParticleClr>();
-            List<COTSParticleClr> updatePartList = new List<COTSParticleClr>();
 
             foreach (var item in allFields)
             {
@@ -474,20 +473,11 @@ namespace OTSModelSharp.ServiceInterface
                 foreach (var leftParticles in left_upField.GetListAnalysisParticles())
                 {
                     Rectangle leftRectangle = (Rectangle)leftParticles.GetParticleRect();
-                    if (leftRectangle.Right > resolutionSize.Width - overlap)//颗粒在左帧图的右侧重叠区域
+                    if (leftRectangle.Left > resolutionSize.Width - overlap)//未跨界
                     {
                         particleClrs.Add(leftParticles);
                     }
                 }
-                //寻找当前帧图的左侧区域颗粒
-                foreach (var centerParticles in right_downField.GetListAnalysisParticles())
-                {
-                    Rectangle centerRectangle = (Rectangle)centerParticles.GetParticleRect();
-                    if (centerRectangle.Left < overlap)//左侧颗粒在当前帧图的左侧重叠区域
-                    {
-                        particleClrs.Add(centerParticles);
-                    }
-                }
             }
             else
             {
@@ -495,142 +485,434 @@ namespace OTSModelSharp.ServiceInterface
                 foreach (var upParticles in left_upField.GetListAnalysisParticles())
                 {
                     Rectangle upRectangle = (Rectangle)upParticles.GetParticleRect();
-                    if (upRectangle.Bottom > resolutionSize.Height - overlap)//颗粒在左帧图的右侧重叠区域
+                    if (upRectangle.Top > resolutionSize.Height - overlap)//未跨界
                     {
                         particleClrs.Add(upParticles);
                     }
                 }
-                //寻找当前帧图的上侧区域颗粒
-                foreach (var downParticles in right_downField.GetListAnalysisParticles())
+            }
+
+            return particleClrs;
+        }
+
+        public Mat CombinImageX(Mat[] list_mats, int OverlapParam, int type)
+        {
+            List<Mat> matStitch = new List<Mat>();//拼接
+            List<Mat> matCombin = new List<Mat>();//合并
+            for (int i = 0; i < list_mats.Count(); i++)
+            {
+                if (i == 0)//首张
                 {
-                    Rectangle downRectangle = (Rectangle)downParticles.GetParticleRect();
-                    if (downRectangle.Top < overlap)//左侧颗粒在当前帧图的左侧重叠区域
-                    {
-                        particleClrs.Add(downParticles);
-                    }
+                    matCombin.Add(new Mat(list_mats[i], new Rect(0, 0, list_mats[i].Width - OverlapParam - 200, list_mats[i].Height)));
+                    matStitch.Add(new Mat(list_mats[i], new Rect(list_mats[i].Width - OverlapParam - 200, 0, OverlapParam + 200, list_mats[i].Height)));
+                }
+                else if(i == list_mats.Count() - 1)//末张
+                {
+                    matStitch.Add(new Mat(list_mats[i], new Rect(0, 0, OverlapParam + 200, list_mats[i].Height)));
+                    matCombin.Add(new Mat(list_mats[i], new Rect(OverlapParam + 200, 0, list_mats[i].Width - OverlapParam - 200, list_mats[i].Height)));
+                }
+                else
+                {
+                    matStitch.Add(new Mat(list_mats[i], new Rect(0, 0, OverlapParam + 200, list_mats[i].Height)));
+                    matCombin.Add(new Mat(list_mats[i], new Rect(OverlapParam + 200, 0, list_mats[i].Width - (OverlapParam + 200) * 2, list_mats[i].Height)));
+                    matStitch.Add(new Mat(list_mats[i], new Rect(list_mats[i].Width - OverlapParam - 200, 0, OverlapParam + 200, list_mats[i].Height)));
                 }
             }
 
-            return particleClrs;
+            for (int i = 0; i < matStitch.Count; i += 2)
+            {
+                if (matStitch.Count == 1)
+                {
+                    matCombin.Insert(i + 1, matStitch[i]);
+                }
+                else
+                {
+                    matCombin.Insert(i + 1, StitchImageX((int)(OverlapParam * 1.5), type, matStitch[i], matStitch[i + 1]));
+                }
+            }
+
+            Mat pano = new OpenCvSharp.Mat();
+            Cv2.HConcat(matCombin.ToArray(), pano);
+
+            return pano;
         }
 
-        private void CombinFun(Dictionary<COTSParticleClr, COTSParticleClr> combin, string style, System.Drawing.Size resolutionSize, int overlap, ref List<COTSParticleClr> deletePartList, ref List<COTSParticleClr> updatePartList)
+        public Mat CombinImageY(Mat[] list_mats, int OverlapParam, int type)
         {
-            foreach (var item in combin)
+            List<Mat> matStitch = new List<Mat>();//拼接
+            List<Mat> matCombin = new List<Mat>();//合并
+            for (int i = 0; i < list_mats.Count(); i++)
             {
-                Rectangle left_topRectangle = (Rectangle)item.Key.GetParticleRect();
-                Rectangle right_bottomRectangle = (Rectangle)item.Value.GetParticleRect();
+                if (i == 0)//首张
+                {
+                    matCombin.Add(new Mat(list_mats[i], new Rect(0, 0, list_mats[i].Width, list_mats[i].Height - OverlapParam - 200)));
+                    matStitch.Add(new Mat(list_mats[i], new Rect(0, list_mats[i].Height - OverlapParam - 200, list_mats[i].Width, OverlapParam + 200)));
+                }
+                else if (i == list_mats.Count() - 1)//末张
+                {
+                    matStitch.Add(new Mat(list_mats[i], new Rect(0, 0, list_mats[i].Width, OverlapParam + 200)));
+                    matCombin.Add(new Mat(list_mats[i], new Rect(0, OverlapParam + 200, list_mats[i].Width, list_mats[i].Height - OverlapParam - 200)));
+                }
+                else
+                {
+                    matStitch.Add(new Mat(list_mats[i], new Rect(0, 0, list_mats[i].Width, OverlapParam + 200)));
+                    matCombin.Add(new Mat(list_mats[i], new Rect(0, OverlapParam + 200, list_mats[i].Width, list_mats[i].Height - (OverlapParam + 200) * 2)));
+                    matStitch.Add(new Mat(list_mats[i], new Rect(0, list_mats[i].Height - OverlapParam - 200, list_mats[i].Width, OverlapParam + 200)));
+                }
+            }
 
-                //左颗粒:跨右边界 右颗粒:跨左边界 
-                if (style == "left_right")
+            for (int i = 0; i < matStitch.Count; i += 2)
+            {
+                if (matStitch.Count == 1)
                 {
-                    if (left_topRectangle.Right == resolutionSize.Width - 1 && right_bottomRectangle.Left == 0)
+                    matCombin.Insert(i + 1, matStitch[i]);
+                }
+                else
+                {
+                    matCombin.Insert(i + 1, StitchImageY((int)(OverlapParam), type, matStitch[i], matStitch[i + 1]));
+                }
+            }
+
+            Mat pano = new OpenCvSharp.Mat();
+            Cv2.VConcat(matCombin.ToArray(), pano);
+
+            return pano;
+        }
+
+        public struct MStitch
+        {
+            public int Pwidth;//单幅图像的宽度
+            public int Pheight;//单幅图像的高度
+            public int W_min;//最小的重叠区域宽度
+            public int W_max;//最大的重叠区域宽度
+            public int H_min;//最小的重叠区域高度
+            public double minval;//块过滤阈值
+            public Mat im;//图像信息
+        }
+        public struct ImageParam
+        {
+            public int W_box;//宽度信息
+            public int H_box;//高度信息
+            public int bdown;//上下信息
+            public MStitch mStitch; //参数结构
+            public Mat im;//图像信息
+        }
+
+        /// <summary>
+        /// 横向拼图
+        /// </summary>
+        public Mat StitchImageX(int min_w, int type, Mat newImg1, Mat newImg2)
+        {
+            MStitch mStitch = new MStitch();
+            mStitch.Pwidth = newImg1.Width;
+            mStitch.Pheight = newImg1.Height;
+            mStitch.W_min = min_w;
+            mStitch.W_max = min_w;
+            mStitch.H_min = newImg1.Height;
+            mStitch.minval = 255;
+            mStitch.im = newImg1;
+
+            ImageParam imageParam = Fun_Match(newImg2, mStitch);
+            imageParam.im = newImg2;
+
+            if (type == 2)
+            {
+                return Fun_Stitch(imageParam);
+            }
+            else
+            {
+                return Fun_StitchRGB(imageParam);
+            }
+        }
+
+        /// <summary>
+        /// 纵向拼图
+        /// </summary>
+        public Mat StitchImageY(int min_w, int type, Mat newImg1, Mat newImg2)
+        {
+            Cv2.Transpose(newImg1, newImg1);
+            Cv2.Flip(newImg1, newImg1, FlipMode.X);
+
+            Cv2.Transpose(newImg2, newImg2);
+            Cv2.Flip(newImg2, newImg2, FlipMode.X);
+
+            MStitch mStitch = new MStitch();
+            mStitch.Pwidth = newImg1.Width;
+            mStitch.Pheight = newImg1.Height;
+            mStitch.W_min = min_w;
+            mStitch.W_max = min_w + 50;
+            mStitch.H_min = newImg1.Height;
+            mStitch.minval = 255;
+            mStitch.im = newImg1;
+
+            ImageParam imageParam = Fun_Match(newImg2, mStitch);
+            imageParam.im = newImg2;
+
+            Mat result = type == 2 ? Fun_Stitch(imageParam) : Fun_StitchRGB(imageParam);
+
+            Cv2.Transpose(result, result);
+            Cv2.Flip(result, result, FlipMode.Y);
+
+            return result;
+        }
+
+        public static ImageParam Fun_Match(Mat im2, MStitch mStitch)
+        {
+            ImageParam imageParam = new ImageParam();
+            double imsum = 0;
+            int x1 = 0;
+            int y1 = 0;
+            int x2 = 0;
+            int y2 = 0;
+            int w_ind = 0;
+            int h_ind = 0;
+
+            //在上窗口所有匹配块内进行搜索
+            for (int w = mStitch.W_min; w <= mStitch.W_max; w++)
+            {
+                for (int h = mStitch.H_min; h <= mStitch.Pheight; h++)
+                {
+                    imsum = 0;//块差分集初始化
+                    x2 = 1;
+                    for (x1 = mStitch.Pwidth - w; x1 <= mStitch.Pwidth; x1 += 5)
                     {
-                        int offset = right_bottomRectangle.Y - left_topRectangle.Y;
-                        if (item.Key.GetActualArea() > item.Value.GetActualArea())
+                        y2 = 1;
+                        for (y1 = mStitch.Pheight - h + 1; y1 <= mStitch.Pheight; y1 += 5)
                         {
-                            Rectangle rectangle = new Rectangle(right_bottomRectangle.X, left_topRectangle.Y, right_bottomRectangle.Width, right_bottomRectangle.Height);
-                            item.Value.SetParticleRect(rectangle);
-                            COTSFeatureClr featureClr = item.Value.GetFeature();
-                            List<COTSSegmentClr> segmentClrs = featureClr.GetSegmentsList();
-                            foreach (var Segment in segmentClrs)
-                            {
-                                Segment.SetHeight(Segment.GetHeight() - offset);
-                            }
-                            if (!updatePartList.Contains(item.Value))
-                            {
-                                updatePartList.Add(item.Value);
-                            }
-                        }
-                        else
-                        {
-                            Rectangle rectangle = new Rectangle(left_topRectangle.X, right_bottomRectangle.Y, left_topRectangle.Width, left_topRectangle.Height);
-                            item.Key.SetParticleRect(rectangle);
-                            COTSFeatureClr featureClr = item.Key.GetFeature();
-                            List<COTSSegmentClr> segmentClrs = featureClr.GetSegmentsList();
-                            foreach (var Segment in segmentClrs)
-                            {
-                                Segment.SetHeight(Segment.GetHeight() + offset);
-                            }
-                            if (!updatePartList.Contains(item.Key))
-                            {
-                                updatePartList.Add(item.Key);
-                            }
+                            //块差分集计算
+                            CheckRC(ref x1, ref y1, mStitch.im);
+                            CheckRC(ref x2, ref y2, im2);
+                            imsum = imsum + Math.Abs(mStitch.im.At<Vec3b>(y1, x1).Item0 - im2.At<Vec3b>(y2, x2).Item0);
+                            y2 = y2 + 5;
                         }
+                        x2 = x2 + 5;
                     }
-                    else
+                    //阈值更新
+                    if (imsum * 5 * 5 <= mStitch.minval * w * h)
                     {
-                        if (item.Key.GetActualArea() > item.Value.GetActualArea())
-                        {
-                            if (!deletePartList.Contains(item.Value))
-                            {
-                                deletePartList.Add(item.Value);
-                            }
-                        }
-                        else
-                        {
-                            if (!deletePartList.Contains(item.Key))
-                            {
-                                deletePartList.Add(item.Key);
-                            }
-                        }
+                        mStitch.minval = imsum * 5 * 5 / (w * h);
+                        w_ind = w;
+                        h_ind = h;
                     }
                 }
-                else
+            }
+
+            imageParam.W_box = w_ind;
+            imageParam.H_box = h_ind;
+            imageParam.bdown = 1;
+
+            //在下窗口所有匹配块内进行搜索
+            Parallel.For(mStitch.W_min, mStitch.W_max, w =>
+            {
+                Parallel.For(mStitch.H_min, mStitch.Pheight, h =>
                 {
-                    if (left_topRectangle.Bottom == resolutionSize.Height - 1 && right_bottomRectangle.Top == 0)
+                    imsum = 0;//块差分集初始化
+                    x2 = 1;
+                    for (x1 = mStitch.Pwidth - w; x1 <= mStitch.Pwidth; x1 += 5)
                     {
-                        int offset = left_topRectangle.X - right_bottomRectangle.X;
-                        if (item.Key.GetActualArea() > item.Value.GetActualArea())
-                        {
-                            Rectangle rectangle = new Rectangle(left_topRectangle.X, right_bottomRectangle.Y, right_bottomRectangle.Width, right_bottomRectangle.Height);
-                            item.Value.SetParticleRect(rectangle);
-                            COTSFeatureClr featureClr = item.Value.GetFeature();
-                            List<COTSSegmentClr> segmentClrs = featureClr.GetSegmentsList();
-                            foreach (var Segment in segmentClrs)
-                            {
-                                Segment.SetStart(Segment.GetStart() + offset);
-                            }
-                            if (!updatePartList.Contains(item.Value))
-                            {
-                                updatePartList.Add(item.Value);
-                            }
-                        }
-                        else
+                        y1 = 1;
+                        for (y2 = mStitch.Pheight - h + 1; y2 <= mStitch.Pheight; y2 += 5)
                         {
-                            Rectangle rectangle = new Rectangle(right_bottomRectangle.X, left_topRectangle.Y, left_topRectangle.Width, left_topRectangle.Height);
-                            item.Key.SetParticleRect(rectangle);
-                            COTSFeatureClr featureClr = item.Key.GetFeature();
-                            List<COTSSegmentClr> segmentClrs = featureClr.GetSegmentsList();
-                            foreach (var Segment in segmentClrs)
-                            {
-                                Segment.SetStart(Segment.GetStart() - offset);
-                            }
-                            if (!updatePartList.Contains(item.Key))
-                            {
-                                updatePartList.Add(item.Key);
-                            }
+                            //块差分集计算
+                            CheckRC(ref x1, ref y1, mStitch.im);
+                            CheckRC(ref x2, ref y2, im2);
+                            imsum = imsum + Math.Abs(mStitch.im.At<Vec3b>(y1, x1).Item0 - im2.At<Vec3b>(y2, x2).Item0);
+                            y1 = y1 + 5;
                         }
+                        x2 = x2 + 5;
                     }
-                    else
+                    //阈值更新
+                    if (imsum * 5 * 5 <= mStitch.minval * w * h)
                     {
-                        if (item.Key.GetActualArea() > item.Value.GetActualArea())
-                        {
-                            if (!deletePartList.Contains(item.Value))
-                            {
-                                deletePartList.Add(item.Value);
-                            }
-                        }
-                        else
-                        {
-                            if (!deletePartList.Contains(item.Key))
-                            {
-                                deletePartList.Add(item.Key);
-                            }
-                        }
+                        mStitch.minval = imsum * 5 * 5 / (w * h);
+                        w_ind = w;
+                        h_ind = h;
+                        imageParam.bdown = 0;
+                    }
+                });
+            });
+
+            imageParam.mStitch = mStitch;
+
+            return imageParam;
+        }
+
+        public static void CheckRC(ref int x, ref int y, Mat im)
+        {
+            //图像矩阵访问有效性检测
+            // 输入参数:
+            // x——列
+            // y——行
+            // im——图像矩阵
+            // 输出参数:
+            // x——列
+            // y——行
+            y = Math.Max(y, 1);
+            y = Math.Min(y, im.Height - 1);
+            x = Math.Max(x, 1);
+            x = Math.Min(x, im.Width - 1);
+        }
+
+        public Mat Fun_Stitch(ImageParam imageParam)
+        {
+            //图像融合
+            //输入参数:
+            //im2——待融合图像
+            //W_box——宽度信息
+            //H_box——高度信息
+            //bdown——上下信息
+            //MStitch——参数结构
+            //输出参数:
+            //MStitch——参数结构
+            //im——融合图像
+
+            Mat img = imageParam.im;
+            int x1 = 0;
+            int y1 = 0;
+            int x2 = 0;
+            int y2 = 0;
+            double w = 0.5; //融合权值
+
+            if (imageParam.bdown == 1)
+            {
+                //下区域重叠
+                x2 = 1;
+                //融合重叠区域
+                for (x1 = imageParam.mStitch.Pwidth - imageParam.W_box; x1 < imageParam.mStitch.Pwidth; x1++)
+                {
+                    y2 = 1;
+                    for (y1 = imageParam.mStitch.Pheight - imageParam.H_box + 1; y1 < imageParam.mStitch.Pheight; y1++)
+                    {
+                        //安全性检测
+                        CheckRC(ref x1, ref y1, imageParam.mStitch.im);
+                        CheckRC(ref x2, ref y2, imageParam.im);
+                        //融合权值
+                        w = (double)x2 / (double)imageParam.W_box;
+                        //加权融合
+                        double ColorRGB = imageParam.mStitch.im.At<Vec3b>(y1, x1).Item0 * (1.0 - w) + imageParam.im.At<Vec3b>(y2, x2).Item0 * w;
+                        imageParam.mStitch.im.Set<Vec3b>(y1, x1, new Vec3b((byte)ColorRGB, (byte)ColorRGB, (byte)ColorRGB));
+                        y2 = y2 + 1;
                     }
+                    x2 = x2 + 1;
                 }
             }
+            else
+            {
+                //上区域重叠
+                x2 = 1;
+                //融合重叠区域
+                for (x1 = imageParam.mStitch.Pwidth - imageParam.W_box; x1 < imageParam.mStitch.Pwidth; x1++)
+                {
+                    y2 = 1;
+                    for (y1 = imageParam.mStitch.Pheight - imageParam.H_box + 1; y1 < imageParam.mStitch.Pheight; y1++)
+                    {
+                        //安全性检测
+                        CheckRC(ref x1, ref y1, imageParam.mStitch.im);
+                        CheckRC(ref x2, ref y2, imageParam.im);
+                        //融合权值
+                        w = (double)x2 / (double)imageParam.W_box;
+                        //加权融合
+                        double ColorRGB = imageParam.mStitch.im.At<Vec3b>(y1, x1).Item0 * (1.0 - w) + imageParam.im.At<Vec3b>(y2, x2).Item0 * w;
+                        imageParam.mStitch.im.Set<Vec3b>(y1, x1, new Vec3b((byte)ColorRGB, (byte)ColorRGB, (byte)ColorRGB));
+
+                        y2 = y2 + 1;
+                    }
+                    x2 = x2 + 1;
+                }
+            }
+
+            //最终图
+            img = new Mat(imageParam.mStitch.Pheight, imageParam.mStitch.Pwidth + imageParam.im.Width - x2 + 1, MatType.CV_8UC3);
+
+            //分离出重叠区域
+            Rect m_select = new Rect(x2 - 1, 0, imageParam.im.Width - x2 + 1, imageParam.mStitch.Pheight);
+            Mat imgSwitch = new Mat(imageParam.im, m_select);
+            Cv2.HConcat(imageParam.mStitch.im, imgSwitch, img);
+
+            return img;
+        }
+
+        public Mat Fun_StitchRGB(ImageParam imageParam)
+        {
+            //图像融合
+            //输入参数:
+            //im2——待融合图像
+            //W_box——宽度信息
+            //H_box——高度信息
+            //bdown——上下信息
+            //MStitch——参数结构
+            //输出参数:
+            //MStitch——参数结构
+            //im——融合图像
+
+            Mat img = imageParam.im;
+            int x1 = 0;
+            int y1 = 0;
+            int x2 = 0;
+            int y2 = 0;
+            double w = 0.5; //融合权值
+
+            if (imageParam.bdown == 1)
+            {
+                //下区域重叠
+                x2 = 1;
+                //融合重叠区域
+                for (x1 = imageParam.mStitch.Pwidth - imageParam.W_box; x1 < imageParam.mStitch.Pwidth; x1++)
+                {
+                    y2 = 1;
+                    for (y1 = imageParam.mStitch.Pheight - imageParam.H_box + 1; y1 < imageParam.mStitch.Pheight; y1++)
+                    {
+                        //安全性检测
+                        CheckRC(ref x1, ref y1, imageParam.mStitch.im);
+                        CheckRC(ref x2, ref y2, imageParam.im);
+                        //融合权值
+                        w = (double)x2 / (double)imageParam.W_box;
+                        //加权融合
+                        double ColorR = imageParam.mStitch.im.At<Vec3b>(y1, x1).Item0 * (1.0 - w) + imageParam.im.At<Vec3b>(y2, x2).Item0 * w;
+                        double ColorG = imageParam.mStitch.im.At<Vec3b>(y1, x1).Item1 * (1.0 - w) + imageParam.im.At<Vec3b>(y2, x2).Item1 * w;
+                        double ColorB = imageParam.mStitch.im.At<Vec3b>(y1, x1).Item2 * (1.0 - w) + imageParam.im.At<Vec3b>(y2, x2).Item2 * w;
+                        imageParam.mStitch.im.Set<Vec3b>(y1, x1, new Vec3b((byte)ColorR, (byte)ColorG, (byte)ColorB));
+                        y2 = y2 + 1;
+                    }
+                    x2 = x2 + 1;
+                }
+            }
+            else
+            {
+                //上区域重叠
+                x2 = 1;
+                //融合重叠区域
+                for (x1 = imageParam.mStitch.Pwidth - imageParam.W_box; x1 < imageParam.mStitch.Pwidth; x1++)
+                {
+                    y2 = 1;
+                    for (y1 = imageParam.mStitch.Pheight - imageParam.H_box + 1; y1 < imageParam.mStitch.Pheight; y1++)
+                    {
+                        //安全性检测
+                        CheckRC(ref x1, ref y1, imageParam.mStitch.im);
+                        CheckRC(ref x2, ref y2, imageParam.im);
+                        //融合权值
+                        w = (double)x2 / (double)imageParam.W_box;
+                        //加权融合
+                        double ColorR = imageParam.mStitch.im.At<Vec3b>(y1, x1).Item0 * (1.0 - w) + imageParam.im.At<Vec3b>(y2, x2).Item0 * w;
+                        double ColorG = imageParam.mStitch.im.At<Vec3b>(y1, x1).Item1 * (1.0 - w) + imageParam.im.At<Vec3b>(y2, x2).Item1 * w;
+                        double ColorB = imageParam.mStitch.im.At<Vec3b>(y1, x1).Item2 * (1.0 - w) + imageParam.im.At<Vec3b>(y2, x2).Item2 * w;
+                        imageParam.mStitch.im.Set<Vec3b>(y1, x1, new Vec3b((byte)ColorR, (byte)ColorG, (byte)ColorB));
+
+                        y2 = y2 + 1;
+                    }
+                    x2 = x2 + 1;
+                }
+            }
+
+            //最终图
+            img = new Mat(imageParam.mStitch.Pheight, imageParam.mStitch.Pwidth + imageParam.im.Width - x2 + 1, MatType.CV_8UC3);
+
+            //分离出重叠区域
+            Rect m_select = new Rect(x2 - 1, 0, imageParam.im.Width - x2 + 1, imageParam.mStitch.Pheight);
+            Mat imgSwitch = new Mat(imageParam.im, m_select);
+            Cv2.HConcat(imageParam.mStitch.im, imgSwitch, img);
+
+            return img;
         }
     }
 }

+ 49 - 3
OTSIncAReportApp/1-UI/Control_Graph/Controls/Control_DrawDistrbutionImageAndBSE.cs

@@ -56,7 +56,9 @@ namespace OTSIncAReportGraph.Controls
        CopyImage=2,
        OriginalSplicing= 3,
        DeleteParticle=4,       
-	   ParticleSegmentation=5
+	   ParticleSegmentation=5,
+       CombinImage=6,
+       RenderCombinImage=7
     }
     /// <summary>
     /// 选择导出的图片是原图还是颗粒渲染后的图片
@@ -64,7 +66,9 @@ namespace OTSIncAReportGraph.Controls
     public enum Outpic_enum
     {
         pic=0,
-        Render_pic=1
+        Render_pic=1,
+        Combin,
+        Render_Combin
     }
 
     public partial class Control_DrawDistrbutionImageAndBSE : UserControl
@@ -1321,6 +1325,8 @@ namespace OTSIncAReportGraph.Controls
                         CMenuStrip.Items[(int)RightButtonMenu.Include].Visible = false;
                        
                         CMenuStrip.Items[(int)RightButtonMenu.CopyImage].Visible = false;
+                        CMenuStrip.Items[(int)RightButtonMenu.CombinImage].Visible = false;
+                        CMenuStrip.Items[(int)RightButtonMenu.RenderCombinImage].Visible = false;
                         CMenuStrip.Items[(int)RightButtonMenu.OriginalSplicing].Visible = false;
                         CMenuStrip.Items[(int)RightButtonMenu.DeleteParticle].Visible = true;
                         //CMenuStrip.Items[(int)RightButtonMenu.CopyDatabase].Visible = true;
@@ -1359,7 +1365,8 @@ namespace OTSIncAReportGraph.Controls
                     CMenuStrip.Items[(int)RightButtonMenu.OriginalSplicing].Visible = true;
                     CMenuStrip.Items[(int)RightButtonMenu.MoveSEMToParticle].Visible = false;
                     CMenuStrip.Items[(int)RightButtonMenu.ParticleSegmentation].Visible = false;
-
+                    CMenuStrip.Items[(int)RightButtonMenu.CombinImage].Visible = true;
+                    CMenuStrip.Items[(int)RightButtonMenu.RenderCombinImage].Visible = true;
                 }
                       
 
@@ -2288,5 +2295,44 @@ namespace OTSIncAReportGraph.Controls
         {
             Particle_Segmentation();
         }
+
+        private void toolStripMenuItem_combin_Click(object sender, EventArgs e)
+        {
+            SaveFileDialog sfd = new SaveFileDialog();
+            //|ALL Files(*.*)|*.*
+            //BMP Files(*.bmp)| *.bmp |
+            sfd.Filter = "png Files(*.png)| *.png |BMP Files(*.bmp)| *.bmp |JPG Files(*.jpg)|*.jpg;*.jpeg";
+            if (sfd.ShowDialog() == DialogResult.OK)
+            {
+                OutPIC outpic = new OutPIC();
+                outpic.m_list_allDfield = m_list_allDfield;
+                outpic.resultFile = resultFile;
+                outpic.sfd = sfd;
+                outpic.type = (int)Outpic_enum.Combin;
+                Thread bThread = new Thread(new ThreadStart(outpic.opencv_outpic));
+                bThread.IsBackground = true;
+                bThread.Start();
+            }
+
+        }
+
+        private void toolStripMenuItem_combinClass_Click(object sender, EventArgs e)
+        {
+            SaveFileDialog sfd = new SaveFileDialog();
+            //|ALL Files(*.*)|*.*
+            //BMP Files(*.bmp)| *.bmp |
+            sfd.Filter = "png Files(*.png)| *.png |BMP Files(*.bmp)| *.bmp |JPG Files(*.jpg)|*.jpg;*.jpeg";
+            if (sfd.ShowDialog() == DialogResult.OK)
+            {
+                OutPIC outpic = new OutPIC();
+                outpic.m_list_allDfield = m_list_allDfield;
+                outpic.resultFile = resultFile;
+                outpic.sfd = sfd;
+                outpic.type = (int)Outpic_enum.Render_Combin;
+                Thread bThread = new Thread(new ThreadStart(outpic.opencv_outpic));
+                bThread.IsBackground = true;
+                bThread.Start();
+            }
+        }
     }
 }

+ 31 - 9
OTSIncAReportApp/1-UI/Control_Graph/Controls/Control_DrawDistrbutionImageAndBSE.designer.cs

@@ -35,7 +35,9 @@
             this.toolStripMenuItem_copyimage = new System.Windows.Forms.ToolStripMenuItem();
             this.ExportoriginalspliceToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
             this.ToolStripMenuItemDelete_Particle = new System.Windows.Forms.ToolStripMenuItem();
-            this.分割颗粒ToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+            this.ToolStripMenuItem_split = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem_combin = new System.Windows.Forms.ToolStripMenuItem();
+            this.toolStripMenuItem_combinClass = new System.Windows.Forms.ToolStripMenuItem();
             this.CMenuStrip.SuspendLayout();
             this.SuspendLayout();
             // 
@@ -48,9 +50,11 @@
             this.toolStripMenuItem_copyimage,
             this.ExportoriginalspliceToolStripMenuItem,
             this.ToolStripMenuItemDelete_Particle,
-            this.分割颗粒ToolStripMenuItem});
+            this.ToolStripMenuItem_split,
+            this.toolStripMenuItem_combin,
+            this.toolStripMenuItem_combinClass});
             this.CMenuStrip.Name = "contextMenuStrip1";
-            this.CMenuStrip.Size = new System.Drawing.Size(219, 206);
+            this.CMenuStrip.Size = new System.Drawing.Size(219, 266);
             // 
             // ToolStripMenuItem_selected
             // 
@@ -91,12 +95,28 @@
             this.ToolStripMenuItemDelete_Particle.Text = "Delete particles";
             this.ToolStripMenuItemDelete_Particle.Click += new System.EventHandler(this.ToolStripMenuItemDelete_Particle_Click);
             // 
-            // 分割颗粒ToolStripMenuItem
+            // ToolStripMenuItem_split
             // 
-            this.分割颗粒ToolStripMenuItem.Name = "分割颗粒ToolStripMenuItem";
-            this.分割颗粒ToolStripMenuItem.Size = new System.Drawing.Size(218, 30);
-            this.分割颗粒ToolStripMenuItem.Text = "分割颗粒";
-            this.分割颗粒ToolStripMenuItem.Click += new System.EventHandler(this.ParticleSegmentation_Click);
+            this.ToolStripMenuItem_split.Name = "ToolStripMenuItem_split";
+            this.ToolStripMenuItem_split.Size = new System.Drawing.Size(218, 30);
+            this.ToolStripMenuItem_split.Text = "分割颗粒";
+            this.ToolStripMenuItem_split.Click += new System.EventHandler(this.ParticleSegmentation_Click);
+            // 
+            // toolStripMenuItem_combin
+            // 
+            this.toolStripMenuItem_combin.Image = global::OTSIncAReportApp.Properties.Resources.复制图像;
+            this.toolStripMenuItem_combin.Name = "toolStripMenuItem_combin";
+            this.toolStripMenuItem_combin.Size = new System.Drawing.Size(218, 30);
+            this.toolStripMenuItem_combin.Text = "导出原图融合图";
+            this.toolStripMenuItem_combin.Click += new System.EventHandler(this.toolStripMenuItem_combin_Click);
+            // 
+            // toolStripMenuItem_combinClass
+            // 
+            this.toolStripMenuItem_combinClass.Image = global::OTSIncAReportApp.Properties.Resources.复制图像;
+            this.toolStripMenuItem_combinClass.Name = "toolStripMenuItem_combinClass";
+            this.toolStripMenuItem_combinClass.Size = new System.Drawing.Size(218, 30);
+            this.toolStripMenuItem_combinClass.Text = "导出原图融合分类图";
+            this.toolStripMenuItem_combinClass.Click += new System.EventHandler(this.toolStripMenuItem_combinClass_Click);
             // 
             // Control_DrawDistrbutionImageAndBSE
             // 
@@ -121,6 +141,8 @@
         private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_copyimage;
         private System.Windows.Forms.ToolStripMenuItem ExportoriginalspliceToolStripMenuItem;
         private System.Windows.Forms.ToolStripMenuItem ToolStripMenuItemDelete_Particle;
-        private System.Windows.Forms.ToolStripMenuItem 分割颗粒ToolStripMenuItem;
+        private System.Windows.Forms.ToolStripMenuItem ToolStripMenuItem_split;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_combin;
+        private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_combinClass;
     }
 }

+ 54 - 20
OTSIncAReportApp/1-UI/Control_Graph/Controls/OutPIC.cs

@@ -1,6 +1,8 @@
-using OTSCommon.Model;
+using OpenCvSharp;
+using OTSCommon.Model;
 using OTSIncAReportGraph;
 using OTSIncAReportGraph.Controls;
+using OTSModelSharp.ServiceInterface;
 using System;
 using System.Collections.Generic;
 using System.Data;
@@ -9,6 +11,7 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using System.Windows.Forms;
+using Point = System.Drawing.Point;
 
 namespace OTSIncAReportApp._3_ServiceCenter
 {
@@ -100,36 +103,67 @@ namespace OTSIncAReportApp._3_ServiceCenter
         public void opencv_outpic(/*int type*/)
         {
             List<DataTable> list_dt_picdata = new List<DataTable>();
-            if (type == (int)Outpic_enum.pic)
+            if (type == (int)Outpic_enum.pic || type == (int)Outpic_enum.Combin)
             {
                 list_dt_picdata = opencv_piclist();
             }
-            else
-                    if (type == (int)Outpic_enum.Render_pic)
+            else if (type == (int)Outpic_enum.Render_pic || type == (int)Outpic_enum.Render_Combin)
             {
                 list_dt_picdata = opencv_piclist_Render();
             }
-
+            OpenCvSharp.Mat save_pano = new OpenCvSharp.Mat();
             OpenCvSharp.Mat[] list_mats = new OpenCvSharp.Mat[list_dt_picdata.Count];
-            NLog.LogManager.GetCurrentClassLogger().Info("Organize and splice all pictures......");
-            for (int i = 0; i < list_dt_picdata.Count; i++)
+
+            if (type == (int)Outpic_enum.Combin || type == (int)Outpic_enum.Render_Combin)
             {
-                OpenCvSharp.Mat[] mats = new OpenCvSharp.Mat[list_dt_picdata[i].Rows.Count];
-                for (int a = 0; a < list_dt_picdata[i].Rows.Count; a++)
+                CImageHandler cImageHandler = new CImageHandler();
+                Dictionary<string, object> sampleMembers = ((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["Sample"])["Members"]);
+                Dictionary<string, object> imageProcessParam = (Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)sampleMembers["MsrParams"])["Members"])["ImageProcessParam"];
+                object strOverlapParam = "";
+                imageProcessParam.TryGetValue("OverlapParam", out strOverlapParam);
+                if (strOverlapParam == null)
                 {
-                    mats[a] = OpenCvSharp.Extensions.BitmapConverter.ToMat((Bitmap)list_dt_picdata[i].Rows[a]["mat"]);
+                    NLog.LogManager.GetCurrentClassLogger().Info("There are no overlapping dimensions");
+                    return;
                 }
-                OpenCvSharp.Mat pano = new OpenCvSharp.Mat();
-                OpenCvSharp.Cv2.HConcat(mats, pano);
-                list_mats[i] = pano;
-                
+                int OverlapParam = int.Parse(strOverlapParam.ToString());
+                List<Mat> maxXList = new List<Mat>();
+                for (int i = 0; i < list_dt_picdata.Count; i++)
+                {
+                    OpenCvSharp.Mat[] mats = new OpenCvSharp.Mat[list_dt_picdata[i].Rows.Count];
+                    for (int a = 0; a < list_dt_picdata[i].Rows.Count; a++)
+                    {
+                        mats[a] = OpenCvSharp.Extensions.BitmapConverter.ToMat((Bitmap)list_dt_picdata[i].Rows[a]["mat"]);
+                    }
+                    //横向拼接
+                    maxXList.Add(cImageHandler.CombinImageX(mats, OverlapParam, type));
+                }
+                save_pano = cImageHandler.CombinImageY(maxXList.ToArray(), OverlapParam, type);
+                OpenCvSharp.Cv2.ImWrite(sfd.FileName, save_pano);
+                NLog.LogManager.GetCurrentClassLogger().Info("Save complete.");
+            }
+            else
+            {
+                NLog.LogManager.GetCurrentClassLogger().Info("Organize and splice all pictures......");
+                for (int i = 0; i < list_dt_picdata.Count; i++)
+                {
+                    OpenCvSharp.Mat[] mats = new OpenCvSharp.Mat[list_dt_picdata[i].Rows.Count];
+                    for (int a = 0; a < list_dt_picdata[i].Rows.Count; a++)
+                    {
+                        mats[a] = OpenCvSharp.Extensions.BitmapConverter.ToMat((Bitmap)list_dt_picdata[i].Rows[a]["mat"]);
+                    }
+                    OpenCvSharp.Mat pano = new OpenCvSharp.Mat();
+                    OpenCvSharp.Cv2.HConcat(mats, pano);
+                    list_mats[i] = pano;
+
+                }
+                NLog.LogManager.GetCurrentClassLogger().Info("Picture splicing completed.");
+                NLog.LogManager.GetCurrentClassLogger().Info("Save to disk......");
+
+                OpenCvSharp.Cv2.VConcat(list_mats, save_pano);
+                OpenCvSharp.Cv2.ImWrite(sfd.FileName, save_pano);
+                NLog.LogManager.GetCurrentClassLogger().Info("Save complete.");
             }
-            NLog.LogManager.GetCurrentClassLogger().Info("Picture splicing completed.");
-            NLog.LogManager.GetCurrentClassLogger().Info("Save to disk......");
-            OpenCvSharp.Mat save_pano = new OpenCvSharp.Mat();
-            OpenCvSharp.Cv2.VConcat(list_mats, save_pano);
-            OpenCvSharp.Cv2.ImWrite(sfd.FileName, save_pano);
-            NLog.LogManager.GetCurrentClassLogger().Info("Save complete.");
         }
        
         private List<DataTable> opencv_piclist_Render()

+ 1 - 1
OTSIncAReportApp/1-UI/frmReMeasure.cs

@@ -565,7 +565,7 @@ namespace OTSIncAReportApp
         {
             if (particle.XRayData == null)
             {
-                control_XRayTable1.Visible = false;
+                //control_XRayTable1.Visible = false;
                 return;
             }
             //显示xray相关信息