0

I have been reading a tutorial on creating a Rpi colour based object tracking system but have been unable to test it due to me being a away from my Rpi. However I have read through the code and it seems to me that only one object of x colour will be tracked at a time. This is a problem as I want to track up to 4 at a time. Can anyone tell me how I can go about doing this?

The code:

# import the necessary packages
from collections import deque
import numpy as np
import argparse
import imutils
import cv2

# construct the argument parse and. parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video",help="path to the (optional) video  file")
ap.add_argument("-b", "--buffer", type=int, default=64, help="max buffer size")
args = vars(ap.parse_args())

# define the lower and upper. boundaries of the "yellow object"
# (or "ball") in the HSV color space, then initialize the
# list of tracked points
colorLower = (24, 100, 100)
colorUpper = (44, 255, 255)
pts = deque(maxlen=args["buffer"])

# if a video path was not supplied, grab the reference
# to the webcam
if not args.get("video", False):
    camera = cv2.VideoCapture(0)

# otherwise, grab a reference to the video file
else:
    camera = cv2.VideoCapture(args["video"])

# keep looping
while True:
    # grab the current frame
    (grabbed, frame) = camera.read()

    # if we are viewing a video and we did not grab a frame,
    # then we have reached the end of the video
    if args.get("video") and not grabbed:
    break

    # resize the frame, inverted ("vertical flip" w/ 180degrees),
    # blur it, and convert it to the HSV color space
    frame = imutils.resize(frame, width=600)
    frame = imutils.rotate(frame, angle=180)
    # blurred =
    cv2.GaussianBlur(frame, (11, 11), 0)
       hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # construct a mask for the color "green", then perform
    # a series of dilations and erosions to remove any small
    # blobs left in the mask
    mask = cv2.inRange(hsv, colorLower, colorUpper)
    mask = cv2.erode(mask, None, iterations=2)
    mask = cv2.dilate(mask, None, iterations=2)

    # find contours in the mask and initialize the current
    # (x, y) center of the ball
    cnts =cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]
    center = None

    # only proceed if at least one contour was found
    if len(cnts) > 0:
        # find the largest contour in the mask, then use
        # it to compute the minimum enclosing circle and
        # centroid
        c = max(cnts, key=cv2.contourArea)
        ((x, y), radius) = cv2.minEnclosingCircle(c)
        M = cv2.moments(c)
        center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))

        # only proceed if the radius meets a minimum size
        if radius > 10:
            # draw the circle and centroid on the frame,
            # then update the list of tracked points
            cv2.circle(frame, (int(x), int(y)), int(radius),
            (0, 255, 255), 2)
            cv2.circle(frame, center, 5, (0, 0, 255), -1)
     # update the points queue
    pts.appendleft(center)

        # loop over the set of tracked points
    for i in range(1, len(pts)):
        # if either of the tracked points are None, ignore
        # them
        if pts[i - 1] is None or pts[i] is None:
            continue

        # otherwise, compute the thickness of the line and
        # draw the connecting lines
        thickness = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5)
        cv2.line(frame, pts[i - 1], pts[i], (0, 0, 255), thickness)

    # show the frame to our screen.
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF

    # if the 'q' key is pressed, stop the loop
    if key == ord("q"):
        break

# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()

The tutorial: here Up to (and including) Step 5

Note: This is NOT my code!!

Also, is it possible to remove the fade on the red line drawn?

  • Tracking 4 objects will increase the complexity significantly. There are several important decisions to be made. Are all the objects being tracked has the same color? What if the first object crossed path with second object? – yapws87 Nov 21 '18 at 14:19
  • Each of the objects will be a different colour. The intended use of this guarantees that there will be no path crossing. – user10208400 Nov 22 '18 at 14:10
0

I have modified the code to enable 4 object tracking and removed the red lines that follows the object.

You will need to modify the colorLower and colorUpper array to determine the color you would like to track.

Modifying object_color will change the detected object color for display.

# import the necessary packages
from collections import deque
import numpy as np
import argparse
import imutils
import cv2

# construct the argument parse and. parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video",help="path to the (optional) video  file")
ap.add_argument("-b", "--buffer", type=int, default=64, help="max buffer size")
args = vars(ap.parse_args())

# define the lower and upper. boundaries of the "yellow object"
# (or "ball") in the HSV color space, then initialize the
# list of tracked points
# Set YOur choice of colors to track here
colorLower = ((24, 24, 24),(24, 24, 100),(24, 100, 24),(24, 100, 100))
colorUpper = ((44, 44, 44),(44, 44, 255),(44, 255, 44),(44, 255, 255))

object_color = ((255,0,0),(0,255,0),(0,0,255),(255,255,0))

pts = (deque(maxlen=args["buffer"]),deque(maxlen=args["buffer"]),deque(maxlen=args["buffer"]),deque(maxlen=args["buffer"]))

# if a video path was not supplied, grab the reference
# to the webcam
if not args.get("video", False):
    camera = cv2.VideoCapture(0)

# otherwise, grab a reference to the video file
else:
    camera = cv2.VideoCapture(args["video"])

# keep looping
while True:
    # grab the current frame
    (grabbed, frame) = camera.read()

    # if we are viewing a video and we did not grab a frame,
    # then we have reached the end of the video
    if args.get("video") and not grabbed:
    break

    # resize the frame, inverted ("vertical flip" w/ 180degrees),
    # blur it, and convert it to the HSV color space
    frame = imutils.resize(frame, width=600)
    frame = imutils.rotate(frame, angle=180)
    # blurred =
    cv2.GaussianBlur(frame, (11, 11), 0)
       hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    for object in range(4):
        # construct a mask for the color "green", then perform
        # a series of dilations and erosions to remove any small
        # blobs left in the mask
        mask = cv2.inRange(hsv, colorLower[object], colorUpper[object])
        mask = cv2.erode(mask, None, iterations=2)
        mask = cv2.dilate(mask, None, iterations=2)

        # find contours in the mask and initialize the current
        # (x, y) center of the ball
        cnts =cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2]
        center = None

        # only proceed if at least one contour was found
        if len(cnts) > 0:
            # find the largest contour in the mask, then use
            # it to compute the minimum enclosing circle and
            # centroid
            c = max(cnts, key=cv2.contourArea)
            ((x, y), radius) = cv2.minEnclosingCircle(c)
            M = cv2.moments(c)
            center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))

            # only proceed if the radius meets a minimum size
            if radius > 10:
                # draw the circle and centroid on the frame,
                # then update the list of tracked points
                cv2.circle(frame, (int(x), int(y)), int(radius),
                (0, 255, 255), 2)
                cv2.circle(frame, center, 5, object_color[object], -1)
     # update the points queue
    pts[object].appendleft(center)

        # loop over the set of tracked points
    for j in range(1, len(pts[object])):
        # if either of the tracked points are None, ignore
        # them
        if pts[object][j - 1] is None or pts[object][j] is None:
             continue

        # otherwise, compute the thickness of the line and
        # draw the connecting lines
        #thickness = int(np.sqrt(args["buffer"] / float(i + 1)) * 2.5)
        thickness = 2
        cv2.line(frame, pts[object][j - 1], pts[object][j], (0, 0, 255), thickness)


    # show the frame to our screen.
    cv2.imshow("Frame", frame)
    key = cv2.waitKey(1) & 0xFF

    # if the 'q' key is pressed, stop the loop
    if key == ord("q"):
        break

# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()
  • Thank you so much! Maybe my question wasn't clear enough but I wanted to keep the red line and remove the fade on it so it draws a kind of graph over the video. – user10208400 Nov 23 '18 at 9:28
  • OK i modified the code to include the line as well. You can adjust the line width by adjusting the thickness variable. – yapws87 Nov 23 '18 at 14:09
  • Thank you very much! You have been a great help! – user10208400 Nov 23 '18 at 16:20

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.