using OpenCvSharp; using OpenCvSharp.Extensions; using DlibDotNet; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.Threading; namespace app { public partial class FrmMain : Form { public FrmMain() { InitializeComponent(); } /// <summary> /// 分水岭 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnWatershed_Click(object sender, EventArgs e) { //展示图 Mat src = Cv2.ImRead(@"img\five.png"); Cv2.ImShow("原图", src); // 标记图 // 灰度图片 Mat marker_src = new Mat(); Cv2.CvtColor(src, marker_src, ColorConversionCodes.BGR2GRAY); // 均值滤波 Cv2.Blur(marker_src, marker_src, new OpenCvSharp.Size(5, 5), new OpenCvSharp.Point(-1, -1)); // 降噪 Cv2.Threshold(marker_src, marker_src, 100, 255, ThresholdTypes.BinaryInv); var kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new OpenCvSharp.Size(12, 12)); // 形态学操作 // 闭运算,去除图像中的小黑点 Cv2.MorphologyEx(marker_src, marker_src, MorphTypes.Close, kernel); Mat distance_img = new Mat(); // 距离变换 Cv2.DistanceTransform(marker_src, distance_img, DistanceTypes.L1, DistanceTransformMasks.Mask3, 5); // 归一化 Cv2.Normalize(distance_img, distance_img, 0, 1.0, NormTypes.MinMax); // 二值化 Cv2.Threshold(distance_img, distance_img, 0.5, 1, ThresholdTypes.Binary); distance_img.ConvertTo(distance_img, MatType.CV_8UC1); Cv2.ImShow("distance_img", distance_img * 10000); // 找轮廓 Cv2.FindContours(distance_img, out OpenCvSharp.Point[][] contours, out HierarchyIndex[] outputArray, RetrievalModes.External, ContourApproximationModes.ApproxSimple); Scalar color = new Scalar(255, 0, 0); // 标记 前景markers。标记注水点。 Mat marker_all = Mat.Zeros(marker_src.Size(), MatType.CV_32SC1); // Draw the foreground markers for (int i = 0; i < contours.Length; i++) { // 对各个标记区域填充不同的像素值,后阶段根据像素值区分区域。 Cv2.DrawContours(marker_all, contours, (int)i, new Scalar((int)i + 1), -1); } //int num = contours.Length; //MessageBox.Show(num.ToString()); // 标记 背景markers。Draw the background markers // 画一个圆 Cv2.Circle(marker_all, new OpenCvSharp.Point(15, 15), 10, new Scalar(255), -1); Mat marker_para = new Mat(); marker_all.ConvertTo(marker_para, MatType.CV_8UC3); Cv2.ImShow("分水岭的第二个参数", marker_para * 10000); src.ConvertTo(src, MatType.CV_8UC3); // 分水岭操作 Cv2.Watershed(src, marker_all); Mat marker_para_end = new Mat(); marker_all.ConvertTo(marker_para_end, MatType.CV_8UC3); Cv2.ImShow("分水岭函数 处理过 marker", marker_para_end * 10000); // 生成随机颜色数组 Vec3b[] colors = new Vec3b[contours.Length]; Random rB = new Random(); Random rG = new Random(); Random rR = new Random(); for (int i = 0; i < contours.Length; i++) { var B = rB.Next(50, 98); var G = rG.Next(47, 255); var R = rR.Next(56, 120); RNG rngB = new RNG((ulong)B); RNG rngG = new RNG((ulong)G); RNG rngR = new RNG((ulong)R); //colors[i] = new Vec3b((byte)rngB.Uniform(0, 255), (byte)rngG.Uniform(0, 255), (byte)rngR.Uniform(0, 255)); // colors[i] = new Vec3b((byte)0, (byte)0, (byte)255); } // 输出图像 Mat dest = Mat.Zeros(marker_all.Size(), MatType.CV_8UC3); for (int i = 0; i < marker_all.Rows; i++) { for (int j = 0; j < marker_all.Cols; j++) { int index = marker_all.At<int>(i, j); if (index > 0 && index <= contours.Length) { dest.At<Vec3b>(i, j) = colors[index - 1]; } else { // 填充背景 dest.At<Vec3b>(i, j) = new Vec3b(255, 0, 0); } } } // 同原图相加 Cv2.Absdiff(src, dest, dest); Cv2.ImShow("原图", src); Cv2.ImShow("新图", dest); } } }