2017-04-10 19 views
3

所以,我使用openCV做了基於顏色的對象檢測,並且我在覆盆子pi 3上運行它。它工作時,它實時跟蹤網球(儘管它有一些延遲,因爲我使用kinect v1(freenect庫))。現在我想確定找到的對象所在的位置。我想知道它是在中間,還是向左或向右多。我正在考慮將相機鏡頭分爲3個部分。我會有3個布爾值,一個用於中間,一個用於左邊,另一個用於右邊,然後所有3個變量將通過USB通信發送。如何,我一直在嘗試一個星期來確定對象在哪裏,但我無法做到這一點。我在這裏尋求幫助。用於使用的OpenCV物體檢測通過視頻檢測對象的位置

當前工作碼(I通過顏色檢測對象)

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

該代碼被適當地評價。使用USB端口發送信息不是問題,我只是無法找到,如何檢測球的位置。

我在我的覆盆子pi上運行raspbian。

編輯: 我忘了提及,我只對根據X軸的物體位置感興趣。我認爲,因爲我將當前框架設置爲600,所以如果像if x > 200 && x < 400: bool middle = true那樣我會寫3。它不工作,你。

EDIT2: 我覺得我能以某種方式工作,但「中間」永遠不會是真的。我左右爲真,但不適合中等。

+0

是不是'center'球的實際中心?你對此感到滿意嗎?我會這樣做,但不是'int'使用'double'。這應該是你正在尋找的。 –

回答

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 

我不得不寫的是「AND」 insted的的「&」 ......這麼多的麻煩,這樣一個小的修復。

0

如果您要檢測其位置的對象,那麼它會比使用cv2.findContours()更好,以使用cv2.HoughCircles()。由於cv2.HoughCircles()直接返回圓的中心位置(x,y)。

您可以使用HoughCircles()here

如果收到圓心然後確定其位置將是容易的樣品。

祝你好運。

+0

我會在我現在怎麼做的時候發佈編輯,你我只會左或右,中間永遠不會是真的。 – user3029612

0

這裏是你的問題的解決,

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