Python single target, multi-target, multi-scale, user-defined characteristics of the KCF tracking algorithm (example code)


Single target tracking:

Directly call the tracker encapsulated in OpenCV.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
Created on Sun Jan 5 17:50:47 2020
Chapter 4 KCF tracking
@author: youxinlin
import cv2
from items import MessageItem
import time
import numpy as np
Monitor module, responsible for intrusion detection, target tracking
class WatchDog(object):
 #Intrusion detector module, for intrusion detection
 def __init__(self,frame=None):
  #Motion detector constructor
  self._background = None
  if frame is not None:
   self._background = cv2.GaussianBlur(cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY),(21,21),0) = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 10))
 def isWorking(self):
  #Does the motion detector work
  return self._background is not None
 def startWorking(self,frame):
  #The motion detector is working
  if frame is not None:
   self._background = cv2.GaussianBlur(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), (21, 21), 0)
 def stopWorking(self):
  #The motion detector is finished
  self._background = None
 def analyze(self,frame):
  #Motion detection
  if frame is None or self._background is None:
  sample_frame = cv2.GaussianBlur(cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY),(21,21),0)
  diff = cv2.absdiff(self._background,sample_frame)
  diff = cv2.threshold(diff, 25, 255, cv2.THRESH_BINARY)[1]
  diff = cv2.dilate(diff,, iterations=2)
  image, cnts, hierarchy = cv2.findContours(diff.copy(),cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
  coordinate = []
  bigC = None
  bigMulti = 0
  for c in cnts:
   if cv2.contourArea(c) < 1500:
   (x,y,w,h) = cv2.boundingRect(c)
   if w * h > bigMulti:
    bigMulti = w * h
    bigC = ((x,y),(x+w,y+h))
  if bigC:
   cv2.rectangle(frame, bigC[0],bigC[1], (255,0,0), 2, 1)
  message = {"coord":coordinate}
  message['msg'] = None
  return MessageItem(frame,message)
class Tracker(object):
 Tracker module, used to track the specified target
 def __init__(self,tracker_type = "BOOSTING",draw_coord = True):
  Initialize tracker type
  #Get opencv version
  (major_ver, minor_ver, subminor_ver) = (cv2.__version__).split('.')
  self.tracker_types = ['BOOSTING', 'MIL','KCF', 'TLD', 'MEDIANFLOW', 'GOTURN']
  self.tracker_type = tracker_type
  self.isWorking = False
  self.draw_coord = draw_coord
  #Construct tracker
  if int(minor_ver) < 3:
   self.tracker = cv2.Tracker_create(tracker_type)
   if tracker_type == 'BOOSTING':
    self.tracker = cv2.TrackerBoosting_create()
   if tracker_type == 'MIL':
    self.tracker = cv2.TrackerMIL_create()
   if tracker_type == 'KCF':
    self.tracker = cv2.TrackerKCF_create()
   if tracker_type == 'TLD':
    self.tracker = cv2.TrackerTLD_create()
   if tracker_type == 'MEDIANFLOW':
    self.tracker = cv2.TrackerMedianFlow_create()
   if tracker_type == 'GOTURN':
    self.tracker = cv2.TrackerGOTURN_create()
 def initWorking(self,frame,box):
  Tracker work initialization
  Frame: initialize tracking screen
  Box: tracking area
  if not self.tracker:
   Raise exception ("tracker not initialized")
  status = self.tracker.init(frame,box)
  if not status:
   raise Exception("Tracker work initialization失败")
  self.coord = box
  self.isWorking = True
 def track(self,frame):
  Turn on tracking
  message = None
  if self.isWorking:
   status,self.coord = self.tracker.update(frame)
   if status:
    message = {"coord":[((int(self.coord[0]), int(self.coord[1])),(int(self.coord[0] + self.coord[2]), int(self.coord[1] + self.coord[3])))]}
    if self.draw_coord:
     p1 = (int(self.coord[0]), int(self.coord[1]))
     p2 = (int(self.coord[0] + self.coord[2]), int(self.coord[1] + self.coord[3]))
     cv2.rectangle(frame, p1, p2, (255,0,0), 2, 1)
     message['msg'] = "is tracking"
  return MessageItem(frame,message)
class ObjectTracker(object):
 def __init__(self,dataSet):
  self.cascade = cv2.CascadeClassifier(dataSet)
 def track(self,frame):
  gray = cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY)
  faces = self.cascade.detectMultiScale(gray,1.03,5)
  for (x,y,w,h) in faces:
  return frame
if __name__ == '__main__' :
# tracker_types = ['BOOSTING', 'MIL','KCF', 'TLD', 'MEDIANFLOW', 'GOTURN']
 tracker = Tracker(tracker_type="KCF")
# video = cv2.VideoCapture(0)
# video = cv2.VideoCapture("")
 video = cv2.VideoCapture(r"/Users/youxinlin/Desktop/video_data/complex1.MOV") 
 ok, frame =
 bbox = cv2.selectROI(frame, False)
 while True:
  _,frame =;
   item = tracker.track(frame);
   k = cv2.waitKey(1) & 0xff
   if k == 27:

With, put it in the same folder:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
Created on Sun Jan 5 17:51:04 2020
@author: youxinlin
import json
from utils import IOUtil
Information encapsulation
class MessageItem(object):
 #Class used to encapsulate information, including pictures and other information
 def __init__(self,frame,message):
  self._frame = frame
  self._message = message
 def getFrame(self):
  #Picture information
  return self._frame
 def getMessage(self):
  #Text message, JSON format
  return self._message
 def getBase64Frame(self):
  #Return the image in Base64 format and convert BGR image into RGB image
  jepg = IOUtil.array_to_bytes(self._frame[...,::-1])
  return IOUtil.bytes_to_base64(jepg)
 def getBase64FrameByte(self):
  #Returns the bytes of Base64 format image
  return bytes(self.getBase64Frame())
 def getJson(self):
  #Get JSON data format
  dicdata = {"frame":self.getBase64Frame().decode(),"message":self.getMessage()}
  return json.dumps(dicdata)
 def getBinaryFrame(self):
  return IOUtil.array_to_bytes(self._frame[...,::-1]) also in the same folder.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
Created on Sun Jan 5 17:51:40 2020
@author: youxinlin
import time
import numpy
import base64
import os
import logging
import sys
from PIL import Image
from io import BytesIO
class IOUtil(object):
 #Stream operation tool class
 def array_to_bytes(pic,formatter="jpeg",quality=70):
  Static method, the numpy array into a binary stream
  : parampic: numpy array
  : param format: picture format
  : param quality: compression ratio. The higher the compression ratio, the shorter the binary data
  stream = BytesIO()
  picture = Image.fromarray(pic),format=formatter,quality=quality)
  jepg = stream.getvalue()
  return jepg
 def bytes_to_base64(byte):
  Static method, bytes to Base64 encoding
  :param byte: 
  return base64.b64encode(byte)
 def transport_rgb(frame):
  Convert BGR image to RGB image, or convert RGB image to BGR image
  return frame[...,::-1]
 def byte_to_package(bytes,cmd,var=1):
  The binary data of the picture stream of each frame is packet
  : param byte: binary
  : param CMD: Command
  head = [ver,len(byte),cmd]
  headPack = struct.pack("!3I", *head)
  senddata = headPack+byte
  return senddata
 def mkdir(filePath):
  create folder
  if not os.path.exists(filePath):
 def countCenter(box):
  Calculate the center of a rectangle
  return (int(abs(box[0][0] - box[1][0])*0.5) + box[0][0],int(abs(box[0][1] - box[1][1])*0.5) +box[0][1])
 def countBox(center):
  We calculate x, y, C, R from two points
  return (center[0][0],center[0][1],center[1][0]-center[0][0],center[1][1]-center[0][1])
 def getImageFileName():
  return time.strftime("%Y_%m_%d_%H_%M_%S", time.localtime())+'.png'

Multi target tracking:

Similar to single target, use multitracker instead_ create()

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
Created on Sun Jan 5 18:02:33 2020

manytarget tracking

@author: youxinlin
"""import numpy as np
import cv2
import sys
if len(sys.argv) != 2:
 print('Input video name is missing')
print('Select multiple tracking targets') 
camera = cv2.VideoCapture(r"/Users/youxinlin/Desktop/video_data/complex6.MOV") 
#camera = cv2.VideoCapture(0)
tracker = cv2.MultiTracker_ Create ()? Multi target tracking
a= cv2.Tracker_c
init_once = False
if not ok:
 print('Failed to read video')
bbox1 = cv2.selectROI('tracking', image)
bbox2 = cv2.selectROI('tracking', image)
bbox3 = cv2.selectROI('tracking', image)
while camera.isOpened():
 if not ok:
  print ('no image to read')
 if not init_once:
  ok = tracker.add(cv2.TrackerKCF_create(),image,bbox1)
  ok = tracker.add(cv2.TrackerKCF_create( ),image, bbox2)
  ok = tracker.add(cv2.TrackerKCF_create(),image, bbox3)
  init_once = True
 ok, boxes = tracker.update(image)
 for newbox in boxes:
  p1 = (int(newbox[0]), int(newbox[1]))
  p2 = (int(newbox[0] + newbox[2]), int(newbox[1] + newbox[3]))
  cv2.rectangle(image, p1, p2, (0,0,255))
 cv2.imshow('tracking', image)
 k = cv2.waitKey(1)
 if k == 27 : break # esc pressed

KCF of multi-scale detection, KCF of user-defined features

In some scenarios, if you don’t want to use the default hog feature tracking or need to compare the tracking effects of different features, the encapsulated method seems not to be available. You need to roll out a wave of KCF code to use your own set features.


The above is a small series to introduce you to achieve single target, multi-target, multi-scale, user-defined features of the KCF tracking algorithm, I hope to help you, if you have any questions please leave me a message, small series will reply to you in time. Thank you very much for your support to developer! If you think this article is helpful to you, please reprint, please indicate the source, thank you!