People counter 8 – Following movement

Here starts the tricky part 🙂

You already know when there’s a person in the image now you want to know in what direction they’re moving (up/down).

In the first frame you detect someone you need to give that person an ID and store it’s initial position in the image.

Then, on the following frames, you want to keep track of that person, you need to match the person’s contour in the following frames to the ID you set when it first appeared, as well as keep storing that person’s coordinates.

Then, after the person crosses a limit (or a certain amount limits) in the image, you want evaluate, using all of the stored positions, if he/she is moving up or down.

To handle all of this IDing and storing of coordinates I created a class called Person. It might not be optimized, but you can take a look at it here.

Here´s a code you should try:

import numpy as np
import cv2
import Person
import time

# 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)

#Variables
font = cv2.FONT_HERSHEY_SIMPLEX
persons = []
max_p_age = 5
pid = 1
areaTH = 500

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)
        area = cv2.contourArea(cnt)
        if area > areaTH:
            #################
            #   TRACKING    #
            #################            
            M = cv2.moments(cnt)
            cx = int(M['m10']/M['m00'])
            cy = int(M['m01']/M['m00'])
            x,y,w,h = cv2.boundingRect(cnt)
            
            new = True
            for i in persons:
                if abs(x-i.getX()) <= w and abs(y-i.getY()) <= h:
                    # el objeto esta cerca de uno que ya se detecto antes
                    new = False
                    i.updateCoords(cx,cy)   #actualiza coordenadas en el objeto and resets age
                    break
            if new == True:
                p = Person.MyPerson(pid,cx,cy, max_p_age)
                persons.append(p)
                pid += 1     
            #################
            #   DIBUJOS     #
            #################
            cv2.circle(frame,(cx,cy), 5, (0,0,255), -1)
            img = cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)            
            cv2.drawContours(frame, cnt, -1, (0,255,0), 3)

    #########################
    # DIBUJAR TRAYECTORIAS  #
    #########################
    for i in persons:
        if len(i.getTracks()) >= 2:
            pts = np.array(i.getTracks(), np.int32)
            pts = pts.reshape((-1,1,2))
            frame = cv2.polylines(frame,[pts],False,i.getRGB())
        if i.getId() == 9:
            print str(i.getX()), ',', str(i.getY())
        cv2.putText(frame, str(i.getId()),(i.getX(),i.getY()),font,0.3,i.getRGB(),1,cv2.LINE_AA)
     
    
    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

 

Important part’s here:

for i in persons:
                if abs(x-i.getX()) <= w and abs(y-i.getY()) <= h:
                    # el objeto esta cerca de uno que ya se detecto antes
                    new = False
                    i.updateCoords(cx,cy)   #actualiza coordenadas en el objeto and resets age
                    break
            if new == True:
                p = Person.MyPerson(pid,cx,cy, max_p_age)
                persons.append(p)
                pid += 1

 

Here we look for a detected contour’s coordinates and try to match them to a previously detected person. If no person is matched then we create a new one.

trayectories

13 thoughts on “People counter 8 – Following movement”

  1. Great Post! I have a problem, what should I do, i am begginer. 🙁


    Traceback (most recent call last):
    File “C:\Users\MADU\Desktop\camera\12.py”, line 10, in
    fgbg = cv2.createBackgroundSubtractorMOG2(detectShadows = True) #Create the background substractor
    AttributeError: ‘module’ object has no attribute ‘createBackgroundSubtractorMOG2’
    >>>

  2. Un fabuloso trabajo, he ido siguiendo el post desde hace varios meses, y siempre lo reviso con la expectativa de seguir descubriendo más; en la espera del post 9 saludos un feliz año nuevo!!!!!!!

  3. I believe I have found a mistake in the fallowing line:
    if abs(x-i.getX()) <= w and abs(y-i.getY()) <= h:
    It should be :
    if abs(cx-i.getX()) <= w and abs(cy-i.getY()) <= h:

    bc later one each track saves it's central coordinates. x and y is just stating corner of rectangular.

  4. Saludos!, He seguido atentamente tu tutorial y te digo que muchas gracias, he aclarado varios conceptos, apenas estoy aprendiendo sobre opencv 🙂 . Estaré esperando la parte del conteo. Mientras tanto, he visto que en la clase Person que creaste tienes definidas unas funciones going_UP y going_DOWN , estas son las que utilizas para contar? cómo se emplean? podrías colaborarme con eso? Gracias.

  5. Pingback: Cialis 5mg prix
  6. Pingback: Cialis online
  7. Pingback: Cialis 20 mg
  8. Pingback: Cialis 20 mg
  9. Pingback: Viagra generika

Leave a Reply