OpenCV BackgroundSubtractor yields poor results on objects with similar color as background color

1.4k views Asked by At

I have kind of challenging task and spent a lot of time on it but without satisfactory results.

The sense is to perform a background subtraction for future people counting. I am doing this with Python 3 and OpenCV 3.3. I have applied cv2.createBackgroundSubtractorMOG2 but faced two main difficulties:

  1. As background is almost dark, and some people that walk on video are wearing dark staff, subtractor sometimes is unable to detect them properly, it simply skips them (take a look at the image below). Converting image from BGR to HSV made little changes but i expect even better result. enter image description here As you can see, a man in grey clothes is not detected well. How is it possible to improve this? If there is more efficient methods, please provide this information, I appreciate and welcome any help! Maybe there is sense to use stereo camera and try to process objects using images depth?

  2. Another question that worries me, is what if a couple of people will be close to each other in case of hard traffic? The region will be simply merged and counted as simple. What can be done in such case?

Thanks in advance for any information!

UPD:

I performed histogram equalization on every channel of the image with HSV colorspace, but even now I am not able to absorb some people with color close to background color.

Here is code updated:

import cv2
import numpy as np
import imutils


cap = cv2.VideoCapture('test4.mp4')
clahe = cv2.createCLAHE(2.0, (8,8))

history = 50
fgbg = cv2.createBackgroundSubtractorMOG2(history=history, detectShadows=True)

while cap.isOpened():
    frame = cap.read()[1]
    width, height = frame.shape[:2]
    frame = imutils.resize(frame, width=min(500, width))
    origin = frame.copy()
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    for channel in range(3):
         hsv[:,:,channel] = clahe.apply(hsv[:,:,channel])

    fgmask = fgbg.apply(hsv, learningRate=1 / history)
    blur = cv2.medianBlur(fgmask, 5)

    cv2.imshow('mask', fgmask)
    cv2.imshow('hcv', hsv)
    cv2.imshow('origin', origin)
    k = cv2.waitKey(30) & 0xff
    if k == 27 or k == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

enter image description here

1

There are 1 answers

5
Jeru Luke On

I believe following the steps below will solve your first problem to a large extent:

1.Preprocessing:

Image preprocessing is very crucial because a computer does not see an image as we humans perceive. Hence, it is always advised to look for ways to enhance the image rather than working on it directly.

For the given image, the man in a jacket appears to be having the same color as the background. I applied histogram equalization to all the three channels of the image and merged them to get the following:

enter image description here

The man is visible slightly better than before.

2. Color Space:

Your choice of going with HSV color space was right. But why restrict to the three channels together? I obtained the hue channel and got the following:

enter image description here

3. Fine Tuning

Now to the image above, you will have to apply some optimal threshold and then follow it up with a morphological erosion operation to get a better silhouette of the man in the frame.

Note: In order to solve your second problem you can also go with some morphological operations after applying a threshold.