2
votes

What I need to do is fairly simple:

1- load a 5 frames video file
2- detect background
3- On every frames, one by one :
-- 1- subtract background (create foreground mask)
-- 2- do some calculations on foreground mask
-- 3- save both original frame and foreground mask

Just to see the 5 frames and the 5 corresponding fgmasks :

import numpy as np
import cv2  
cap = cv2.VideoCapture('test.avi')
fgbg = cv2.BackgroundSubtractorMOG()

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()

    fgmask = fgbg.apply(frame)
    # Display the fgmask frame
    cv2.imshow('fgmask',fgmask)
    # Display original frame
    cv2.imshow('img', frame)

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

cap.release()
cv2.destroyAllWindows()

Every frame gets opened and displayed correctly but the showed fgmask do not correspond to the showed original frame. Somewhere in the process, the order of the fgmasks gets mixed up.

The background does get subtracted correctly but I don't get the 5 expected fgmasks.

What am I missing ? I feel like this should be straightforward : the while loop runs over the 5 frames of the video and fgbg.apply apply the background subtraction function to each frame.

opencv-2.4.9-3

1
5 frames only might not be enough to build a good background model for BackgroundSubtractorMOG, BackgroundSubtractorMOG2, etc.berak
Maybe... But since the subtraction "works" (I get the background subtracted and the moving object white), I would think that it's possible to use it on just 5 frames.Chargaff
Since you only have 5 frames, you can implement Background Subtraction by assuming the first frame as the background or running average method. Moreover, MOG usually takes a few frames to give the correct results, as mentioned by @berak.bikz05

1 Answers

2
votes

As bikz05 suggested, running average method worked pretty good on my 5 images sets. Thanks for the tip !

import cv2
import numpy as np

c = cv2.VideoCapture('test.avi')
_,f = c.read()

avg1 = np.float32(f)
avg2 = np.float32(f)

# loop over images and estimate background 
for x in range(0,4):
    _,f = c.read()

    cv2.accumulateWeighted(f,avg1,1)
    cv2.accumulateWeighted(f,avg2,0.01)

    res1 = cv2.convertScaleAbs(avg1)
    res2 = cv2.convertScaleAbs(avg2)

    cv2.imshow('img',f)
    cv2.imshow('avg1',res1)
    cv2.imshow('avg2',res2)
    k = cv2.waitKey(0) & 0xff
    if k == 5:
        break