You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过C#从Background Subtraction中为人体目标绘制矩形框?

嘿,我来帮你解决这个问题!在C#里从背景减除的结果中给人体目标绘制矩形框,其实可以拆解成几个清晰的步骤,我会结合代码示例给你讲明白,你可以直接上手试试。

核心思路

背景减除后你会得到一张前景掩码(二值图像,白色代表前景目标、黑色代表背景)。接下来咱们要做的就是:

  1. 对掩码做预处理,去掉干扰噪点
  2. 检测掩码中的所有前景轮廓
  3. 筛选出符合人体特征的轮廓
  4. 给筛选后的轮廓绘制 bounding box(矩形框)

1. 预处理前景掩码(去噪)

背景减除的结果往往会带有一些小噪点,比如零星的白色小点,这些会干扰后续的轮廓检测。咱们可以用形态学开运算来去掉这些噪点:

using OpenCvSharp;
using System.Collections.Generic;

// 假设你已经得到了背景减除后的前景掩码foregroundMask
Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));
// 开运算:先腐蚀再膨胀,去掉小噪点
Cv2.MorphologyEx(foregroundMask, foregroundMask, MorphTypes.Open, kernel);

2. 检测前景轮廓

接下来用OpenCV的轮廓检测函数,从掩码里提取所有前景轮廓。这里建议只提取最外层轮廓(RetrievalModes.External),避免嵌套轮廓的干扰:

List<Point[]> contours = new List<Point[]>();
Mat hierarchy = new Mat();
// 查找轮廓,ApproxSimple用来简化轮廓点,减少计算量
Cv2.FindContours(foregroundMask, contours, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

3. 筛选有效人体轮廓

不是所有轮廓都是人体,咱们得设置规则过滤掉无效的:

  • 最小面积阈值:太小的轮廓肯定是噪点,直接跳过
  • 宽高比筛选:人体的宽高比一般不会太极端(比如不会特别宽或者特别瘦),可以设置一个合理的范围

代码示例:

// 最小轮廓面积,根据你的摄像头距离、画面大小调整,比如5000像素
int minContourArea = 5000;
// 遍历所有轮廓
foreach (var contour in contours)
{
    // 计算当前轮廓的面积
    double area = Cv2.ContourArea(contour);
    if (area < minContourArea)
        continue; // 跳过小轮廓

    // 计算轮廓的 bounding rectangle
    Rect boundingRect = Cv2.BoundingRect(contour);
    // 计算宽高比:宽度/高度
    double aspectRatio = (double)boundingRect.Width / boundingRect.Height;
    // 人体的宽高比大概在0.2-0.9之间,你可以根据实际场景调整
    if (aspectRatio < 0.2 || aspectRatio > 0.9)
        continue; // 跳过不符合人体比例的轮廓

    // 到这里,这个轮廓大概率是人体,开始绘制矩形框
    // originalFrame是你的原始彩色视频帧,用来画框的载体
    Cv2.Rectangle(originalFrame, boundingRect, new Scalar(0, 255, 0), 2);
}

完整整合代码

把上面的步骤整合起来,就是一个可以直接调用的方法:

public void DrawHumanBoundingBoxes(Mat originalFrame, Mat foregroundMask)
{
    // 1. 预处理去噪
    Mat kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(5, 5));
    Cv2.MorphologyEx(foregroundMask, foregroundMask, MorphTypes.Open, kernel);

    // 2. 检测轮廓
    List<Point[]> contours = new List<Point[]>();
    Mat hierarchy = new Mat();
    Cv2.FindContours(foregroundMask, contours, hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple);

    // 3. 筛选并绘制矩形
    int minArea = 5000;
    foreach (var contour in contours)
    {
        double area = Cv2.ContourArea(contour);
        if (area < minArea) continue;

        Rect rect = Cv2.BoundingRect(contour);
        double aspectRatio = (double)rect.Width / rect.Height;
        if (aspectRatio > 0.2 && aspectRatio < 0.9)
        {
            // 画绿色矩形框,线宽为2
            Cv2.Rectangle(originalFrame, rect, new Scalar(0, 255, 0), 2);
        }
    }
}

几个实用提示

  • 阈值调整:minArea和宽高比阈值一定要根据你的实际场景调!比如摄像头离人近,面积阈值就得设大一点;如果是远距离监控,阈值就得小一些。
  • 优化背景减除结果:如果背景减除的掩码有很多鬼影或者噪点,可以调整背景减除器的参数,比如BackgroundSubtractorMOG2的history(历史帧数量)、varThreshold(方差阈值),或者关掉阴影检测(detectShadows = false),减少阴影的干扰。
  • 进阶精准检测:如果单纯的轮廓筛选不够精准,你可以结合轻量的人体检测模型(比如YOLO的C#实现),但如果只是基于背景减除的场景,上面的方法足够应付大部分需求了。

内容的提问来源于stack exchange,提问作者Lễ Cống Anh Sơn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:22:09