Player and football detection using Opencv-Python in FIFA match.

Kanan Vyas
4 min readJul 24, 2018

The FIFA world cup 2018 has ended,it was so interesting that I almost watched every match and in the final France won the world cup and Croatia won the hearts.To combine my interest and academic,I started a new project by detecting players in the FIFA match and also detecting their nationality.

So the project goes like this: we will first detect the players and if there is a match of France vs. Belgium, we will mark the detected players of France and Belgium.

Algorithm

  1. For our example, we will work on the highlights video of the match between France vs. Belgium. The you tube link from where I’ve taken this video is: https://www.youtube.com/watch?v=ntQsMSuEbyg&t=49s
  2. Now first we will import the necessary libraries and read the video. Define some necessary variables.
#Import libraries
import cv2
import numpy as np
#Reading the video
vidcap = cv2.VideoCapture('cutvideo.mp4')
success,image = vidcap.read()
count = 0
success = True
idx = 0

2. Now read the video frame by frame and we will frames into HSV format. The need to convert it into HSV is, Using HSV image, we can detect any specified color background ranging from specific color codes. Here we will first detect the green ground, so the other part will become black, so it will be easy to detect our players.Moreover, HSV image will also helpful to detect our players by their nationality. We can detect France players by their blue jersey and Belgium players by their Red jersey.

#Read the video frame by frame
while success:
#converting into hsv image
hsv = cv2.cvtColor(image,cv2.COLOR_BGR2HSV)
#green range
lower_green = np.array([40,40, 40])
upper_green = np.array([70, 255, 255])
#blue range
lower_blue = np.array([110,50,50])
upper_blue = np.array([130,255,255])
#Red range
lower_red = np.array([0,31,255])
upper_red = np.array([176,255,255])
#white range
lower_white = np.array([0,0,0])
upper_white = np.array([0,0,255])

We will define a mask of our green color range to detect the ground.

#Define a mask ranging from lower to uppper
mask = cv2.inRange(hsv, lower_green, upper_green)
#Do masking
res = cv2.bitwise_and(image, image, mask=mask)
#convert to hsv to gray
res_bgr = cv2.cvtColor(res,cv2.COLOR_HSV2BGR)
res_gray = cv2.cvtColor(res,cv2.COLOR_BGR2GRAY)

Now our all images will look like this:

Green ground detected frames.

Now we will do morphological closing operations on these frames. The closing operation will fill out noise which is present in the crowd.So false detection can be reduced.

#Defining a kernel to do morphological operation in threshold #image to get better output.
kernel = np.ones((13,13),np.uint8)
thresh = cv2.threshold(res_gray,127,255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel)

Now our frames will look like this:

Now we will find contours on every frame.After finding contour we will check for only that contours, where height is greater then width, those will be detected players. Now we will do the same, we will do masking operation on the detected players for detecting their jersey color, if the jersey color is blue, we will put text as a “France” and if it is red then we will put text as a “Belgium”.

for c in contours:
x,y,w,h = cv2.boundingRect(c)

#Detect players
if(h>=(1.5)*w):
if(w>15 and h>= 15):
idx = idx+1
player_img = image[y:y+h,x:x+w]
player_hsv = cv2.cvtColor(player_img,cv2.COLOR_BGR2HSV)
#If player has blue jersy
mask1 = cv2.inRange(player_hsv, lower_blue, upper_blue)
res1 = cv2.bitwise_and(player_img, player_img, mask=mask1)
res1 = cv2.cvtColor(res1,cv2.COLOR_HSV2BGR)
res1 = cv2.cvtColor(res1,cv2.COLOR_BGR2GRAY)
nzCount = cv2.countNonZero(res1)
#If player has red jersy
mask2 = cv2.inRange(player_hsv, lower_red, upper_red)
res2 = cv2.bitwise_and(player_img, player_img, mask=mask2)
res2 = cv2.cvtColor(res2,cv2.COLOR_HSV2BGR)
res2 = cv2.cvtColor(res2,cv2.COLOR_BGR2GRAY)
nzCountred = cv2.countNonZero(res2)
if(nzCount >= 20):
#Mark blue jersy players as france
cv2.putText(image, 'France', (x-2, y-2), font, 0.8, (255,0,0), 2, cv2.LINE_AA)
cv2.rectangle(image,(x,y),(x+w,y+h),(255,0,0),3)
else:
pass
if(nzCountred>=20):
#Mark red jersy players as belgium
cv2.putText(image, 'Belgium', (x-2, y-2), font, 0.8, (0,0,255), 2, cv2.LINE_AA)
cv2.rectangle(image,(x,y),(x+w,y+h),(0,0,255),3)
else:
pass

Now for detecting football, we will detect white color using the same masking method.

if((h>=1 and w>=1) and (h<=30 and w<=30)):
player_img = image[y:y+h,x:x+w]

player_hsv = cv2.cvtColor(player_img,cv2.COLOR_BGR2HSV)
#white ball detection
mask1 = cv2.inRange(player_hsv, lower_white, upper_white)
res1 = cv2.bitwise_and(player_img, player_img, mask=mask1)
res1 = cv2.cvtColor(res1,cv2.COLOR_HSV2BGR)
res1 = cv2.cvtColor(res1,cv2.COLOR_BGR2GRAY)
nzCount = cv2.countNonZero(res1)
if(nzCount >= 3):
# detect football
cv2.putText(image, 'football', (x-2, y-2), font, 0.8, (0,255,0), 2, cv2.LINE_AA)
cv2.rectangle(image,(x,y),(x+w,y+h),(0,255,0),3)

After running this code you can see the following output:

The whole source code is given here:

--

--

Kanan Vyas

Software Engineer in ML | Founder at @clique_org | Interested in Cricket and Kathak.