static void Main(string[] args) { #region Mat[] splitall; Mat src; Mat channel_depth = new Mat(); Mat channel_gray = new Mat(); Mat channel_three = new Mat(); Mat element3 = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 1)); Mat element5 = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(3, 3)); FileStorage cld_date = new FileStorage("0924.yaml", FileStorage.Mode.Read); //101161kk.yaml using (var fs = new FileStorage("0924.yaml", FileStorage.Mode.Read)) //0924.yaml { src = fs["vocabulary"].ReadMat(); } Cv2.Split(src, out splitall); splitall[2].ConvertTo(channel_depth, MatType.CV_32FC1); //var window1 = new Window("depth",channel_depth); //Cv2.WaitKey(); splitall[3].ConvertTo(channel_gray, MatType.CV_8UC1); //using (var window = new Window("原始图", WindowMode.Normal, channel_gray)) //{ // Cv2.WaitKey(); //} int imgcols = channel_depth.Cols, imgrows = channel_depth.Rows; Mat model_calc_gray = Mat.Zeros(channel_depth.Rows, channel_depth.Cols, MatType.CV_32FC1); Mat model_gray = Mat.Zeros(channel_depth.Rows, channel_depth.Cols, MatType.CV_8UC1); Mat model_step1 = Mat.Zeros(channel_depth.Rows, channel_depth.Cols, MatType.CV_32FC1); for (int i = 0; i < channel_depth.Rows; i++) { for (int j = 0; j < channel_depth.Cols; j++) { if (channel_depth.At <float>(i, j) < 900) //900时为临界 ==》 0943 { model_calc_gray.Set <float>(i, j, channel_gray.At <Byte>(i, j)); //= channel_gray.At<short>(i, j);//char convert to float that could calcaulate }//方便后面sigmoid计算 else { continue; } } } Mat Edge_one = model_calc_gray.Clone(); for (int i = 0; i < 100; i++) { for (int j = 0; j < model_calc_gray.Cols; j++) { Edge_one.Set <float>(i, j, 0); } } //取反 Mat Edge = Mat.Zeros(channel_depth.Rows, channel_depth.Cols, MatType.CV_32FC1); Edge = new Scalar(255) - Edge_one; // int zero_cout = Cv2.CountNonZero(Edge); //返回矩阵中的非零值个数 Scalar zero_sum = Cv2.Sum(Edge); //对mat类四个通道求和 float matMean = (float)(zero_sum[0] / zero_cout); //对非0像素求均值 float angle = 0.2f; for (int i = 0; i < imgrows; i++) { for (int j = 0; j < imgcols; j++) { if (Edge.At <float>(i, j) != 0) { model_step1.Set <float>(i, j, sigmod(Edge.At <float>(i, j), matMean, angle)); } } } Mat show_change_two = Mat.Zeros(channel_depth.Rows, channel_depth.Cols, MatType.CV_8UC1); Cv2.Normalize(model_step1, show_change_two, 0, 255, NormTypes.MinMax, MatType.CV_8UC1); using (var window = new Window("转换展示图", WindowMode.Normal, show_change_two)) { Cv2.WaitKey(); } /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Cv2.MorphologyEx(show_change_two, show_change_two, MorphTypes.Close, element5, new Point(-1, -1), 10); using (var window = new Window("5次模糊", WindowMode.Normal, show_change_two)) { Cv2.WaitKey(); } Cv2.MorphologyEx(show_change_two, show_change_two, MorphTypes.Dilate, element5, new Point(-1, -1), 8); using (var window = new Window("5次模糊", WindowMode.Normal, show_change_two)) { Cv2.WaitKey(); } #region 注释代码 //Cv2.MorphologyEx(show_change_two, show_change_two, MorphTypes.Erode, element5, new Point(-1, -1), 2); //using (var window = new Window("5次模糊", WindowMode.Normal, show_change_two)) //{ // Cv2.WaitKey(); //} //Cv2.MorphologyEx(show_change_two, show_change_two, MorphTypes.Open, element5, new Point(-1, -1), 10); //using (var window = new Window("5次模糊", WindowMode.Normal, show_change_two)) //{ // Cv2.WaitKey(); //} //for (int num1 = 0; num1 < 5; num1++) // //Cv2.MedianBlur(show_change_two, show_change_two, 5); // Cv2.GaussianBlur(show_change_two, show_change_two, new Size(3, 1), MatType.CV_8UC1); //using (var window = new Window("10次中值", WindowMode.Normal, show_change_two)) //{ // Cv2.WaitKey(); //} //Cv2.MorphologyEx(show_change_two, show_change_two, MorphTypes.Close, element5, new Point(-1, -1), 3); //using (var window = new Window("5比原算", WindowMode.Normal, show_change_two)) //{ // Cv2.WaitKey(); //} //for (int num1 = 0; num1 < 10; num1++) // Cv2.GaussianBlur(show_change_two, show_change_two, new Size(1, 3), MatType.CV_8UC1); //using (var window = new Window("5次模糊", WindowMode.Normal, show_change_two)) //{ // Cv2.WaitKey(); //} //Cv2.MorphologyEx(show_change_two, show_change_two, MorphTypes.Dilate, element3, new Point(-1, -1), 3); ////调试结果较好,二值化之前都不要对图像进行滤波,会丧失边界 //Cv2.Dilate(show_change_two, show_change_two, element3, new Point(-1, -1), 5); //using (var window = new Window("5膨胀", WindowMode.Normal, show_change_two)) //{ // Cv2.WaitKey(); //} // Cv2.Dilate(show_change_two, show_change_two, element5, new Point(-1, -1), 5); //using (var window = new Window("5次腐蚀", WindowMode.Normal, show_change_two)) //{ // Cv2.WaitKey(); //} // for (int num1 = 0; num1 < 10; num1++) // Cv2.MedianBlur(show_change_two, show_change_two, 5); //// Cv2.GaussianBlur(show_change_two, show_change_two, new Size(1, 3), MatType.CV_8UC1); // using (var window = new Window("10次中值", WindowMode.Normal, show_change_two)) // { // Cv2.WaitKey(); // } // int a = 0; //Cv2.Threshold(show_change_two, show_change_two, 0, 255,ThresholdTypes.Otsu); //PixelConnectivity pixelConnectivity =new PixelConnectivity(); //Cv2.ConnectedComponents(show_change_two, show_change_two, 4); //////Cv2.MedianBlur(show_change_two, show_change_two, 5); //using (var window = new Window("结果二值", WindowMode.Normal, show_change_two)) //{ // Cv2.WaitKey(); //} //for (int num1 = 0; num1 < 10; num1++) // Cv2.MedianBlur(show_change_two, show_change_two, 5); //// Cv2.GaussianBlur(show_change_two, show_change_two, new Size(1, 3), MatType.CV_8UC1); //using (var window = new Window("10次中值", WindowMode.Normal, show_change_two)) //{ // Cv2.WaitKey(); //} //int a = 0; #endregion #endregion /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Mat Sobel_Edge = new Mat(); Mat Sobel_result = Mat.Zeros(imgrows, imgcols, MatType.CV_8UC1); Cv2.Sobel(show_change_two, Sobel_Edge, MatType.CV_16SC1, 4, 0, 5, 1, 0, BorderTypes.Default); Cv2.ConvertScaleAbs(Sobel_Edge, Sobel_result); Cv2.Threshold(Sobel_result, Sobel_result, 20, 255, ThresholdTypes.Otsu); using (var window = new Window("sobel结果二值", WindowMode.Normal, Sobel_result)) { Cv2.WaitKey(); } //for (int num1 = 0; num1 < 3; num1++) ////Cv2.MedianBlur(Sobel_result, Sobel_result, 3); // Cv2.GaussianBlur(Sobel_result, Sobel_result, new Size(1, 3), MatType.CV_8UC1); //using (var window = new Window("10次模糊", WindowMode.Normal, Sobel_result)) //{ // Cv2.WaitKey(); //} //Mat img_step2 = new Mat(); //Cv2.MorphologyEx(Sobel_result, Sobel_result, MorphTypes.Open, element5, new Point(-1, -1), 1); //using (var window = new Window("sobel5后膨胀", WindowMode.Normal, Sobel_result)) //{ // Cv2.WaitKey(); //} Mat result = Mat.Zeros(imgrows, imgcols, MatType.CV_8UC1); Point[][] contours_one; HierarchyIndex[] hierarchy_one; Cv2.FindContours(Sobel_result.Clone(), out contours_one, out hierarchy_one, RetrievalModes.External, ContourApproximationModes.ApproxSimple, new Point(0, 0)); List <Point[]> afterFilter = new List <Point[]>(); Console.WriteLine("轮廓数量" + contours_one.Length); for (int c = 0; c < contours_one.Length; c++) { Console.WriteLine("轮廓" + c + "长度" + contours_one[c].Length); } //vector<vector<Point>>::iterator itc = contours_one.begin(); for (int c = 0; c < contours_one.Length; c++) { double area = Cv2.ContourArea(contours_one[c]); Console.WriteLine(area); if (area > 800) { afterFilter.Add(contours_one[c]); } } Cv2.DrawContours(result, afterFilter, -1, new Scalar(255), -1); using (var window = new Window("去除小面积结果图", WindowMode.Normal, result)) { Cv2.WaitKey(); } ////for (int num = 0; num < 5; num++) //// Cv2.Dilate(result, result, element3); //using (var window = new Window("连接下面的部分5次膨胀结果图", WindowMode.Normal, result)) //{ // Cv2.WaitKey(); //} Cv2.MorphologyEx(result, result, MorphTypes.Close, element3, new Point(-1, -1), 5); using (var window = new Window("闭运算再次迭代10次结果图", result)) { Cv2.WaitKey(); } Mat result1 = Mat.Zeros(imgrows, imgcols, MatType.CV_8UC1); Point[][] contours_one1; HierarchyIndex[] hierarchy_one1; Cv2.FindContours(result.Clone(), out contours_one1, out hierarchy_one1, RetrievalModes.External, ContourApproximationModes.ApproxSimple, new Point(0, 0)); List <Point[]> afterFilter1 = new List <Point[]>(); Console.WriteLine(contours_one1.Length); //vector<vector<Point>>::iterator itc = contours_one.begin(); for (int c = 0; c < contours_one1.Length; c++) { double area = Cv2.ContourArea(contours_one1[c]); Console.WriteLine(area); if (area > 3000) { afterFilter1.Add(contours_one1[c]); } } Cv2.DrawContours(result1, afterFilter1, -1, new Scalar(255), -1); using (var window = new Window("再次去除小面积结果图", WindowMode.Normal, result1)) { Cv2.WaitKey(); } Mat result_uchar = Mat.Zeros(imgrows, imgcols, MatType.CV_8UC1); result1.ConvertTo(result_uchar, MatType.CV_8UC1); Point[][] contours_three; HierarchyIndex[] hierarchy_three; Cv2.FindContours(result_uchar.Clone(), out contours_three, out hierarchy_three, RetrievalModes.External, ContourApproximationModes.ApproxSimple, new Point(0, 0)); Mat rectangle_one = Mat.Zeros(imgrows, imgcols, MatType.CV_8UC3); Rect[] boundRect_one = new Rect[contours_three.Length]; //定义外接矩形集合 RotatedRect[] box_one = new RotatedRect[contours_three.Length]; Point2f[] rect_one = new Point2f[4]; Console.WriteLine("最终边界数量:" + contours_three.Length); List <Point2f[]> rec_vec = new List <Point2f[]>(contours_three.Length); float[] center_one_x = new float[contours_three.Length]; float[] center_one_y = new float[contours_three.Length]; for (int i = 0; i < contours_three.Length; i++) { box_one[i] = Cv2.MinAreaRect(contours_three[i]); //计算外接旋转矩形 boundRect_one[i] = Cv2.BoundingRect(contours_three[i]); //计算每个轮廓最小外接矩形 Cv2.Circle(rectangle_one, new Point(box_one[i].Center.X, box_one[i].Center.Y), 5, new Scalar(0, 255, 0), -1); //绘制最旋转矩形的中心点 rect_one = box_one[i].Points(); //把最小外接矩形四个端点复制给rect数组 复制构造 Cv2.Rectangle(rectangle_one, boundRect_one[i], new Scalar(0, 255, 0), 5); //画最小外接矩形 center_one_x[i] = box_one[i].Center.X; center_one_y[i] = box_one[i].Center.Y; //cout << "end" <<center_one.size() << endl; for (int j = 0; j < 4; j++) { Cv2.Line(rectangle_one, (Point)rect_one[j], (Point)rect_one[(j + 1) % 4], new Scalar(0, 0, 255), 2); //绘制旋转矩形每条边 // rec_vec[i].push_back(rect_one[j]); /*cout << "第"<<j<<"个角点"<< rect[j] << endl;*/ } using (var window = new Window("绘制最小外接矩形结果图", WindowMode.Normal, rectangle_one)) { Cv2.WaitKey(); } } int[] ind = new int[center_one_x.Length]; BubbleSort(center_one_x, ind); for (int i = 0; i < contours_three.Length - 1; i++) { // cout << "ind" << ind[i] << endl; Point point_one; point_one.X = boundRect_one[ind[i]].X + boundRect_one[ind[i]].Width / 2; point_one.Y = boundRect_one[ind[i]].Y; Point point_two; point_two.X = boundRect_one[ind[i + 1]].X + boundRect_one[ind[i + 1]].Width / 2; point_two.Y = boundRect_one[ind[i + 1]].Y + boundRect_one[ind[i + 1]].Height; Point point_three; point_three = point_two - point_one; point_three.X = Math.Abs(point_three.X); point_three.Y = Math.Abs(point_three.Y); Rect rect = new Rect(point_one.X, point_one.Y, point_three.X, point_three.Y); Mat capture_one = channel_gray[rect]; //imshow("截图第一幅图结果图", capture_one); using (var window = new Window("截图第一幅图结果图", WindowMode.Normal, capture_one)) { Cv2.WaitKey(); } Point point_four; point_four.X = point_one.X + point_three.X / 2; point_four.Y = point_one.Y + 100; Cv2.Circle(channel_gray, point_four, 9, new Scalar(0, 0, 255)); Console.WriteLine("贴标X:" + splitall[0].At <float>(point_four.Y, point_four.X)); Console.WriteLine("贴标Y:" + splitall[1].At <float>(point_four.Y, point_four.X)); Console.WriteLine("贴标Z:" + splitall[2].At <float>(point_four.Y, point_four.X)); using (var window = new Window("截图第一幅圈圈", WindowMode.Normal, channel_gray)) { Cv2.WaitKey(); } Point point_five; point_five.X = point_one.X + point_three.Y / 2; point_five.Y = point_one.Y + 200; Cv2.Circle(channel_gray, point_five, 9, new Scalar(0, 0, 255)); Console.WriteLine("喷码X:" + splitall[0].At <float>(point_five.Y, point_five.X)); Console.WriteLine("喷码Y:" + splitall[1].At <float>(point_five.Y, point_five.X)); Console.WriteLine("喷码Z:" + splitall[2].At <float>(point_five.Y, point_five.X)); using (var window = new Window("截图第二幅圈圈", WindowMode.Normal, channel_gray)) { Cv2.WaitKey(); } } }