【问题标题】:How to remove shadows from a video that has static background?如何从具有静态背景的视频中去除阴影?
【发布时间】:2025-12-17 19:05:01
【问题描述】:

我正在尝试检测移动物体并从具有静态背景的视频中移除阴影。我正在使用混合高斯(MOG)方法来检测运动物体。我正在使用 opencv3 和 python 3.5。如何从视频和前景蒙版中删除阴影?我使用腐蚀和膨胀来减少噪音。但它不会消除阴影。

import cv2
import numpy as np

cap = cv2.VideoCapture('TownCentreXVID.avi')
fgbg = cv2.createBackgroundSubtractorMOG2()

while(1):

    _, frame = cap.read()
    mask = fgbg.apply(frame)



    kernel = np.ones((5,5),np.uint8)
    opening = cv2.morphologyEx(mask, cv2.MORPH_OPEN, kernel)
    closing = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

    window = cv2.namedWindow('Original', cv2.WINDOW_NORMAL| cv2.WINDOW_KEEPRATIO )
    window = cv2.namedWindow('Mask', cv2.WINDOW_NORMAL| cv2.WINDOW_KEEPRATIO)
    window = cv2.namedWindow('Opening', cv2.WINDOW_NORMAL| cv2.WINDOW_KEEPRATIO )
    #window = cv2.namedWindow('Closing', cv2.WINDOW_NORMAL| cv2.WINDOW_KEEPRATIO)

    cv2.imshow('Original',frame)
    cv2.imshow('Mask',thresh)
    cv2.imshow('Opening',opening)
    #cv2.imshow('Closing',closing)

    k = cv2.waitKey(5) & 0xFF
    if k == 27:
        break

cv2.destroyAllWindows()
cap.release()

【问题讨论】:

  • 你试过fgbg.setDetectShadows(0)吗?
  • 你能把整个代码贴出来吗?fgbg1 =cv2.BackgroundSubtractorMOG2(setShadowValue=0)我现在正在使用这一行。但是cv2.imshow 给出了错误,说 Mat 既不是 numpy 数组也不是标量
  • 就拿我写的那一行放在fgbg = cv2.createBackgroundSubtractorMOG2()之后
  • 这不会消除阴影。它不标记阴影。如果我使用setDetectshadows(1),它会将阴影标记为灰色。

标签: python-3.x opencv image-processing object-detection shadow-removal


【解决方案1】:

backgroundsubtractor 返回一个蒙版,其中前景对象为白色,阴影为灰色。
您可以使用thresholding 创建一个没有阴影或只有阴影的新蒙版。
使用没有阴影的蒙版仅获得前景。
使用只有阴影的蒙版来替换背景上的阴影(带有参考背景图像)。

结果:

代码:

import cv2
import numpy as np
# load image / mask
mask = cv2.imread("mask.png",0)
#threshold mask
ret, foreground = cv2.threshold(mask, 200, 255, cv2.THRESH_BINARY)
ret, shadow = cv2.threshold(mask, 200, 255, cv2.THRESH_TOZERO_INV)
# stack images vertically
res = np.concatenate((mask,foreground,shadow),axis=0)
#show image
cv2.imshow("Result",res)
cv2.waitKey(0)
cv2.destroyAllWindows()

【讨论】:

  • 谢谢。您的代码工作正常。有没有办法在视频中也可以去除阴影,而不仅仅是在蒙版中?
  • 当帧中没有检测到前景对象时,存储该帧的副本。您可以使用此图像替换阴影区域(example)。为此,使用分离阴影作为遮罩。注意:要使用阴影灰色作为蒙版,您需要做一个额外的阈值,以便将灰色转换为白色。
  • 谢谢。我会试试的。
  • 如何在这里创建投资回报率?因为阴影不会在不同帧的相同位置。
  • 取整帧。取只有阴影的蒙版(应该与框架的大小相同。使用shadow_mask_inverted = cv2.bitwise_not(shadow_mask) 创建负片做img1 = cv2.bitwise_and(frame,frame,shadow_mask_inverted)img2 = cv2.bitwise_and(frame_without_object,frame_without_object,shadow_mask)result = cv2.add(img1,img2)