判斷第二根桿子上兩個球員誰距離球比較近,會利用較近的球員去踢球。
由於影像輸出後要進行運算,要花費一段時間(可以看影片中的上下兩台攝影機的延遲看出),
所以模擬速度如果調整過快會導致判斷錯誤。
程式碼:
import vrep import time import random as rng from PIL import Image as I import array import math import cv2, numpy def speed(handle,speed): vrep.simxSetJointTargetVelocity(clientID,handle,speed,vrep.simx_opmode_oneshot_wait) #影像尋找藍色物件 def track_blue_object(image): # Blur the image to reduce noise100 blur = cv2.GaussianBlur(image, (3,3),0) # Convert BGR to HSV hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV) # Threshold the HSV image for only blue colors ran = 20 lower_blue = numpy.array([0-ran,100,100]) upper_blue = numpy.array([0+ran,255,255]) # Threshold the HSV image to get only blue colors mask = cv2.inRange(hsv, lower_blue, upper_blue) # Blur the mask bmask = cv2.GaussianBlur(mask, (5,5),0) threshold = 100 canny_output = cv2.Canny(bmask, threshold,threshold*2) contours, _ = cv2.findContours(canny_output, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Get the moments mu = [None]*len(contours) for i in range(len(contours)): mu[i] = cv2.moments(contours[i]) # Get the mass centers mc = [None]*len(contours) for i in range(len(contours)): mc[i] = (mu[i]['m10'] / (mu[i]['m00']), mu[i]['m01'] / (mu[i]['m00'])) return mc #影像尋找紅色物件 def track_red_object(image): # Blur the image to reduce noise100 blur = cv2.GaussianBlur(image, (3,3),0) # Convert BGR to HSV hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV) # Threshold the HSV image for only blue colors ran = 15 lower_red = numpy.array([120-ran,100,100]) upper_red = numpy.array([120+ran,255,255]) # Threshold the HSV image to get only blue colors mask = cv2.inRange(hsv, lower_red, upper_red) # Blur the mask bmask = cv2.GaussianBlur(mask, (5,5),0) threshold = 100 canny_output = cv2.Canny(bmask, threshold,threshold*2) contours, _ = cv2.findContours(canny_output, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Get the moments mu = [None]*len(contours) for i in range(len(contours)): mu[i] = cv2.moments(contours[i]) # Get the mass centers mc = [None]*len(contours) for i in range(len(contours)): # add 1e-5 to avoid division by zero mc[i] = (mu[i]['m10'] / (mu[i]['m00'] ), mu[i]['m01'] / (mu[i]['m00'])) return mc #影像尋找綠色物件 def track_green_object(image): # Blur the image to reduce noise100 blur = cv2.GaussianBlur(image, (5,5),0) # Convert BGR to HSV hsv = cv2.cvtColor(blur, cv2.COLOR_BGR2HSV) # Threshold the HSV image for only green colors range = 15 lower_green = numpy.array([60-range,100,100]) upper_green = numpy.array([60+range,255,255]) # Threshold the HSV image to get only green colors mask = cv2.inRange(hsv, lower_green, upper_green) # Blur the mask bmask = cv2.GaussianBlur(mask, (5,5),0) # Take the moments to get the centroid moments = cv2.moments(bmask) m00 = moments['m00'] centroid_x, centroid_y = None, None if m00 != 0: centroid_x = int(moments['m10']/m00) centroid_y = int(moments['m01']/m00) # Assume no centroid ctr = None # Use centroid if it exists if centroid_x != None and centroid_y != None: ctr = (centroid_x, centroid_y) return ctr vrep.simxFinish(-1) clientID = vrep.simxStart('127.0.0.1', 19997, True, True, 5000, 5) blue00=blue10=blue11=blue20=blue21=blue22=blue30=blue31=blue32=None red00=red10=red11=red20=red21=red22=red30=red31=red32=None KickBallV =360 R_KickBallVel = (math.pi/180)*KickBallV B_KickBallVel = -(math.pi/180)*KickBallV if clientID!=-1: print('Connected to remote API server') # get vision sensor objects res, v0 = vrep.simxGetObjectHandle(clientID, 'vs1', vrep.simx_opmode_oneshot_wait) res, v1 = vrep.simxGetObjectHandle(clientID, 'vs2', vrep.simx_opmode_oneshot_wait) err, resolution, image = vrep.simxGetVisionSensorImage(clientID, v0, 0, vrep.simx_opmode_streaming) err,BRev_handle=vrep.simxGetObjectHandle(clientID,'BRev',vrep.simx_opmode_oneshot_wait) err,BRev0_handle=vrep.simxGetObjectHandle(clientID,'BRev0',vrep.simx_opmode_oneshot_wait) err,BRev1_handle=vrep.simxGetObjectHandle(clientID,'BRev1',vrep.simx_opmode_oneshot_wait) err,BMo_handle=vrep.simxGetObjectHandle(clientID,'BMo',vrep.simx_opmode_oneshot_wait) err,BMo0_handle=vrep.simxGetObjectHandle(clientID,'BMo0',vrep.simx_opmode_oneshot_wait) err,RRev_handle=vrep.simxGetObjectHandle(clientID,'RRev',vrep.simx_opmode_oneshot_wait) err,RRev0_handle=vrep.simxGetObjectHandle(clientID,'RRev0',vrep.simx_opmode_oneshot_wait) err,RRev1_handle=vrep.simxGetObjectHandle(clientID,'RRev1',vrep.simx_opmode_oneshot_wait) err,RMo0_handle=vrep.simxGetObjectHandle(clientID,'RMo0',vrep.simx_opmode_oneshot_wait) err,RMo_handle=vrep.simxGetObjectHandle(clientID,'RMo',vrep.simx_opmode_oneshot_wait) time.sleep(1) while (vrep.simxGetConnectionId(clientID) != -1): # get image from vision sensor 'v0' blue00_pos=blue10_pos=blue11_pos=blue20_pos=blue21_pos=blue22_pos=blue30_pos=blue31_pos=blue32_pos=None red00_pos=red10_pos=red11_pos=red20_pos=red21_pos=red22_pos=red30_pos=red31_pos=red32_pos=None err, resolution, image = vrep.simxGetVisionSensorImage(clientID, v0, 0, vrep.simx_opmode_buffer) if err == vrep.simx_return_ok: image_byte_array = array.array('b', image) image_buffer = I.frombuffer("RGB", (resolution[0],resolution[1]), bytes(image_byte_array), "raw", "RGB", 0, 1) img2 = numpy.asarray(image_buffer) ret_blue = track_blue_object(img2) ret_red = track_red_object(img2) ret_green = track_green_object(img2) if ret_green != None: #各球員座標命名方式 # blue(x)(y) x = 第幾根桿子(0~3) y = 左邊數來第幾個人(0~2) # red(x)(y) x = 第幾根桿子(0~3) y = 左邊數來第幾個人(0~2) #刪除重複的座標 times_of_del_ret_blue = int(len(ret_blue)/2) times_of_del_ret_red = int(len(ret_red)/2) #times_of_del_ret_green = int(len(ret_green)/2) for i in range(0,times_of_del_ret_blue): if ret_blue[i][1] - ret_blue[i+1][1] <= 1: del ret_blue[i] for i in range(0,times_of_del_ret_red): if ret_red[i][1] - ret_red[i+1][1] <= 1: del ret_red[i] #藍球員座標命名 for i in range(len(ret_blue)): if ret_blue[i][1] >=10 and ret_blue[i][1] <=25: blue00 = (ret_blue[i][0], ret_blue[i][1]) elif ret_blue[i][1] >= 40 and ret_blue[i][1] <=70: blue10_pos = (ret_blue[i][0], ret_blue[i][1]) if blue11_pos== None: blue11_pos= (ret_blue[i][0], ret_blue[i][1]) elif ret_blue[i][1] >=90 and ret_blue[i][1] <=130: if blue20_pos == None: if blue22_pos == None: blue22_pos = (ret_blue[i][0], ret_blue[i][1]) elif blue21_pos == None: blue21_pos = (ret_blue[i][0], ret_blue[i][1]) elif blue20_pos == None: blue20_pos = (ret_blue[i][0], ret_blue[i][1]) elif ret_blue[i][1] >=140 and ret_blue[i][1] <=180: if blue30_pos == None: if blue32_pos == None: blue32_pos = (ret_blue[i][0], ret_blue[i][1]) elif blue31_pos == None: blue31_pos = (ret_blue[i][0], ret_blue[i][1]) elif blue30_pos == None: blue30_pos = (ret_blue[i][0], ret_blue[i][1]) #藍球員10和11座標排列 if blue10_pos[0] < blue11_pos[0]: blue10 = blue10_pos blue11 = blue11_pos elif blue10_pos[0] > blue11_pos[0]: blue10 = blue11_pos blue11 = blue10_pos #紅球員座標命名 for i in range(len(ret_red)): if ret_red[i][1] >=230 and ret_red[i][1] <=250: red00 = (ret_red[i][0], ret_red[i][1]) elif ret_red[i][1] >= 185 and ret_red[i][1] <=205: red10_pos = (ret_red[i][0], ret_red[i][1]) if red11_pos == None: red11_pos = (ret_red[i][0], ret_red[i][1]) elif ret_red[i][1] >=134 and ret_red[i][1] <=154: if red21_pos == None: if red22_pos == None: red22_pos = (ret_red[i][0], ret_red[i][1]) elif red20_pos == None: red20_pos = (ret_red[i][0], ret_red[i][1]) elif red21_pos == None: red21_pos = (ret_red[i][0], ret_red[i][1]) elif ret_red[i][1] >=80 and ret_red[i][1] <=100: if red30_pos == None: if red32_pos == None: red32_pos = (ret_red[i][0], ret_red[i][1]) elif red31_pos == None: red31_pos = (ret_red[i][0], ret_red[i][1]) elif red30_pos == None: red30_pos = (ret_red[i][0], ret_red[i][1]) #紅球員10和11座標排列 if red10_pos[0] < red11_pos[0]: red10 = red10_pos red11 = red11_pos elif blue10_pos[0] > blue11_pos[0]: red10 = red11_pos red11 = red10_pos #------------------------------對打程式開始------------------------------ Bv = ret_green[0] - blue00[0] BBv=ret_green[1] - blue00[1] Rv = ret_green[0] - red00[0] RRv=ret_green[1] - red00[1] #藍守門員移動 if Bv<0.0: speed(BMo_handle,Bv*-0.02) elif Bv>0.0: speed(BMo_handle,Bv*-0.02) else: pass #紅守門員移動 if Rv<0.0: speed(RMo_handle,Rv*-0.02) elif Rv>0.0: speed(RMo_handle,Rv*-0.02) else: pass #藍桿一移動 B10v = ret_green[0] - blue10[0] B11v = ret_green[0] - blue11[0] if abs(B10v) <= abs(B11v): if ret_green[0] < 147 : if B10v < 0: speed(BMo0_handle,B10v*-0.02) elif B10v > 0: speed(BMo0_handle,B10v*-0.02) else: pass else: speed(BMo0_handle,0.5) elif abs(B10v) > abs(B11v): if ret_green[0] >108: if B11v < 0: speed(BMo0_handle,B11v*-0.02) elif B11v > 0: speed(BMo0_handle,B11v*-0.02) else: pass else: speed(BMo0_handle,-0.5) #紅桿一移動 R10v = ret_green[0] - red10[0] R11v = ret_green[0] - red11[0] if abs(R10v) <= abs(R11v): if ret_green[0] < 147 : if R10v < 0: speed(RMo0_handle,R10v*-0.02) elif R10v > 0: speed(RMo0_handle,R10v*-0.02) else: pass else: speed(BMo0_handle,0.5) elif abs(R10v) > abs(R11v): if ret_green[0] >108: if R11v < 0: speed(RMo0_handle,R11v*-0.02) elif R11v > 0: speed(RMo0_handle,R11v*-0.02) else: pass else: speed(RMo0_handle,-0.5) #藍守門員踢球 if blue00[1] >=18 and ret_green[1] <= 17: if ret_green[0] >62.5: speed(BMo_handle,2) time.sleep(0.1) speed(BRev_handle,20) time.sleep(0.1) if ret_green[1] != blue00[1]: Bv = ret_green[0]-blue00[0] if Bv<0.0: speed(BMo_handle,Bv*-0.02) elif Bv>0.0: speed(BMo_handle,Bv*-0.02) else: pass else: speed(BRev_handle,2) elif ret_green[0] <62.5: speed(BMo_handle,-2) time.sleep(0.1) speed(BRev_handle,20) time.sleep(0.1) if ret_green[1] != blue00[1]: Bv = ret_green[0] - blue00[0] if Bv<0.0: speed(BMo_handle,Bv*-0.02) elif Bv>0.0: speed(BMo_handle,Bv*-0.02) else: pass else: speed(BRev_handle,2) elif ret_green[0] - blue00[0] >= -3 and ret_green[0] - blue00[0] <= 3: if BBv<10.0: speed(BRev_handle,-2) elif BBv>10.0: speed(BRev_handle,2) else: pass #紅守門員踢球 if red00[1] <=236 and ret_green[1] >= 237: if ret_green[0] >62.5: speed(RMo_handle,2) time.sleep(0.1) speed(RRev_handle,-20) time.sleep(0.1) if ret_green[1] != ret_red[1]: Rv = ret_green[0] - red00[0] if Rv < 0.0: speed(RMo_handle,Rv*-0.02) elif Rv>0.0: speed(RMo_handle,Rv*-0.02) else: pass else: speed(RRev_handle,2) elif ret_green[0] <62.5: speed(RMo_handle,-2) time.sleep(0.1) speed(RRev_handle,-20) time.sleep(0.1) if ret_green[1] != red00[1]: Rv = ret_green[0] - red00[0] if Rv<0.0: speed(RMo_handle,Rv*-0.02) elif Rv>0.0: speed(RMo_handle,Rv*-0.02) else: pass else: speed(RRev_handle,2) elif ret_green[0] - red00[0] >= -3 and ret_green[0] - red00[0] <= 3: if RRv<-10.0: speed(RRev_handle,-2) elif RRv>-10.0: speed(RRev_handle,2) else: pass #藍桿一踢球 if ret_green[1] <= 70 and ret_green[1] >= 55: speed(BRev0_handle,B_KickBallVel) speed(BRev1_handle,B_KickBallVel) else: speed(BRev0_handle,R_KickBallVel) speed(BRev1_handle,R_KickBallVel) #紅桿一踢球 if ret_green[1] <= 202 and ret_green[1] >= 187: speed(RRev0_handle,R_KickBallVel) speed(RRev1_handle,R_KickBallVel) else: speed(RRev0_handle,B_KickBallVel) speed(RRev1_handle,B_KickBallVel) #對打程式結束 #影像加框處理 if ret_blue: for i in range(len(ret_blue)): cv2.rectangle(img2,(int(ret_blue[i][0] - 2),int(ret_blue[i][1] - 5)), (int(ret_blue[i][0] + 2),int(ret_blue[i][1] + 5)), (0x33,0xcc,0xff), 1) if ret_red: for i in range(len(ret_red)): cv2.rectangle(img2,(int(ret_red[i][0] - 2),int(ret_red[i][1] - 5)), (int(ret_red[i][0] + 2),int(ret_red[i][1] + 5)), (0xff,0x33,0x33), 1) if ret_green: cv2.rectangle(img2,(ret_green[0]-5,ret_green[1]-5), (ret_green[0]+5,ret_green[1]+5), (0x99,0xff,0x33), 1) img2 = img2.ravel() #影像回傳 vrep.simxSetVisionSensorImage(clientID, v1, img2, 0, vrep.simx_opmode_oneshot) elif err == vrep.simx_return_novalue_flag: print("no image yet") pass else: print(err) else: print("Failed to connect to remote API Server") vrep.simxFinish(clientID)