Opencv运动检测,不受随机噪声触发

问题描述 投票:0回答:1

我是图像处理新手,我有点挣扎,我正在制作自己的 DIY 安全软件,并且我做了一个功能来检测某些运动,以便开始录制并通知我。

这个函数的想法是拍摄两个图像并比较它们以找到一些运动,我遇到的问题是:

  1. 检测效果非常好,但在夜间,图像上甚至每天在阴影中都会出现一些噪点,从而错误地触发阳性检测
  2. 该功能没有错误触发,但错过了一些检测

我尝试选项2的方式是通过注释代码,主要思想是

  • 分割灰度图像并模糊
  • 用自适应阈值(高斯和均值)替换基本阈值

这是我的代码:

import cv2
import numpy as np
from skimage.metrics import structural_similarity as ssim

def count_diff_nb(img_1, img_2):

    # resize images
    img_1_height, img_1_width = img_1.shape[:2]
    new_height = int((600 / img_1_width) * img_1_height)

    img_1 = cv2.resize(img_1, (600,new_height))
    img_2 = cv2.resize(img_2, (600,new_height))

    # convert to gray scale
    gray_image1 = cv2.cvtColor(img_1, cv2.COLOR_BGR2GRAY)
    gray_image2 = cv2.cvtColor(img_2, cv2.COLOR_BGR2GRAY)

    # Gaussian blur in order to remove some noise
    blur1 = cv2.GaussianBlur(gray_image1, (5,5), 0)
    blur2 = cv2.GaussianBlur(gray_image2, (5,5), 0)

    # divide (bad idea)
    #divide1 = cv2.divide(gray_image1, blur1, scale=255)
    #divide2 = cv2.divide(gray_image2, blur2, scale=255)

    # Compute SSIM between two images
    #ssim_value, diff = ssim(gray_image1, gray_image2, full=True)
    ssim_value, diff = ssim(blur1, blur2, full=True)
    #ssim_value, diff = ssim(divide1, divide2, full=True)
    diff_percent = (1 - ssim_value) * 100

    # The diff image contains the actual image differences between the two images
    # and is represented as a floating point data type so we must convert the array 
    # to 8-bit unsigned integers in the range [0,255] before we can use it with OpenCV
    diff = (diff * 255).astype("uint8")

    # Adaptative threshold (bad idea too)
    #thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
    #thresh = cv2.adaptiveThreshold(diff, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 3, 10)

    # Threshold the difference image
    thresh = cv2.threshold(diff, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]

    # followed by finding contours to
    # obtain the regions that differ between the two images
    contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    
    # Highlight differences
    mask = np.zeros(img_1.shape, dtype='uint8')
    filled = img_2.copy()


    contours_nb = 0
    for c in contours:
        # limit is an area so sqrt of size
        area = cv2.contourArea(c)
        # 72000 is 1/3 of global img area
        if area > 2000 and area < 72000:
            contours_nb = contours_nb + 1
            x,y,w,h = cv2.boundingRect(c)
            cv2.rectangle(img_1, (x, y), (x + w, y + h), (36,255,12), 2)
            cv2.rectangle(img_2, (x, y), (x + w, y + h), (36,255,12), 2)
            cv2.drawContours(mask, [c], 0, (0,255,0), -1)
            cv2.drawContours(filled, [c], 0, (0,255,0), -1)

    return contours_nb, diff_percent, img_2, filled

为了能够找到灵敏度(不是错过检测)和忽略由于黑暗而产生的随机噪声之间的最佳点,你有什么想法或我缺少的东西吗?

我想在转换为灰度之前忽略深色,但如果移动的东西是黑色的……我认为这是一个坏主意。

非常感谢!

python opencv image-processing computer-vision detection
1个回答
0
投票

我不知道你做错了什么,但谷歌搜索一下你可以找到很多方法,例如从使用轮廓检测和背景减法使用OpenCV进行移动物体检测,你可以找到一个很好的流程图使用 OpenCV 的对象检测管道 :

提到了背景减法,在你的算法中没有描述,但我可能是错的,我无法通过地球读取opencv。在文档中,他们将其中一种方法描述为:

它使用前几帧(默认为 120)进行背景建模。 它采用概率前景分割算法,使用贝叶斯推理来识别可能的前景对象。估计是自适应的;新的观测值比旧的观测值具有更大的权重,以适应可变的照明。进行一些形态过滤操作(例如关闭和打开)以消除不需要的噪声。在前几帧中您将看到一个黑色窗口......

你实际上可以在 OpenCV 文档上找到它 :

显然有两个BackgroundSubtractorMOG和BackgroundSubtractorGMG。

这意味着流的第一帧应该作为运动检测的基线。我不知道您是否需要重新校准您的设置,以防您正在对 24 小时运行的安全摄像头进行编程,并遇到大量环境光线变化

© www.soinside.com 2019 - 2024. All rights reserved.