OpenCvSharp-图像分割Grabcuts算法、检测轮廓及目标面积(源码)

核心函数:

Cv2.Gradcuts() 图像分割Grabcuts算法

将输入图像分割成前景和背景,并将分割结果保存在掩码 mask 中。在输入掩码中,可以通过设置像素的值来指定其属于前景、背景或可能的前景/背景区域。在函数执行后,输出掩码 mask 中的像素值将被更新以表示分割结果。

void Cv2.GrabCut(InputArray img, 
                 InputOutputArray mask, 
                 Rect rect, 
                 InputOutputArray bgdModel, 
                 InputOutputArray fgdModel, 
                 int iterCount, 
                 GrabCutModes mode = GrabCutModes.Eval)
  • img: 输入图像,通常是彩色图像。
  • mask: 输入/输出掩码图像,用于指定前景、背景和可能的前景/背景区域,同时也是输出的分割结果。
  • rect: 感兴趣区域的矩形框,用于初始化分割。
  • bgdModel: 背景模型,内部使用,需要传入一个与图像相同大小的数组。
  • fgdModel: 前景模型,内部使用,需要传入一个与图像相同大小的数组。
  • iterCount: 迭代次数,算法的迭代次数,影响分割的精度。
  • mode: 指定算法的模式,可以是 GrabCutModes.InitWithRectGrabCutModes.InitWithMask。默认是 GrabCutModes.Eval

函数的工作流程如下:

  1. 根据提供的矩形框和掩码,初始化背景和前景模型。
  2. 迭代执行以下步骤:
    • 通过估计当前模型,将未知区域分为前景和背景。
    • 更新模型参数,使其更好地拟合分割结果。
    • 根据模型,重新分配未知区域。
  3. 返回分割结果,即更新后的掩码图像,其中前景区域被标记为前景(1),背景区域被标记为背景(0),可能的前景区域被标记为可能的前景(3),可能的背景区域被标记为可能的背景(2)
  • 代码:

  • using OpenCvSharp;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace 图像分割_Grabcuts算法
    {
        class Program
        {
            static void Main(string[] args)
            {
                Mat src = Cv2.ImRead("C:/Users/CGW/Desktop/digits/5.jpg", ImreadModes.AnyColor); // 读取输入图像
    
                Mat mask = new Mat(); // 存储掩码图像
                Mat bgdModel = new Mat(); // 存储背景模型
                Mat fgdModel = new Mat(); // 存储前景模型
    
                // 使用GrabCut算法进行图像分割,指定感兴趣区域的矩形框作为初始化
                Cv2.GrabCut(src, mask, new OpenCvSharp.Rect(17, 56, 117, 156), bgdModel, fgdModel, 12, GrabCutModes.InitWithRect);
    
                Mat result = new Mat(mask.Rows, mask.Cols, MatType.CV_8UC1); // 创建结果图像
                int foregroundPixels = 0; // 前景像素数量
    
                for (int i = 0; i < mask.Width; i++)
                {
                    for (int j = 0; j < mask.Height; j++)
                    {
                        byte v = mask.Get<byte>(j, i); // 获取掩码图像的像素值
    
                        // 根据掩码像素值设置结果图像的像素值
                        switch (v)
                        {
                            case 0: // 0 表示背景
                                result.Set<byte>(j, i, 255); // 设置为白色
                                break;
                            case 1: // 1 表示前景
                                result.Set<byte>(j, i, 0); // 设置为黑色
                                foregroundPixels++; // 前景像素数量加1
                                break;
                            case 2: // 2 表示可能的背景
                                result.Set<byte>(j, i, 200); // 设置为灰色
                                break;
                            case 3: // 3 表示可能的前景
                                result.Set<byte>(j, i, 0); // 设置为黑色
                                foregroundPixels++;
                                break;
                        }
                    }
                }
    
                Cv2.ImShow("result", result); // 显示分割结果图像
                
    
                Console.WriteLine("Foreground Area: " + foregroundPixels); // 输出前景面积
                Cv2.WaitKey(); // 等待用户按键
            }
        }
    }
    

结果:

检测目标轮廓以及计算整体面积

猜你喜欢

转载自blog.csdn.net/m0_55074196/article/details/132577884
今日推荐