People counter 6 – Find contours

Again, sorry for the delay between posts, I’ve been busy with other projects :S

So far, we have filtered the video stream so we only get movement:

peoplecount filter1

Now it’s time to detect contours on the frames. This is really simple with openCV’s findCountours function.

Here´s the code:

import numpy as np
import cv2

# http://docs.opencv.org/master/d3/dc0/group__imgproc__shape.html#ga17ed9f5d79ae97bd4c7cf18403e1689a&gsc.tab=0
##http://docs.opencv.org/master/d4/d73/tutorial_py_contours_begin.html#gsc.tab=0

cap = cv2.VideoCapture('peopleCounter.avi') #Open video file
fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows = True) #Create the background substractor
kernelOp = np.ones((3,3),np.uint8)
kernelCl = np.ones((11,11),np.uint8)

while(cap.isOpened()):
ret, frame = cap.read() #read a frame

fgmask = fgbg.apply(frame) #Use the substractor
try:
ret,imBin= cv2.threshold(fgmask,200,255,cv2.THRESH_BINARY)
#Opening (erode->dilate) para quitar ruido.
mask = cv2.morphologyEx(imBin, cv2.MORPH_OPEN, kernelOp)
#Closing (dilate -> erode) para juntar regiones blancas.
mask = cv2.morphologyEx(mask , cv2.MORPH_CLOSE, kernelCl)
except:
#if there are no more frames to show...
print('EOF')
break

_, contours0, hierarchy = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
for cnt in contours0:
cv2.drawContours(frame, cnt, -1, (0,255,0), 3, 8)

cv2.imshow('Frame',frame)

#Abort and exit with 'Q' or ESC
k = cv2.waitKey(30) & 0xff
if k == 27:
break

cap.release() #release video file
cv2.destroyAllWindows() #close all openCV windows

 

The important thing here are these lines:

    _, contours0, hierarchy = cv2.findContours(mask,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    for cnt in contours0:
        cv2.drawContours(frame, cnt, -1, (0,255,0), 3, 8)

 

We give the function our mask, cv2.RETR_EXTERNAL means we only care about external contours (contours within contours will not be detected), and cv2.CHAIN_APPROX_NONE is the algorithm used to “make” the contour (you can change it to another one as a test).

Draw contours is only used to visually appreciate the contours on the image we display.

All of the other lines of the code have been previously explained in the series.

contours

People Counter 2 – Opening a video stream

In the second part of the tutorial we’ll cover how to open a video stream in OpenCV.

A video stream may be a video recording in a file or video from a webcam. I’ll show you how to work with both.

First, let’s work with a video file. Download this sample video. We’ll be using it throughout the tutorials.

Create a new Python script in the same location as the video and add the following code:

import numpy as np
import cv2

cap = cv2.VideoCapture('peopleCounter.avi') #Open video file

while(cap.isOpened()):
    ret, frame = cap.read() #read a frame
    try:
        cv2.imshow('Frame',frame)
    except:
        #if there are no more frames to show...
        print('EOF')
        break

    #Abort and exit with 'Q' or ESC
    k = cv2.waitKey(30) & 0xff
    if k == 27:
        break

cap.release() #release video file
cv2.destroyAllWindows() #close all openCV windows

As you can see, we begin by importing numpy and openCV to our script.

Then we open the video file with the VideoCapture object, giving it the location of the video file as a parameter.

The we read frames from the video and show them, one by one, until we reach the end of it. At that point, we exit the while loop and close the video file and the video window.

Using a webcam is very similar:

import numpy as np
import cv2

cap = cv2.VideoCapture(0)
    
while(cap.isOpened()):
    ret, frame = cap.read()
    try:
        cv2.imshow('Frame',frame)
    except:
        print('EOF')
        break

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

cap.release()
cv2.destroyAllWindows()

The only difference is how we create the VideoCapture object. This time we pass it 0 as parameter. This indicates that we want to use the webcam with ID 0. Is you hav emultiple webcams on your computer, such as a USB webcam and another one embedded onyour screen, you’ll need to pass 0 or 1, depending on which one you want to use.

A VideoCapture object has several properties that you can access and sometimes change:

  • CAP_PROP_POS_MSEC Current position of the video file in milliseconds or video capture timestamp.
  • CAP_PROP_POS_FRAMES 0-based index of the frame to be decoded/captured next.
  • CAP_PROP_POS_AVI_RATIO Relative position of the video file: 0 – start of the film, 1 – end of the film.
  • CAP_PROP_FRAME_WIDTH Width of the frames in the video stream.
  • CAP_PROP_FRAME_HEIGHT Height of the frames in the video stream.
  • CAP_PROP_FPS Frame rate.
  • CAP_PROP_FOURCC 4-character code of codec.
  • CAP_PROP_FRAME_COUNT Number of frames in the video file.
  • CAP_PROP_FORMAT Format of the Mat objects returned by retrieve() .
  • CAP_PROP_MODE Backend-specific value indicating the current capture mode.
  • CAP_PROP_BRIGHTNESS Brightness of the image (only for cameras).
  • CAP_PROP_CONTRAST Contrast of the image (only for cameras).
  • CAP_PROP_SATURATION Saturation of the image (only for cameras).
  • CAP_PROP_HUE Hue of the image (only for cameras).
  • CAP_PROP_GAIN Gain of the image (only for cameras).
  • CAP_PROP_EXPOSURE Exposure (only for cameras).
  • CAP_PROP_CONVERT_RGB Boolean flags indicating whether images should be converted to RGB.
  • CAP_PROP_WHITE_BALANCE Currently not supported
  • CAP_PROP_RECTIFICATION Rectification flag for stereo cameras (note: only supported by DC1394 v 2.x backend currently)

You can use the get method to show them and set to give them a new value.

Here´s an example on showing all of the properties’ values and changing the width and height of the video stream from the webcam:

import numpy as np
import cv2

cap = cv2.VideoCapture(0)

#show all video properties
for i in range(19):
    print i, cap.get(i)

cap.set(3,160) #set width
cap.set(4,120) #set height
    
while(cap.isOpened()):
    ret, frame = cap.read()
    try:
        cv2.imshow('Frame',frame)
    except:
        print('EOF')
        break

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

cap.release()
cv2.destroyAllWindows()

 

This is all for this tutorial. Next time we’ll work on the video stream, drawing a GUI on it.

Please leave any comments or questions you have. 🙂

 

PS. If you have trouble opening the AVI file in openCV, try updating your video codecs. Downloading DIVX codec helped me when I had this issue.