using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using OpenCvSharp; using System.Runtime.InteropServices; namespace NewSegDll { class InParameter { public int iMethod; public Mat MGryImg; public Mat MHesOutImage; public Mat MValley; public int iDimA; public int iDimB; public int iXiHua; public int iLianJie; //for Method2 public Mat MEdgeOutImage; //for Method3 public Form1 m_fmForMethod3; public int[] m_aiTrackBarMethod3; public Mat m_Mbinaryzation; public int m_iWhichBlur = 0; public int m_iMethod3DoSeg = 0; } public class NewSeg { Mat m_MOrgImg; public Mat m_MOutImg; double[] m_adOutParam; InParameter m_InParam; public int DoSeg(Mat _MOrgImg, Mat _MOutImg, double[] _adOutParam) { m_MOrgImg = _MOrgImg; m_MOutImg = _MOutImg; m_adOutParam = _adOutParam; PrepareParameter(); if(2 == m_InParam.iMethod) { DetectEdge(); return 2; } else if(3 == m_InParam.iMethod) { ShowMethod3Form(); return 3; } ////Cv2.ImShow("[原图]", m_InParam.MGryImg); ////Cv2.WaitKey(0); //ImgHessian(); //FindValley(); //FindShed(); return 1; } private int PrepareParameter() { m_InParam = new InParameter(); m_InParam.MGryImg = new Mat(); m_InParam.m_fmForMethod3 = new Form1(); m_InParam.m_aiTrackBarMethod3 = new int[6]; m_InParam.m_aiTrackBarMethod3[0] = 0; m_InParam.m_aiTrackBarMethod3[1] = 120; m_InParam.m_aiTrackBarMethod3[2] = 1; m_InParam.m_aiTrackBarMethod3[3] = 2; m_InParam.m_aiTrackBarMethod3[4] = 5; m_InParam.m_aiTrackBarMethod3[5] = 1; m_InParam.m_Mbinaryzation = new Mat(); //转为为灰度? if (3 == m_MOrgImg.Channels()) { Cv2.CvtColor(m_MOrgImg, m_InParam.MGryImg, ColorConversionCodes.RGB2GRAY); } else { if (1 == m_MOrgImg.Channels()) { m_InParam.MGryImg = m_MOrgImg.Clone(); } else { return -1; } } m_InParam.iMethod = 1; m_InParam.iDimA = 3; m_InParam.iDimB = 1; bool bFanSe = false; int iTiaoZheng = 0; double dTZXS = 1.0; double dK = 1.0; double dB = 0.0; m_InParam.iXiHua = 0; m_InParam.iLianJie = 0; if (m_adOutParam != null) { /* if((m_adOutParam[0] > 1.5)&&(m_adOutParam[0] < 2.5)) { m_InParam.iMethod = 2; } if ((m_adOutParam[0] > 2.5) && (m_adOutParam[0] < 3.5)) { m_InParam.iMethod = 3; } */ m_InParam.iMethod = (int)(m_adOutParam[0] + 0.5); if ((m_adOutParam[1] > m_adOutParam[0]) && (m_adOutParam[1] < 2.5)) { bFanSe = true; } if ((m_adOutParam[2] > 0.5) && (m_adOutParam[2] < 100.5)) { m_InParam.iDimA = (int)(m_adOutParam[2] + 0.5); } if ((m_adOutParam[3] > 0.5) && (m_adOutParam[3] < 100.5)) { m_InParam.iDimB = (int)(m_adOutParam[3] + 0.5); } if ((m_adOutParam[4] > 1.5) && (m_adOutParam[4] < 2.5)) { iTiaoZheng = 2; dTZXS = Math.Max(m_adOutParam[5], 1.0); } else if ((m_adOutParam[4] > 2.5) && (m_adOutParam[4] < 3.5)) { iTiaoZheng = 3; dTZXS = Math.Max(m_adOutParam[5], 1.0); } else if ((m_adOutParam[4] > 3.5) && (m_adOutParam[4] < 4.5)) { iTiaoZheng = 4; dK = m_adOutParam[6]; dB = m_adOutParam[7]; } if ((m_adOutParam[8] > 1.5) && (m_adOutParam[8] < 2.5)) { m_InParam.iXiHua = 2; } if ((m_adOutParam[9] > 1.5) && (m_adOutParam[9] < 2.5)) { m_InParam.iLianJie = 2; } } if ((bFanSe) || (iTiaoZheng > 1)) { int Rows = m_InParam.MGryImg.Rows; int Cols = m_InParam.MGryImg.Cols; int[] point = new int[2]; //Vec3b redcol = new Vec3b(0, 0, 255); for (point[0] = 0; point[0] < Rows; point[0]++) { for (point[1] = 0; point[1] < Cols; point[1]++) { Byte bTemp = m_InParam.MGryImg.At(point); if (bFanSe) { bTemp = (Byte)(255 - bTemp); } if (2 == iTiaoZheng) { bTemp = (Byte)((double)bTemp / dTZXS + 0.5); } if (3 == iTiaoZheng) { double dtt = 255.0 - bTemp; dtt = dtt / dTZXS; bTemp = (Byte)(255 - dtt + 0.5); } if (4 == iTiaoZheng) { double dtt = dK * bTemp + dB; dtt = Math.Min(Math.Max(dtt, 0.0), 255.0); bTemp = (Byte)(dtt + 0.5); } m_InParam.MGryImg.Set(point, bTemp); } } } m_InParam.MHesOutImage = new Mat(); m_InParam.MValley = new Mat(); m_InParam.MEdgeOutImage = new Mat(); return 1; } private int ShowMethod3Form() { m_InParam.m_fmForMethod3.m_aiTrackBarMethod3 = m_InParam.m_aiTrackBarMethod3; m_InParam.m_fmForMethod3.m_MOrgImg = m_MOrgImg; m_InParam.m_fmForMethod3.MGryImg = m_InParam.MGryImg; m_InParam.m_fmForMethod3.m_Mbinaryzation = m_InParam.m_Mbinaryzation; m_InParam.m_fmForMethod3.m_iWhichBlur = m_InParam.m_iWhichBlur; m_InParam.m_fmForMethod3.NSeg = this; m_InParam.m_fmForMethod3.ShowDialog(); //m_InParam.m_iWhichBlur = m_InParam.m_fmForMethod3.m_iWhichBlur; //m_InParam.m_iMethod3DoSeg = m_InParam.m_fmForMethod3.m_iMethod3DoSeg; //if (1 == m_InParam.m_iMethod3DoSeg) //{ // Method3DoSeg(); //} return 1; } public int Method3DoSegButonClickAction() { m_InParam.m_iWhichBlur = m_InParam.m_fmForMethod3.m_iWhichBlur; m_InParam.m_iMethod3DoSeg = m_InParam.m_fmForMethod3.m_iMethod3DoSeg; m_InParam.m_fmForMethod3.m_Mbinaryzation.CopyTo(m_InParam.MValley); FindShed(); return 1; } private int Method3DoSeg() { m_InParam.m_fmForMethod3.m_Mbinaryzation.CopyTo(m_InParam.MValley); FindShed(); return 1; } private int DetectEdge() { /* int height = m_InParam.MGryImg.Rows; int width = m_InParam.MGryImg.Cols; int SUB_WIDTH = 50,SUB_HEIGHT = 50; int M = width / SUB_WIDTH, N = height / SUB_HEIGHT; Mat image_cut; m_InParam.MValley = new Mat(height, width, MatType.CV_8UC1,Scalar.All(0)); for(int j = 0; j < N; j ++) { for (int i = 0; i < M; i++) { Rect rect = new Rect(i * SUB_WIDTH, j * SUB_HEIGHT, SUB_WIDTH, SUB_HEIGHT); image_cut = new Mat(m_InParam.MGryImg, rect); double min,max; Point minloc,maxloc; Cv2.MinMaxLoc(image_cut, out min, out max, out minloc, out maxloc); m_InParam.MValley.Set(maxloc.Y + j * SUB_HEIGHT, maxloc.X + i * SUB_WIDTH,255); } } */ Mat JDMGryImg = new Mat(); Cv2.Resize(m_InParam.MGryImg, JDMGryImg, new Size(m_InParam.MGryImg.Cols * 0.2, m_InParam.MGryImg.Rows * 0.2), 0, 0, InterpolationFlags.Linear); Cv2.Sobel(JDMGryImg, m_InParam.MEdgeOutImage, -1, 1, 1, 3); Cv2.Threshold(m_InParam.MEdgeOutImage, m_InParam.MEdgeOutImage, 20, 255, ThresholdTypes.Binary); Mat JDMEdge = new Mat(); Cv2.Canny(JDMGryImg, JDMEdge, 50, 50, 3); m_InParam.MEdgeOutImage = m_InParam.MEdgeOutImage | JDMEdge; //Cv2.Threshold(m_InParam.MGryImg, m_InParam.MEdgeOutImage, 170, 255, ThresholdTypes.BinaryInv); Mat kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(7,7), new Point(-1, -1)); Cv2.MorphologyEx(m_InParam.MEdgeOutImage, m_InParam.MEdgeOutImage, MorphTypes.Close, kernel); Mat MTemp0 = new Mat(); Cv2.Threshold(JDMGryImg, MTemp0, 150, 255, ThresholdTypes.BinaryInv); m_InParam.MEdgeOutImage = m_InParam.MEdgeOutImage & MTemp0; //kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(2, 2), new Point(-1, -1)); //Cv2.MorphologyEx(m_InParam.MEdgeOutImage, m_InParam.MEdgeOutImage, MorphTypes.Erode, kernel); //ImgThin(m_InParam.MEdgeOutImage,-1); //Cv2.ImShow("211", m_InParam.MEdgeOutImage); //Cv2.WaitKey(0); //LTQY(); //Mat MTemp1 = new Mat(); //Cv2.Resize(m_InParam.MEdgeOutImage, MTemp1, new Size(m_InParam.MGryImg.Cols * 0.2, m_InParam.MGryImg.Rows * 0.2), 0, 0, InterpolationFlags.Linear); //Cv2.ConnectedComponentsWithAlgorithm //ImgThin(MTemp); ConnectionBoundary(m_InParam.MEdgeOutImage, 108); Mat MTemp2 = new Mat(); Cv2.BitwiseNot(m_InParam.MEdgeOutImage, MTemp2); kernel = Cv2.GetStructuringElement(MorphShapes.Cross, new Size(7, 7), new Point(-1, -1)); Cv2.MorphologyEx(MTemp2, MTemp2, MorphTypes.Erode, kernel); //Cv2.ImShow("216", MTemp2); //Cv2.WaitKey(0); Mat MTemp3 = new Mat(); Cv2.Resize(m_MOrgImg, MTemp3, new Size(MTemp2.Cols, MTemp2.Rows), 0, 0, InterpolationFlags.Linear); Mat watermark = new Mat(MTemp2.Size(), MatType.CV_32S); Point[][] contour; HierarchyIndex[] hier; Cv2.FindContours(MTemp2, out contour, out hier, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, null); for (int i = 0; i < hier.Length; i++) { Cv2.DrawContours(watermark, contour, i, Scalar.All(i + 1), 1, LineTypes.Link8, hier); } Cv2.Watershed(MTemp3, watermark);//mmmmm Mat MTemp4 = new Mat(MTemp3.Rows, MTemp3.Cols, MatType.CV_8UC1, Scalar.All(0)); int Rows = watermark.Rows; int Cols = watermark.Cols; int[] point = new int[2]; //Vec3b redcol = new Vec3b(0, 0, 255); for (point[0] = 0; point[0] < Rows; point[0]++) { for (point[1] = 0; point[1] < Cols; point[1]++) { if (0 >= watermark.At(point[0], point[1])) { MTemp4.Set(point, 255); } } } //Cv2.ImShow("219", MTemp4); //Cv2.WaitKey(0); Cv2.Resize(MTemp4, MTemp4, new Size(m_InParam.MGryImg.Cols, m_InParam.MGryImg.Rows), 0, 0, InterpolationFlags.Linear); //Cv2.Resize(MTemp, m_InParam.MEdgeOutImage, new Size(m_InParam.MGryImg.Cols, m_InParam.MGryImg.Rows), 0, 0, InterpolationFlags.Linear); //Cv2.ImShow("215", MTemp4); //Cv2.ImWrite("D:\\temp.bmp", m_InParam.MEdgeOutImage); //Cv2.ImShow("212", m_InParam.MValley); //Cv2.WaitKey(0); //Cv2.ImShow("219", MTemp4); //Cv2.WaitKey(0); Cv2.Resize(MTemp4, MTemp4, new Size(m_InParam.MGryImg.Cols, m_InParam.MGryImg.Rows), 0, 0, InterpolationFlags.Linear); //int[] point = new int[2]; Vec3b redcol = new Vec3b(0, 0, 255); Rows = m_MOutImg.Rows; Cols = m_MOutImg.Cols; for (point[0] = 0; point[0] < Rows; point[0]++) { for (point[1] = 0; point[1] < Cols; point[1]++) { if (120 < MTemp4.At(point[0], point[1])) { m_MOutImg.Set(point, redcol); } } } /* Cv2.BitwiseNot(m_InParam.MEdgeOutImage, m_InParam.MValley); Size bianjieSize = m_InParam.MValley.Size(); Mat Temp = Mat.Zeros(bianjieSize.Height + 2, bianjieSize.Width + 2, m_InParam.MValley.Type());//延展图像 m_InParam.MValley.CopyTo(Temp.SubMat(new Range(1, bianjieSize.Height + 1), new Range(1, bianjieSize.Width + 1))); Cv2.FloodFill(Temp, new Point(0, 0), new Scalar(255)); Mat cutImg = new Mat(); Temp.SubMat(new Range(1, bianjieSize.Height + 1), new Range(1, bianjieSize.Width + 1)).CopyTo(cutImg); Cv2.BitwiseNot(cutImg, cutImg); m_InParam.MValley = m_InParam.MValley | cutImg; kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(2, 2), new Point(-1, -1)); Cv2.MorphologyEx(m_InParam.MValley, m_InParam.MValley, MorphTypes.Close, kernel); Cv2.ImShow("213", m_InParam.MValley); Cv2.WaitKey(0); */ return 1; } public int LTQY() { Mat img_bool, labels = new Mat(), stats = new Mat(), centroids = new Mat(), img_color; img_bool = m_InParam.MEdgeOutImage; int nccomps = Cv2.ConnectedComponentsWithStats ( img_bool, //二值图像 labels, //和原图一样大的标记图 stats, //nccomps×5的矩阵 表示每个连通区域的外接矩形和面积(pixel) centroids //nccomps×2的矩阵 表示每个连通区域的质心 ); //显示原图统计结果 char[] title = new char[1024]; //sprintf(title,"原图中连通区域数:%d\n",nccomps); //cv::String num_connect(title); //cv::imshow(num_connect, img_bool); //去除过小区域,初始化颜色表 //vector colors(nccomps); int[] colors = new int[nccomps]; //colors[0] = cv::Vec3b(0,0,0); // background pixels remain black. for(int i = 1; i < nccomps; i++ ) { colors[i] = 255; //去除面积小于100的连通域 if( stats.At(i, 4) < 20 ) colors[i] = 0; // small regions are painted with black too. } //按照label值,对不同的连通域进行着色 img_color = new Mat(img_bool.Rows,img_bool.Cols, MatType.CV_8UC1,Scalar.All(0)); for( int y = 0; y < img_color.Rows; y++ ) for( int x = 0; x < img_bool.Cols; x++ ) { int label = labels.At(y, x); //CV_Assert(0 <= label && label <= nccomps); img_color.Set(y, x,(Byte)colors[label]); } /* //统计降噪后的连通区域 cv::cvtColor(img_color,img_gray,cv::COLOR_BGR2GRAY); cv::threshold(img_gray, img_gray, 1, 255, cv::THRESH_BINARY); nccomps = cv::connectedComponentsWithStats (img_gray, labels,stats,centroids); sprintf(title,"过滤小目标后的连通区域数量:%d\n",nccomps); num_connect = title; */ //Cv2.ImShow("217", img_color); //Cv2.WaitKey(0); return 0; } public void ImgThin(Mat src, int maxIterations = -1) { //if (src.empty()) return;//图像为空,直接返回 Cv2.Threshold(src, src, 100, 1, ThresholdTypes.Binary);//转为0或1的图像 int ImgHeight = src.Rows; int ImgWidth = src.Cols; int count = 0; //记录迭代次数 while (true) { count++; if (maxIterations != -1 && count > maxIterations) //限制次数并且迭代次数到达 break; //vector > mFlag; //用于标记需要删除的点 List mFlag = new List(); //对点标记 for (int i = 0; i < ImgHeight; ++i) { for (int j = 0; j < ImgWidth; ++j) { //如果满足四个条件,进行标记 // p9 p2 p3 // p8 p1 p4 // p7 p6 p5 int p1 = src.At(i, j); int p2 = (i == 0) ? 0 : src.At(i - 1, j); int p3 = (i == 0 || j == ImgWidth - 1) ? 0 : src.At(i - 1, j + 1); int p4 = (j == ImgWidth - 1) ? 0 : src.At(i, j + 1); int p5 = (i == ImgHeight - 1 || j == ImgWidth - 1) ? 0 : src.At(i + 1, j + 1); int p6 = (i == ImgHeight - 1) ? 0 : src.At(i + 1, j); int p7 = (i == ImgHeight - 1 || j == 0) ? 0 : src.At(i + 1, j - 1); int p8 = (j == 0) ? 0 : src.At(i, j - 1); int p9 = (i == 0 || j == 0) ? 0 : src.At(i - 1, j - 1); if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6) { int ap = 0; if (p2 == 0 && p3 == 1) ++ap; if (p3 == 0 && p4 == 1) ++ap; if (p4 == 0 && p5 == 1) ++ap; if (p5 == 0 && p6 == 1) ++ap; if (p6 == 0 && p7 == 1) ++ap; if (p7 == 0 && p8 == 1) ++ap; if (p8 == 0 && p9 == 1) ++ap; if (p9 == 0 && p2 == 1) ++ap; if (ap == 1) { if (p2 * p4 * p6 == 0) { if (p4 * p6 * p8 == 0) { //标记 //mFlag.push_back(make_pair(i, j)); mFlag.Add(new int[2] { i, j }); } } } } } } //将标记的点删除 /* for (Point2d i = mFlag.ForEach; i != mFlag.end(); ++i) { src.At(i->first, i->second) = 0; } */ mFlag.ForEach(delegate(int[] aiP) { src.Set(aiP, 0); }); //直到没有点满足,算法结束 //if (mFlag.size() == 0) break; //else mFlag.clear();//将mFlag清空 if (mFlag.Count() == 0) break; else mFlag.Clear(); //对点标记 for (int i = 0; i < ImgHeight; ++i) { for (int j = 0; j < ImgWidth; ++j) { //如果满足四个条件,进行标记 // p9 p2 p3 // p8 p1 p4 // p7 p6 p5 int p1 = src.At(i, j); if (p1 != 1) continue; int p2 = (i == 0) ? 0 : src.At(i - 1, j); int p3 = (i == 0 || j == ImgWidth - 1) ? 0 : src.At(i - 1, j + 1); int p4 = (j == ImgWidth - 1) ? 0 : src.At(i, j + 1); int p5 = (i == ImgHeight - 1 || j == ImgWidth - 1) ? 0 : src.At(i + 1, j + 1); int p6 = (i == ImgHeight - 1) ? 0 : src.At(i + 1, j); int p7 = (i == ImgHeight - 1 || j == 0) ? 0 : src.At(i + 1, j - 1); int p8 = (j == 0) ? 0 : src.At(i, j - 1); int p9 = (i == 0 || j == 0) ? 0 : src.At(i - 1, j - 1); if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6) { int ap = 0; if (p2 == 0 && p3 == 1) ++ap; if (p3 == 0 && p4 == 1) ++ap; if (p4 == 0 && p5 == 1) ++ap; if (p5 == 0 && p6 == 1) ++ap; if (p6 == 0 && p7 == 1) ++ap; if (p7 == 0 && p8 == 1) ++ap; if (p8 == 0 && p9 == 1) ++ap; if (p9 == 0 && p2 == 1) ++ap; if (ap == 1) { if (p2 * p4 * p8 == 0) { if (p2 * p6 * p8 == 0) { //标记 //mFlag.push_back(make_pair(i, j)); mFlag.Add(new int[2] { i, j }); } } } } } } //删除 /* for (vector >::iterator i = mFlag.begin(); i != mFlag.end(); ++i) { src.At(i->first, i->second) = 0; } */ mFlag.ForEach(delegate(int[] aiP) { src.Set(aiP, 0); }); //直到没有点满足,算法结束 //if (mFlag.size() == 0) break; //else mFlag.clear();//将mFlag清空 if (mFlag.Count() == 0) break; else mFlag.Clear(); } Cv2.Threshold(src, src, 0, 255, ThresholdTypes.Binary);//二值化图像 } public void ConnectionBoundary(Mat Img, int iDistance) { Cv2.Threshold(Img, Img, 100, 1, ThresholdTypes.Binary);//转为0或1的图像 Mat ConnectImg = Connectivity(Img); List mFlag = new List(); List lstaiDirection = new List(); int[] point = new int[2]; for (point[0] = 1; point[0] < (Img.Rows - 1); point[0]++) { for (point[1] = 1; point[1] < (Img.Cols - 1); point[1]++) { if ((1 <= (Img.At(point[0], point[1]))) && (0 == (ConnectImg.At(point[0], point[1])))) { Img.Set(point, 0); } if ((1 <= (Img.At(point[0], point[1]))) && (1 == (ConnectImg.At(point[0], point[1])))) { mFlag.Add(new int[2] { point[0], point[1] }); int i = 0, j = 0; for (i = -1; i <= 1; i++) { bool bFind = false; for (j = -1; j <= 1; j++) { if ((0 == i) && (0 == j)) { continue; } if ((Img.At(point[0] + i, point[1] + j)) >= 1) { bFind = true; break; } } if (bFind) { break; } } lstaiDirection.Add(new int[2] { 0 - i, 0 - j }); } } } int iCount = mFlag.Count(); List[] Development = new List[iCount]; List NotFind = new List(); List Used = new List(); for (int ii = 0; ii < iCount; ii++) { NotFind.Add(ii); int[] pnt = mFlag[ii]; Development[ii] = new List(); Development[ii].Add(new int[2] { pnt[0], pnt[1] }); } Mat TempImg = new Mat(Img.Size(), MatType.CV_32SC1); for (point[0] = 0; point[0] < Img.Rows; point[0]++) { for (point[1] = 0; point[1] < Img.Cols; point[1]++) { int Temp = Img.At(point[0], point[1]); TempImg.Set(point, Temp); } } int[,] Neighbor = new int[260, 2] {{-1,0},{0,1},{1,0},{0,1}/*4*/,{-1,1},{1,1},{1,-1},{-1,-1}/*8*/, {-2,0},{0,2},{2,0},{0,-2}/*12*/,{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,-2},{-2,-1}/*20*/, {-2,2},{2,2},{2,-2},{-2,-2},{-3,0},{0,3},{3,0},{0,-3}/*28*/, {-3,1},{-1,3},{1,3},{3,1},{3,-1},{1,-3},{-1,-3},{-3,-1}/*36*/, {2,3},{-3,2},{-2,-3},{-2,3},{-3,-2},{3,2},{3,-2},{2,-3}, {4,0},{0,4},{-4,0},{0,-4},{1,4},{4,-1},{4,1},{-1,-4},{-4,1},{-4,-1},{-1,4},{1,-4},{3,3},{3,-3},{-3,3}, {-3,-3},{-4,-2},{-2,-4},{-4,2},{4,2},{-2,4},{4,-2},{2,-4},{2,4},{4,-3},{-3,4},{4,3},{5,0},{0,5},{0,-5}, {-5,0},{3,4},{-3,-4},{-4,-3},{3,-4},{-4,3},{5,-1},{-1,5},{-1,-5},{5,1},{1,-5},{-5,1},{-5,-1},{1,5},{-2,5}, {2,-5},{2,5},{5,2},{-5,2},{-2,-5},{5,-2},{-5,-2},{-4,4},{4,-4},{4,4},{-4,-4},{3,-5},{-5,3},{-3,5},{5,-3}, {5,3},{-5,-3},{-3,-5},{3,5}/*108*/,{0,6},{0,-6},{-6,0},{6,0},{-6,1},{1,6},{-6,-1},{1,-6},{-1,6},{-1,-6},{6,-1}, {6,1},{2,6},{-2,-6},{6,2},{-6,2},{2,-6},{-6,-2},{-2,6},{6,-2},{-5,-4},{5,4},{4,5},{-4,5},{4,-5},{-5,4}, {5,-4},{-4,-5},{-3,6},{-6,3},{-3,-6},{-6,-3},{3,-6},{6,3},{3,6},{6,-3},{0,7},{7,0},{0,-7},{-7,0},{5,-5}, {1,7},{-1,7},{-5,-5},{-7,-1},{-7,1},{-1,-7},{1,-7},{7,1},{-5,5},{5,5},{7,-1}/*160*/,{6,4},{-6,4},{6,-4},{-6,-4}, {-4,-6},{4,6},{4,-6},{-4,6},{7,-2},{7,2},{2,7},{-7,-2},{-2,-7},{-2,7},{2,-7},{-7,2}/*176*/,{7,-3},{-3,7},{-3,-7}, {3,-7},{-7,3},{3,7},{7,3},{-7,-3},{6,-5},{5,6},{5,-6},{6,5},{-5,6},{-5,-6},{-6,5},{-6,-5},{8,0},{0,-8}, {-8,0},{0,8},{-4,7},{4,-7},{-8,-1},{-1,8},{-7,4},{-1,-8},{7,4},{1,-8},{1,8},{8,1},{8,-1},{-4,-7},{-7,-4}, {7,-4},{-8,1},{4,7}/*212*/,{-2,8},{2,-8},{-2,-8},{8,2},{-8,2},{-8,-2},{2,8},{8,-2},{-6,6},{6,6},{6,-6},{-6,-6}, {3,-8},{-3,8},{8,3},{8,-3},{3,8},{-3,-8},{-8,3},{-8,-3},{7,-5},{-7,-5},{5,7},{7,5},{5,-7},{-7,5},{-5,-7}, {-5,7}/*240*/,{8,-4},{-4,-8},{-8,-4},{8,4},{4,8},{-8,4},{4,-8},{-4,8},{0,-9},{0,9},{-9,0},{9,0},{9,-1},{-9,-1}, {1,-9},{-1,9},{-1,-9},{-9,1},{1,9},{9,1}/*260*/ }; while (0 != NotFind.Count()) { int ii = NotFind[0]; NotFind.RemoveAt(0); int LastIndex = Development[ii].Count() - 1; int[] pntOld = (Development[ii])[LastIndex]; int[] pnt = new int[2] { pntOld[0], pntOld[1] }; int[] dir = lstaiDirection[ii]; bool bHave = false; for (int nn = 0; nn < iDistance; nn++) { if ((0 > (dir[0] * Neighbor[nn, 0])) || (0 > (dir[1] * Neighbor[nn, 1]))) { continue; } pnt[0] = pntOld[0] + Neighbor[nn, 0]; pnt[1] = pntOld[1] + Neighbor[nn, 1]; if ((0 > pnt[0]) || (Img.Rows <= pnt[0]) || (0 > pnt[1]) || (Img.Cols <= pnt[1])) { continue; } int iThisPnt = TempImg.At(pnt[0], pnt[1]); if ((1 < iThisPnt) && (ii != iThisPnt)) { NotFind.Remove(iThisPnt); if (false == Used.Contains(iThisPnt)) { int FirstOne = (Development[iThisPnt]).FindIndex(t => (t[0] == pnt[0]) && (t[1] == pnt[1])); //.First(t => (t[0] == pnt[0]) && (t[1] == pnt[1])); int LastOne = Development[iThisPnt].Count() - 1; if (1 <= (LastOne - FirstOne)) { for (int jj = FirstOne + 1; jj <= LastOne; jj++) { TempImg.Set((Development[iThisPnt])[jj], 0); } (Development[iThisPnt]).RemoveRange(FirstOne + 1, LastOne - FirstOne); } Used.Add(iThisPnt); Used.Add(ii); } ConnectTwoPnt(pntOld, pnt, Development[ii]); bHave = true; break; } if (1 == iThisPnt) { ConnectTwoPnt(pntOld, pnt, Development[ii]); bHave = true; break; } } if (bHave) { continue; } pnt[0] = pntOld[0] + dir[0]; pnt[1] = pntOld[1] + dir[1]; if ((0 > pnt[0]) || (Img.Rows <= pnt[0]) || (0 > pnt[1]) || (Img.Cols <= pnt[1])) { continue; } /* if(1 <= TempImg.At(pnt[0], pnt[1])) { continue; } */ Development[ii].Add(pnt); TempImg.Set(pnt, ii); NotFind.Add(ii); /* int iThisPnt = TempImg.At(pnt[0], pnt[1]); if (1 < iThisPnt) { NotFind.Remove(iThisPnt); if(false == Used.Contains(iThisPnt)) { int FirstOne = (Development[iThisPnt]).FindIndex(t => (t[0] == pnt[0]) && (t[1] == pnt[1])); //.First(t => (t[0] == pnt[0]) && (t[1] == pnt[1])); int LastOne = Development[iThisPnt].Count() - 1; if(1 <= (LastOne - FirstOne)) { for (int jj = FirstOne + 1; jj <= LastOne; jj++) { TempImg.Set((Development[iThisPnt])[jj], 0); } (Development[iThisPnt]).RemoveRange(FirstOne + 1, LastOne - FirstOne); } Used.Add(iThisPnt); Used.Add(ii); } } else if (0 >= iThisPnt) { Development[ii].Add(pnt); TempImg.Set(pnt, ii); NotFind.Add(ii); } */ } for (int ii = 0; ii < iCount; ii++) { Development[ii].ForEach(delegate(int[] aiP) { Img.Set(aiP, 1); }); } Cv2.Threshold(Img, Img, 0, 255, ThresholdTypes.Binary);//二值化图像 } public void ConnectTwoPnt(int[] pntA, int[] pntB, List DevelopmentA) { int iXThis = pntA[0]; int iYThis = pntA[1]; int iXD = pntB[0] - iXThis; int iYD = pntB[1] - iYThis; int iSignX = 0 == iXD ? 0 : iXD / ((int)(Math.Abs(iXD))); int iSignY = 0 == iYD ? 0 : iYD / ((int)(Math.Abs(iYD))); while ((0 != iXD) || (0 != iYD)) { if ((Math.Abs(iXD)) > (Math.Abs(iYD))) { iXThis += iSignX; } else { iYThis += iSignY; } DevelopmentA.Add(new int[2] { iXThis, iYThis }); iXD = pntB[0] - iXThis; iYD = pntB[1] - iYThis; } } public Mat Connectivity(Mat Img) { Mat TempImg = new Mat(Img.Size(), MatType.CV_8UC1); int[] point = new int[2]; for (point[0] = 1; point[0] < (Img.Rows - 1); point[0]++) { for (point[1] = 0; point[1] < Img.Cols; point[1]++) { byte Temp = Img.At(point[0] - 1, point[1]); Temp += Img.At(point[0], point[1]); Temp += Img.At(point[0] + 1, point[1]); TempImg.Set(point, Temp); } } Mat ConnectImg = new Mat(Img.Size(), MatType.CV_8UC1); for (point[0] = 1; point[0] < (Img.Rows - 1); point[0]++) { for (point[1] = 1; point[1] < (Img.Cols - 1); point[1]++) { byte Temp = TempImg.At(point[0], point[1] - 1); Temp += TempImg.At(point[0], point[1]); Temp += TempImg.At(point[0], point[1] + 1); Temp -= Img.At(point[0], point[1]); ConnectImg.Set(point, Temp); } } TempImg = null; return ConnectImg; } public Mat m_watermark; private int FindShed() { Mat watermark = new Mat(m_InParam.MValley.Size(), MatType.CV_32S); Point[][] contour; HierarchyIndex[] hier; Cv2.FindContours(m_InParam.MValley, out contour, out hier, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, null); for (int i = 0; i < hier.Length; i++) { Cv2.DrawContours(watermark, contour, i, Scalar.All(i + 1), 1, LineTypes.Link8, hier); } //Mat Temp = new Mat(imsegm.Size(), MatType.CV_8UC3); //imsegm.CopyTo(Temp); Cv2.Watershed(m_MOrgImg, watermark);//mmmmm int Rows = watermark.Rows; int Cols = watermark.Cols; int[] point = new int[2]; Vec3b redcol = new Vec3b(0, 0, 255); for (point[0] = 0; point[0] < Rows; point[0]++) { for (point[1] = 0; point[1] < Cols; point[1]++) { if (0 >= watermark.At(point[0], point[1])) { m_MOutImg.Set(point, redcol); } } } m_watermark = watermark.Clone(); //Cv2.ImShow("555", m_MOutImg); //Cv2.WaitKey(0); return 1; } private int FindValley() { //Cv2.BitwiseNot(m_InParam.MHesOutImage, m_InParam.MValley); Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(m_InParam.iDimA, m_InParam.iDimA), new Point(-1, -1)); Cv2.MorphologyEx(m_InParam.MHesOutImage, m_InParam.MHesOutImage, MorphTypes.Close, kernel); //Cv2.ImShow("333", m_InParam.MHesOutImage); //Cv2.WaitKey(0); Cv2.BitwiseNot(m_InParam.MHesOutImage, m_InParam.MValley); //kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(m_InParam.iDimB, m_InParam.iDimB), new Point(-1, -1)); //Cv2.MorphologyEx(m_InParam.MValley, m_InParam.MValley, MorphTypes.Open, kernel); //Cv2.MorphologyEx(m_InParam.MValley, m_InParam.MValley, MorphTypes.Close, kernel); Size bianjieSize = m_InParam.MValley.Size(); Mat Temp = Mat.Zeros(bianjieSize.Height + 2, bianjieSize.Width + 2, m_InParam.MValley.Type());//延展图像 m_InParam.MValley.CopyTo(Temp.SubMat(new Range(1, bianjieSize.Height + 1), new Range(1, bianjieSize.Width + 1))); Cv2.FloodFill(Temp, new Point(0, 0), new Scalar(255)); Mat cutImg = new Mat(); Temp.SubMat(new Range(1, bianjieSize.Height + 1), new Range(1, bianjieSize.Width + 1)).CopyTo(cutImg); Cv2.BitwiseNot(cutImg, cutImg); m_InParam.MValley = m_InParam.MValley | cutImg; //Cv2.ImShow("444", m_InParam.MValley); //Cv2.WaitKey(0); return 1; } private int ImgHessian() { //Mat srcImage = m_InParam.MGryImg; Mat srcImage = new Mat(); m_InParam.MGryImg.ConvertTo(srcImage, MatType.CV_32F); int height = srcImage.Rows; int width = srcImage.Cols; //zk Mat outImage = new Mat(height, width, MatType.CV_8UC1,Scalar.All(0)); int W = 5; double sigma = 1.2; Mat xxGauKernel = new Mat(2 * W + 1, 2 * W + 1, MatType.CV_32FC1, Scalar.All(0)); Mat xyGauKernel = new Mat(2 * W + 1, 2 * W + 1, MatType.CV_32FC1, Scalar.All(0)); Mat yyGauKernel = new Mat(2 * W + 1, 2 * W + 1, MatType.CV_32FC1, Scalar.All(0)); //构建高斯二阶偏导数模板 for (int i = -W; i <= W; i++) { for (int j = -W; j <= W; j++) { double tt1 = (1 - (i * i) / (sigma * sigma)); double tt2 = Math.Exp(-1 * (i * i + j * j) / (2 * sigma * sigma)); double tt3 = (-1 / (2 * Math.PI * Math.Pow(sigma, 4))); double t1 = tt1 * tt2 * tt3; float t2 = (float)t1; //Dxx = 1/(2*pi*sigma^4)*(x.^2/sigma^2-1).*exp(-(x.^2+y.^2)/(2*sigma^2)) //double tt4 = 1.0 / (2.0 * Math.PI * Math.Pow(sigma, 4.0)); //double tt5 = ((double)i * i / (sigma * sigma) - 1); //double tt6 = Math.Exp(-((double)i * i + (double)j * j) / (2 * sigma * sigma)); //float t3 = (float)(tt4*tt5*tt6); xxGauKernel.Set(i + W, j + W, t2); yyGauKernel.Set(i + W, j + W, (float)((1 - (j * j) / (sigma * sigma)) * Math.Exp(-1 * (i * i + j * j) / (2 * sigma * sigma)) * (-1 / (2 * Math.PI * Math.Pow(sigma, 4))))); xyGauKernel.Set(i + W, j + W, (float)(((i * j)) * Math.Exp(-1 * (i * i + j * j) / (2 * sigma * sigma)) * (1 / (2 * Math.PI * Math.Pow(sigma, 6))))); } } /* for (int i = 0; i < (2 * W + 1); i++) { for (int j = 0; j < (2 * W + 1); j++) { cout << xxGauKernel.at(i, j) << " "; } cout << endl; } */ Mat xxDerivae = new Mat(height, width, MatType.CV_32FC1, Scalar.All(0)); Mat yyDerivae = new Mat(height, width, MatType.CV_32FC1, Scalar.All(0)); Mat xyDerivae = new Mat(height, width, MatType.CV_32FC1, Scalar.All(0)); //图像与高斯二阶偏导数模板进行卷积 Cv2.Filter2D(srcImage, xxDerivae, xxDerivae.Depth(), xxGauKernel); Cv2.Filter2D(srcImage, yyDerivae, yyDerivae.Depth(), yyGauKernel); Cv2.Filter2D(srcImage, xyDerivae, xyDerivae.Depth(), xyGauKernel); //Cv2.ImShow("111", xxDerivae); //Cv2.WaitKey(0); //Cv2.ImShow("111", yyDerivae); //Cv2.WaitKey(0); //Cv2.ImShow("111", xyDerivae); //Cv2.WaitKey(0); //zk //Mat tmpImage = new Mat(height, width, MatType.CV_8UC1, Scalar.All(0)); Byte[,] abtmpImage = new Byte[height, width]; float fMavV = 0.0f; float fMinV = 999999.0f; float[] afImXX = new float[height * width]; float[] afImYY = new float[height * width]; float[] afImXY = new float[height * width]; Marshal.Copy(xxDerivae.Data, afImXX, 0, height * width); Marshal.Copy(yyDerivae.Data, afImYY, 0, height * width); Marshal.Copy(xyDerivae.Data, afImXY, 0, height * width); for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { //map best_step; /* int HLx = h - STEP; if (HLx < 0){ HLx = 0; } int HUx = h + STEP; if (HUx >= height){ HUx = height - 1; } int WLy = w - STEP; if (WLy < 0){ WLy = 0; } int WUy = w + STEP; if (WUy >= width){ WUy = width - 1; } float fxx = srcImage.at(h, WUy) + srcImage.at(h, WLy) - 2 * srcImage.at(h, w); float fyy = srcImage.at(HLx, w) + srcImage.at(HUx, w) - 2 * srcImage.at(h, w); float fxy = 0.25*(srcImage.at(HUx, WUy) + srcImage.at(HLx, WLy) - srcImage.at(HUx, WLy) - srcImage.at(HLx, WUy)); */ //float fxx = xxDerivae.At(h, w); //float fyy = yyDerivae.At(h, w); //float fxy = xyDerivae.At(h, w); float fxx = afImXX[h * width + w]; float fyy = afImYY[h * width + w]; float fxy = afImXY[h * width + w]; /* //float myArray[2][2] = { { fxx, fxy }, { fxy, fyy } }; //构建矩阵,求取特征值 float[,] myArray = new float[2, 2] { { fxx, fxy }, { fxy, fyy } }; Mat Array = new Mat(2, 2, MatType.CV_32FC1, myArray); Mat eValue = new Mat(); Mat eVector = new Mat(); Cv2.Eigen(Array, eValue, eVector); //矩阵是降序排列的 float a1 = eValue.At(0, 0); float a2 = eValue.At(1, 0); */ double dT1 = (fxx + fyy) * (fxx + fyy) - 4 * (fxx * fyy - fxy * fxy); if (dT1 < 0) { continue; } dT1 = Math.Sqrt(dT1); double a1 = (fxx + fyy + dT1)/2.0; double a2 = (fxx + fyy - dT1) / 2.0; if ((a1 > 0) && (Math.Abs(a1) > (1 + Math.Abs(a2)))) //根据特征向量判断线性结构 { /* //zk double t1 = Math.Pow((Math.Abs(a1) - Math.Abs(a2)), 4); //double t1 = Math.Pow((Math.Abs(a1) / Math.Abs(a2)) * (Math.Abs(a1) - Math.Abs(a2)), 1.5); float t2 = (float)t1; if(t2 > fMavV) { fMavV = t2; } if (t2 < fMinV) { fMinV = t2; } */ //tmpImage.Set(h, w, 2); //outImage.at(h, w) = pow((ABS(a1) / ABS(a2))*(ABS(a1) - ABS(a2)), 1.5); abtmpImage[h, w] = (Byte)255; } } } //float fSegYuZhi = 1; //(fMavV - fMinV) * 0.00001f + fMinV; //m_InParam.MHesOutImage = new Mat(tmpImage.Size(), MatType.CV_8UC3); //Cv2.Threshold(tmpImage, m_InParam.MHesOutImage, 1, 255, ThresholdTypes.Binary); m_InParam.MHesOutImage = new Mat(height, width, MatType.CV_8UC1, abtmpImage); ; /* //----------做一个闭操作 Mat element = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 2), new Point(-1, -1)); Cv2.MorphologyEx(outImage, outImage, MorphTypes.Close, element); Cv2.ImWrite("D:\\temp.bmp", outImage); */ //Cv2.ImShow("222", m_InParam.MHesOutImage); //Cv2.WaitKey(0); //Cv2.ImWrite("D:\\temp.bmp", m_InParam.MHesOutImage); return 0; } } }