2017-04-10 1 views
3

Also habe ich Objekterkennung basierend auf Farbe mit OpenCV und ich es auf Raspberry Pi 3 laufen. Es funktioniert, wie es Tennisball in Echtzeit verfolgt (obwohl es einige Verzögerung hat, wie ich verwende kinect v1 (freenect-Bibliothek)). Jetzt möchte ich die Position ermitteln, wo das gefundene Objekt ist. Ich möchte wissen, ob es in der Mitte oder mehr auf der linken oder mehr auf der rechten Seite ist. Ich dachte daran, den Kamerarahmen auf 3 Teile zu teilen. Ich würde 3 booleans haben, eins für Mitte, eins für links und eins für Recht, und dann würden alle 3 Variablen über usb-Kommunikation gesendet. Wie auch immer, ich habe schon seit einer Woche versucht herauszufinden, wo das Objekt ist, aber ich bin dazu nicht in der Lage. Ich bitte hier um Hilfe.Erkennung von Objekten Position über Video

Aktuelle Arbeits Code für Objekterkennung mit OpenCV (I erkennen Objekt nach Farbe)

# USAGE 
# python ball_tracking.py --video ball_tracking_example.mp4 
# python ball_tracking.py 

# 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 "green" 
# ball in the HSV color space, then initialize the 
# list of tracked points 
greenLower = (29, 86, 6) 
greenUpper = (64, 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, blur it, and convert it to the HSV 
    # color space 
    frame = imutils.resize(frame, width=600) 
    # 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, greenLower, greenUpper) 
    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) 
     #EDIT: 
     if int(x) > int(200) & int(x) < int(400): 
      middle = True 
      left = False 
      notleft = False 

     if int(x) > int(1) & int(x) < int(200): 
      left = True 
      middle = False 
      notleft = False 

     if int(x) > int(400) & int(x) < int(600): 
      notleft = True 
      left = False 
      middle = False 

     print ("middle: ", middle, " left: ", left, " right: ", notleft) 

    # update the points queue 
    pts.appendleft(center) 

    # loop over the set of tracked points 
    for i in xrange(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() 

Der Code richtig kommentiert wird. Senden von Informationen mit USB-Port ist kein Problem, ich kann einfach nicht herausfinden, wie man erkennt, wo der Ball ist.

Ich laufe Raspbian auf meinem Raspberry Pi.

EDIT: Ich vergaß zu erwähnen, ich bin nur in Objekte Position nach X-Achse interessiert. Ich dachte, dass ich, wenn ich den aktuellen Frame auf 600 gesetzt habe, 3 schreiben würde, wenn es wie if x > 200 && x < 400: bool middle = true ist. Es funktioniert nicht du.

EDIT2: Ich denke, ich habe es irgendwie funktioniert, aber die "Mitte" wird nie wahr sein. Ich werde für links und rechts wahr, aber nicht für Mitte.

+0

Ist das nicht 'center' die eigentliche Mitte der Kugel? Bist du damit zufrieden? Ich würde es so machen, aber anstelle von "int" verwende ein "double". Das sollte das sein, wonach du suchst. –

Antwort

2
 if int(x) > int(200) AND int(x) < int(400): 
      middle = True 
      left = False 
      notleft = False 

     if int(x) > int(1) AND int(x) < int(200): 
      left = True 
      middle = False 
      notleft = False 

     if int(x) > int(400) AND int(x) < int(600): 
      notleft = True 
      left = False 
      middle = False 

alles, was ich war schreiben musste "AND" insted "&" ... So viel Mühe, so ein kleines Update. Hier

0

Wenn das Objekt, von dem Sie die Position erkennen, dann ist es besser als cv2.findContours(), cv2.HoughCircles() zu verwenden. Da cv2.HoughCircles() die Mittelpunktsposition (x, y) der Kreise direkt zurückgibt.

können Sie die Probe mit den HoughCircles finden() here

Wenn Sie das Zentrum dieses Kreises erhalten dann seine Position zu bestimmen, wird leicht sein.

Viel Glück.

+0

Ich werde bearbeiten, wie ich es jetzt gemacht habe, du wirst nur links oder rechts, Mitte wird nie wahr sein. – user3029612

0

ist die Lösung für Ihre Frage,

# 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=32, 
    help="max buffer size") 
args = vars(ap.parse_args()) 

# define the lower and upper boundaries of the "green" 
# ball in the HSV color space 
greenLower = (29, 86, 6) 
greenUpper = (64, 255, 255) 

# initialize the list of tracked points, the frame counter, 
# and the coordinate deltas 
pts = deque(maxlen=args["buffer"]) 
counter = 0 
(dX, dY) = (0, 0) 
direction = "" 

# 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, blur it, and convert it to the HSV 
    # color space 
    frame = imutils.resize(frame, width=600) 
    # 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, greenLower, greenUpper) 
    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) 
      pts.appendleft(center) 

    # loop over the set of tracked points 
    for i in np.arange(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 

     # check to see if enough points have been accumulated in 
     # the buffer 
     if counter >= 10 and i == 1 and pts[-10] is not None: 
      # compute the difference between the x and y 
      # coordinates and re-initialize the direction 
      # text variables 
      dX = pts[-10][0] - pts[i][0] 
      dY = pts[-10][1] - pts[i][1] 
      (dirX, dirY) = ("", "") 

      # ensure there is significant movement in the 
      # x-direction 
      if np.abs(dX) > 20: 
       dirX = "East" if np.sign(dX) == 1 else "West" 

      # ensure there is significant movement in the 
      # y-direction 
      if np.abs(dY) > 20: 
       dirY = "North" if np.sign(dY) == 1 else "South" 

      # handle when both directions are non-empty 
      if dirX != "" and dirY != "": 
       direction = "{}-{}".format(dirY, dirX) 

      # otherwise, only one direction is non-empty 
      else: 
       direction = dirX if dirX != "" else dirY 

     # 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 movement deltas and the direction of movement on 
    # the frame 
    cv2.putText(frame, direction, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 
     0.65, (0, 0, 255), 3) 
    cv2.putText(frame, "dx: {}, dy: {}".format(dX, dY), 
     (10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 
     0.35, (0, 0, 255), 1) 

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

    # 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() 
Verwandte Themen