核心函数:
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.InitWithRect
或GrabCutModes.InitWithMask
。默认是GrabCutModes.Eval
。
函数的工作流程如下:
- 根据提供的矩形框和掩码,初始化背景和前景模型。
- 迭代执行以下步骤:
- 通过估计当前模型,将未知区域分为前景和背景。
- 更新模型参数,使其更好地拟合分割结果。
- 根据模型,重新分配未知区域。
- 返回分割结果,即更新后的掩码图像,其中前景区域被标记为前景(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(); // 等待用户按键 } } }
结果:
检测目标轮廓以及计算整体面积