c# OpenCvSharp 分水岭 Watershed 分割方法

c# OpenCvSharp 分水岭 Watershed 分割方法

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);

        }

       
    }
}

 

发表回复

您的电子邮箱地址不会被公开。