C#+OpenCV基础(十五)_图像的基础分割方法
1、GrabCut人为干预分割前景
/// <summary>
/// 检测边缘并标注(GrabCut人为干预分割前景;速度比分水岭算法慢,结果准确性高)
/// </summary>
/// <param name="img">图片</param>
/// <param name="rect">前景物体矩形区域;new Rect(100, 100, 200, 200)</param>
/// <param name="dstMat">结果图片</param>
/// <param name="bgdModel">背景图</param>
/// <param name="fgdModel">前景图</param>
/// <param name="iterCount">迭代次数</param>
/// <param name="mode">初始化的模式;默认为矩形初始化</param>
public static Mat GrabCut(Mat img, Rect rect, out Mat dstMat,
out Mat bgdModel, out Mat fgdModel, int iterCount = 1, GrabCutModes mode = GrabCutModes.InitWithRect)
{
Mat dstMat1 = new Mat();
dstMat = new Mat();
bgdModel = new Mat();
fgdModel = new Mat();
Cv2.GrabCut(img, dstMat, rect, bgdModel, fgdModel, iterCount, mode);
Cv2.Compare(img, dstMat, dstMat1, CmpType.EQ);
return dstMat1;
}
2、漫水填充分割
/// <summary>
/// 检测边缘并标注(漫水填充;类似于PS的魔术棒,适合于对二值图处理)
/// </summary>
/// <param name="image">图片/结果图片</param>
///// <param name="mask">操作掩码;但是不会填充非零像素</param>
/// <param name="seedPoint">起始点</param>
/// <param name="newVal">被染色的值</param>
/// <param name="rect">设置重绘区域的最小边界矩形区域</param>
/// <param name="loDiff">最小色差值</param>
/// <param name="upDiff">最大色差值</param>
/// <param name="flags">操作标志位</param>
/// <returns></returns>
public static int FloodFill(InputOutputArray image, Point seedPoint, Scalar newVal, out Rect rect,
Scalar? loDiff = null, Scalar? upDiff = null, FloodFillFlags flags = FloodFillFlags.Link4)
=> Cv2.FloodFill(image, seedPoint, newVal, out rect, loDiff, upDiff, flags);
3、分水岭分割
/// <summary>
/// 分水岭分割
/// </summary>
/// <param name="image">图片</param>
/// <param name="markers">掩码</param>
/// <returns></returns>
public static void Watershed(InputArray image, InputOutputArray markers) => Cv2.Watershed(image, markers);
/// <summary>
/// 检测边缘并标注(分水岭分割)
/// 先在外面找边缘-比如:先图像灰度化、再滤波、再Canny边缘检测;如使用MarginDetector_Sobel或者MarginDetector_Canny
/// 再传入原始图像和边缘信息
/// </summary>
/// <param name="image">图片</param>
/// <param name="points">轮廓集合</param>
/// <param name="hierarchy">历史轮廓</param>
/// <returns></returns>
public static Mat Watershed_Draw(Mat image, Point[][] points, HierarchyIndex[] hierarchy)
{
Mat imageContours = Mat.Zeros(image.Size(), MatType.CV_8UC1); // 轮廓
Mat markers = new Mat(image.Size(), MatType.CV_32S); // 第二个参数
for (int index = 0; index < hierarchy.Length; index++)
{
Cv2.DrawContours(markers, points, index, Scalar.All(index + 1), 1, LineTypes.Link8, hierarchy);
Cv2.DrawContours(imageContours, points, index, new Scalar(255), 1, LineTypes.Link8, hierarchy);
}
// 分水岭分割
Cv2.Watershed(image, markers);
// 填充颜色
Mat perspectiveImage = new Mat(image.Size(), MatType.CV_8UC3);
for (int i = 0; i < markers.Size().Height; i++)
{
for (int j = 0; j < markers.Size().Width; j++)
{
int index = markers.At<int>(i, j);
if (index == -1)
{
perspectiveImage.At<Vec3b>(i, j) = new Vec3b(255, 255, 255);
}
else
{
perspectiveImage.At<Vec3b>(i, j) = RandomColor(index);
}
}
}
Mat wshed = new Mat();
Cv2.AddWeighted(image, 0.4, perspectiveImage, 0.6, 0, wshed);
return wshed;
}
/// <summary>
/// 随机颜色
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
/// <exception cref="NotImplementedException"></exception>
private static Vec3b RandomColor(int index)
{
int value = index % 255; // 0~255随机数
Random random = new Random();
byte aa = Convert.ToByte(random.Next(0, value));
byte bb = Convert.ToByte(random.Next(0, value));
byte cc = Convert.ToByte(random.Next(0, value));
return new Vec3b(aa, bb, cc);
}
本文来自博客园,作者:꧁执笔小白꧂,转载请注明原文链接:https://www.cnblogs.com/qq2806933146xiaobai/p/18295551