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

SSIM检测建筑平面图差异的噪声成因及优化方案问询

建筑平面图差异检测:SSIM抗纹理噪声优化方案

噪声成因

SSIM对地板斑点这类纹理噪声敏感的核心原因是,它的计算基于局部区域的亮度、对比度、结构相似度三个维度。斑点纹理属于高频随机细节差异,即使两张图的宏观建筑结构完全一致,局部像素的微小波动也会拉低SSIM的局部相似度得分,触发阈值检测后被误判为差异区域。

可行优化方法

1. 预处理:针对性消除纹理噪声

对灰度图先进行滤波处理,优先选择中值滤波(能保留建筑边缘的同时消除斑点/椒盐噪声),也可根据噪声类型选择高斯模糊:

def find_diff(before, after):
    before_grey = cv2.cvtColor(before, cv2.COLOR_BGR2GRAY)
    after_grey = cv2.cvtColor(after, cv2.COLOR_BGR2GRAY)
    
    # 新增:中值滤波消除斑点噪声
    before_grey = cv2.medianBlur(before_grey, 5)  # 核大小选奇数,可根据斑点尺寸调整(3/5/7)
    after_grey = cv2.medianBlur(after_grey, 5)
    
    (score, diff) = compare_ssim(before_grey, after_grey, full=True)
    diff = (diff * 255).astype("uint8")
    print("SSIM: {}".format(score))
    
    thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
    contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = imutils.grab_contours(contours)
    
    for c in contours:
        (x, y, w, h) = cv2.boundingRect(c)
        cv2.rectangle(before, (x, y), (x + w, y + h), (0, 0, 255), 2)
        cv2.rectangle(after, (x, y), (x + w, y + h), (0, 0, 255), 2)
    
    return before, after, diff

2. 调整SSIM的计算窗口大小

SSIM默认用11x11的窗口计算局部相似度,放大窗口可以忽略局部小纹理的波动,聚焦宏观结构差异:

# 修改compare_ssim调用,指定更大的窗口(必须为奇数)
(score, diff) = compare_ssim(before_grey, after_grey, full=True, win_size=19)

窗口尺寸越大,对局部纹理的容忍度越高,可根据平面图的实际尺寸和纹理密度调整。

3. 后处理:过滤微小误检轮廓

斑点噪声对应的轮廓通常面积很小,在绘制差异框前加入面积阈值过滤:

for c in contours:
    # 新增:过滤面积小于阈值的小轮廓
    if cv2.contourArea(c) < 500:  # 阈值根据图像分辨率调整,比如1000对应更大的区域
        continue
    (x, y, w, h) = cv2.boundingRect(c)
    cv2.rectangle(before, (x, y), (x + w, y + h), (0, 0, 255), 2)
    cv2.rectangle(after, (x, y), (x + w, y + h), (0, 0, 255), 2)

4. 替换算法:聚焦结构边缘差异

建筑平面图的显著差异(墙体改动、房间布局变化)本质是边缘结构变化,可改用Canny边缘差异检测跳过纹理干扰:

def find_diff(before, after):
    before_grey = cv2.cvtColor(before, cv2.COLOR_BGR2GRAY)
    after_grey = cv2.cvtColor(after, cv2.COLOR_BGR2GRAY)
    
    # 提取边缘
    before_edge = cv2.Canny(before_grey, 50, 150)
    after_edge = cv2.Canny(after_grey, 50, 150)
    
    # 计算边缘差异
    diff = cv2.absdiff(before_edge, after_edge)
    diff = (diff * 255).astype("uint8")
    
    thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)[1]
    contours = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = imutils.grab_contours(contours)
    
    for c in contours:
        if cv2.contourArea(c) < 500:
            continue
        (x, y, w, h) = cv2.boundingRect(c)
        cv2.rectangle(before, (x, y), (x + w, y + h), (0, 0, 255), 2)
        cv2.rectangle(after, (x, y), (x + w, y + h), (0, 0, 255), 2)
    
    return before, after, diff

这种方法直接聚焦结构边缘的变化,完全避开地板斑点这类纹理噪声的干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 13:04:59