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

OpenCV房屋屋顶边缘与轮廓检测一致性问题求助

屋顶轮廓检测一致性优化方案

1. 颜色空间掩码预处理,先过滤无关区域

屋顶通常有相对固定的颜色特征(比如红瓦、灰瓦、深色沥青),通过转换到HSV/Lab颜色空间,针对屋顶颜色范围生成掩码,直接排除树木、电线这类颜色差异大的干扰项,减少后续边缘检测的无效计算。

示例代码:

import cv2
import numpy as np

img = cv2.imread("house.jpg")
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# 针对红瓦屋顶的HSV范围(需根据你的数据集手动调整区间)
lower_red1 = np.array([0, 120, 70])
upper_red1 = np.array([10, 255, 255])
mask1 = cv2.inRange(hsv, lower_red1, upper_red1)

lower_red2 = np.array([170, 120, 70])
upper_red2 = np.array([180, 255, 255])
mask2 = cv2.inRange(hsv, lower_red2, upper_red2)

# 合并掩码,保留屋顶候选区域
roof_mask = mask1 | mask2
filtered_img = cv2.bitwise_and(img, img, mask=roof_mask)

注:如果是灰瓦/沥青屋顶,需要重新调整HSV的上下限,可通过取几张样本图的屋顶像素值统计范围。

2. 基于形状特征的轮廓硬过滤

屋顶基本是多边形结构(三角形、矩形、梯形为主),通过轮廓的面积、近似多边形边数、长宽比等特征,过滤掉树叶、阴影、电线这类不符合屋顶形状的轮廓。

示例代码:

# 从过滤后的图像提取边缘
gray = cv2.cvtColor(filtered_img, cv2.COLOR_BGR2GRAY)
edges = cv2.Canny(gray, 50, 150)
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

valid_roof_contours = []
for cnt in contours:
    # 过滤过小的轮廓(比如树叶、细电线)
    area = cv2.contourArea(cnt)
    if area < 500:
        continue
    # 多边形近似,获取轮廓边数
    peri = cv2.arcLength(cnt, True)
    approx = cv2.approxPolyDP(cnt, 0.02 * peri, True)
    # 屋顶通常为3-5边多边形,可根据样本调整
    if 3 <= len(approx) <= 5:
        # 过滤细长型轮廓(比如电线)
        x, y, w, h = cv2.boundingRect(cnt)
        aspect_ratio = float(w) / h
        if 0.3 <= aspect_ratio <= 3:
            valid_roof_contours.append(cnt)

注:面积、边数、长宽比的阈值,建议手动统计10-15张样本图的屋顶参数后设定,匹配度会更高。

3. 自适应阈值+多尺度边缘检测,解决光照不均问题

针对背景与屋顶像素强度相近的情况,用自适应阈值代替全局阈值,结合多尺度Canny边缘检测,覆盖不同光照条件下的边缘特征,减少漏检和误检。

示例代码:

# 自适应阈值处理,应对局部光照不均
adaptive_thresh = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, 
                                       cv2.THRESH_BINARY_INV, 11, 2)

# 多尺度Canny合并结果,覆盖不同对比度的边缘
edges1 = cv2.Canny(gray, 30, 100)
edges2 = cv2.Canny(gray, 60, 150)
edges3 = cv2.Canny(gray, 90, 200)
combined_edges = cv2.bitwise_or(edges1, cv2.bitwise_or(edges2, edges3))

4. 针对性形态学变换,修复边缘缺口

不要用固定的膨胀/腐蚀,先通过开运算去除小噪点,再用闭运算填补屋顶边缘的缺口,强化完整轮廓。

示例代码:

# 开运算:先腐蚀再膨胀,清除小的亮噪点
kernel_open = np.ones((3, 3), np.uint8)
opening = cv2.morphologyEx(combined_edges, cv2.MORPH_OPEN, kernel_open, iterations=1)

# 闭运算:先膨胀再腐蚀,填补边缘的微小缺口
kernel_close = np.ones((5, 5), np.uint8)
closing = cv2.morphologyEx(opening, cv2.MORPH_CLOSE, kernel_close, iterations=1)

5. 区域生长辅助分割,应对复杂背景

如果上述方法仍有干扰,可尝试区域生长:从屋顶大概率存在的区域(比如图像中上部)选取种子点,分割出连续的屋顶区域后再提取轮廓。

示例代码:

h, w = gray.shape
# 选取图像上部1/3区域作为种子候选区
seed_point = (w // 2, h // 6)
mask = np.zeros_like(gray)
# 区域生长,loDiff/upDiff控制生长的像素差异范围
cv2.floodFill(gray, mask, seed_point, 255, loDiff=10, upDiff=10)
# 从生长后的掩码提取轮廓
contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

额外建议

因为你的数据集只有50张,建议先手动标注10-15张样本的屋顶特征(颜色范围、面积区间、形状参数),把这些统计值作为过滤规则的核心依据;同时可以将多种方法串联使用(颜色掩码→自适应阈值→形状过滤),逐步缩小候选区域,提升检测一致性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 18:53:20