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
相关产品推荐
相关产品推荐

