40623128 - 個人課程網站

更改影像辨識方式 << Previous Next >> 遭遇問題與解決方式

影像辨識多個球員踢球

判斷第二根桿子上兩個球員誰距離球比較近,會利用較近的球員去踢球。

由於影像輸出後要進行運算,要花費一段時間(可以看影片中的上下兩台攝影機的延遲看出),

所以模擬速度如果調整過快會導致判斷錯誤。

設定檔:tablefootball - 0601.ttt

程式碼:

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)


更改影像辨識方式 << Previous Next >> 遭遇問題與解決方式