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

如何用C#的Emgu.CV在平面图中检测房间门并修改颜色?

问题:平面图门检测误判的解决思路

我有平面图图片和GeoJSON文件,需要把GeoJSON叠加到图片上,修改房间和门的颜色。已经用Emgu.CV实现了房间检测和颜色修改,但卡在门的检测与颜色修改环节:只有房间坐标,尝试通过房间的黄色检测门,会误检房间内其他区域,不确定是否需要门的坐标,求解决思路。


现有C#代码

static void DetectAndDrawDoors(Image<Bgr, byte> image, List<PolygonData> polygonDataList)
{
    Mat hsvImage = new Mat();
    CvInvoke.CvtColor(image, hsvImage, ColorConversion.Bgr2Hsv);

    ScalarArray lowerBound = new ScalarArray(new MCvScalar(20, 50, 0));
    ScalarArray upperBound = new ScalarArray(new MCvScalar(29, 255, 100));

    Mat yellowMask = new Mat();
    CvInvoke.InRange(hsvImage, lowerBound, upperBound, yellowMask);

    CvInvoke.GaussianBlur(yellowMask, yellowMask, new Size(5, 5), 0);

    CvInvoke.MorphologyEx(yellowMask, yellowMask, MorphOp.Open, CvInvoke.GetStructuringElement(ElementShape.Rectangle, new Size(5, 5), new Point(-1, -1)), new Point(-1, -1), 1, BorderType.Default, new MCvScalar());

    VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
    CvInvoke.FindContours(yellowMask, contours, null, RetrType.List, ChainApproxMethod.ChainApproxSimple);

    // Iterate over contours using a for loop
    for (int i = 0; i < contours.Size; i++)
    {
        VectorOfPoint approxContour = new VectorOfPoint();
        CvInvoke.ApproxPolyDP(contours[i], approxContour, 10, false);

        if (CvInvoke.ContourArea(approxContour) > 20)
        {
            Rectangle boundingBox = CvInvoke.BoundingRectangle(approxContour);

            // Check if the current contour is part of any active polygon
            foreach (var polygonData in polygonDataList.Where(pd => pd.Active == "True"))
            {
                if (IsContourInActivePolygon(approxContour, polygonData.Coordinates))
                {
                    CvInvoke.Rectangle(image, boundingBox, new MCvScalar(0, 255, 0), 20);
                }
            }
        }
    }
}

static bool IsContourInActivePolygon(VectorOfPoint contour, List<Coordinate> polygonCoordinates)
{
    // Convert contour points to coordinates
    List<Coordinate> contourCoordinates = contour.ToArray().Select(point => new Coordinate { Latitude = point.Y, Longitude = point.X }).ToList();

    // Check if any point of the contour is inside the polygon
    return contourCoordinates.Any(point => IsPointInPolygon(point, polygonCoordinates));
}

static bool IsPointInPolygon(Coordinate point, List<Coordinate> polygonCoordinates)
{
    // Implementation of point in polygon algorithm
    int count = polygonCoordinates.Count;
    bool inside = false;

    for (int i = 0, j = count - 1; i < count; j = i++)
    {
        if (((polygonCoordinates[i].Latitude > point.Latitude) != (polygonCoordinates[j].Latitude > point.Latitude)) &&
            (point.Longitude < (polygonCoordinates[j].Longitude - polygonCoordinates[i].Longitude) * (point.Latitude - polygonCoordinates[i].Latitude) / (polygonCoordinates[j].Latitude - polygonCoordinates[i].Latitude) + polygonCoordinates[i].Longitude))
        {
            inside = !inside;
        }
    }

    return inside;
}

34号房间GeoJSON示例

{
    "type": "Feature",
    "geometry": {
        "type": "Polygon",
        "coordinates": [
            [768,74],
            [768,322],
            [851,322],
            [875,346],
            [872,349],
            [872,350],
            [931,409],
            [934,406],
            [935,406],
            [959,430],
            [959,522],
            [1102,522],
            [1102,74]
        ]
    },
    "properties": {
        "active": true,
        "roomname": "34",
        "disp_label": "",
        "arch_ref": ""
    }
}

解决思路

1. 优化颜色检测与轮廓筛选

仅靠黄色范围过滤容易误检,可增加多重约束:

  • 缩小HSV参数范围:比如把明度上限从100调低,过滤房间内偏亮的黄色干扰区域;
  • 增加形状判断:门通常是细长矩形,计算轮廓的宽高比,只保留宽高比大于3(根据实际门的比例调整)的轮廓,排除方形/圆形的误检区域;
  • 限制面积范围:添加面积上限(比如200像素),过滤房间内大面积黄色区域。

2. 结合房间边界的位置校验

门必然位于房间多边形的边界上,而非内部,可修改判断逻辑:

  • 计算黄色轮廓的重心点,判断其是否在房间内;
  • 检查轮廓的顶点是否靠近房间多边形的边缘(比如距离≤5像素),只有同时满足这两个条件的轮廓才判定为门。

3. 补充门的GeoJSON数据(最优方案)

直接在GeoJSON中添加门的Feature(类型为Polygon或LineString),完全避免颜色检测的误判。示例格式:

{
    "type": "Feature",
    "geometry": {
        "type": "Polygon",
        "coordinates": [[x1,y1],[x2,y2],[x3,y3],[x4,y4]]
    },
    "properties": {
        "roomname": "34",
        "type": "door"
    }
}

之后直接遍历门的Feature,在图片上绘制颜色即可。

4. 调整形态学操作参数

当前的开运算可能过度处理或不足,可:

  • 改用更小的结构元素(比如Size(3,3)矩形),避免侵蚀门的轮廓;
  • 添加闭运算,填补门轮廓的微小缺口,提升检测稳定性。

内容的提问来源于stack exchange,提问作者Monisha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:17:02