Skip to content Skip to sidebar Skip to footer

Counting The Point Which Intercept In A Line With Opencv Python

I am working in vehicle counting with opencv and python programming, I already complete step: 1. Detect moving vehicle with BackgroundSubtractorMOG2 2. Draw rectangle on it, then p

Solution 1:

Here is my approach that would work independently of the video frame rate. Assuming that you are able to track a car's centroid at each frame, I would save the last two centroids' position (last_centroid and centroid in my code) and process as follows:

  1. compute the intercepting line equation's parameters ( (a,b,c) from aX + bY + c = 0)
  2. compute the equation's parameters of the segment line between last_centroid and centroid
  3. find if the two lines are intersecting
  4. if so, increment your counter

Here is how I implemented it in OpenCV (Python):

import cv2
import numpy as np
import collections

Params = collections.namedtuple('Params', ['a','b','c']) #to store equation of a linedefcalcParams(point1, point2): #line's equation Params computationif point2[1] - point1[1] == 0:
         a = 0
         b = -1.0elif point2[0] - point1[0] == 0:
        a = -1.0
        b = 0else:
        a = (point2[1] - point1[1]) / (point2[0] - point1[0])
        b = -1.0

    c = (-a * point1[0]) - b * point1[1]
    return Params(a,b,c)

defareLinesIntersecting(params1, params2, point1, point2):
    det = params1.a * params2.b - params2.a * params1.b
    if det == 0:
        returnFalse#lines are parallelelse:
        x = (params2.b * -params1.c - params1.b * -params2.c)/det
        y = (params1.a * -params2.c - params2.a * -params1.c)/det
        if x <= max(point1[0],point2[0]) and x >= min(point1[0],point2[0]) and y <= max(point1[1],point2[1]) and y >= min(point1[1],point2[1]):
            print("intersecting in:", x,y)
            cv2.circle(frame,(int(x),int(y)),4,(0,0,255), -1) #intersecting pointreturnTrue#lines are intersecting inside the line segmentelse:
            returnFalse#lines are intersecting but outside of the line segment

cv2.namedWindow('frame')
frame = np.zeros((240,320,3), np.uint8)

last_centroid = (200,200) #centroid of a car at t-1
centroid = (210,180) #centroid of a car at t

line_params = calcParams(last_centroid, centroid)
intercept_line_params = calcParams((0,170), (300,170))
print("Params:", line_params.a,line_params.b,line_params.c) 

while(1):
    cv2.circle(frame,last_centroid,4,(0,255,0), -1) #last_centroid
    cv2.circle(frame,centroid,4,(0,255,0), -1) #current centroid
    cv2.line(frame,last_centroid,centroid,(0,0,255),1) #segment line between car centroid at t-1 and t
    cv2.line(frame,(0,170),(300,170),(200,200,0),2) #intercepting lineprint("AreLinesIntersecting: ",areLinesIntersecting(intercept_line_params,line_params,last_centroid,centroid)) 
    cv2.imshow('frame',frame)
    if cv2.waitKey(15) & 0xFF == ord('q'):
        break

cv2.destroyAllWindows()

And here are some results:

Fig1. Segment is intersecting the lineFig1. Segment is intersecting the line (intercepting line in blue - segment line between last_centroid and centroid in red) Fig2. Segment is NOT intersecting the lineFig2. Segment is NOT intersecting the line

N.B. I found the formulas to calculate the intersection point here.

I hope my approach will help to address your problem.

Solution 2:

To assume that the centroid will assume a position 170 (in x or y) is wrong, because videos generally works at 30 fps, that mean you will get 30 centroid locations per second which means even if there the object crosses the line, it may never be 170!

To counter this, one method that can be used is defining a line margin. This means now you have a line margin x before actual line (y = 170) and x after the line margin.

So if your object falls anywhere in the margin, you can increment the counter. Now the next big part would be to make a tracking mechanism wherein you collect the list of point for each object and check if it fell in the margin.

Post a Comment for "Counting The Point Which Intercept In A Line With Opencv Python"