Beberapa waktu yang lalu ada yang menanyakan perihal lambatnya operasi openCV yang diintegrasikan dengan wxPython. Setelah melihat kode yang dipakai, ternyata penyebabnya adalah operasi deteksi objek yang menggunakan CascadeClassifier yang dilakukan setiap frame. Walaupun konon operasi pendeteksian objek menggunakan detektor CascadeClasifier merupakan state-of-the-art mendeteksi tercepat (baik menggunakan fitur Haar, ataupun yang lebih cepat lagi dengan menggunakan Local Binary Pattern), Operasi ini sangat tidak dianjurkan dijalankan di setiap frame karena tidak efisien.
Penjejakan (tracking) objek dengan cara mendeteksi objek di tiap frame merupakan cara yang paling naif karena setiap piksel pada beberapa tingkatan skala akan diperiksa. Cara yang lebih cerdas adalah memanfaatkan informasi yang sebelumnya sudah diketahui (deteksi pada frame sebelumnya), dan memanfaatkan asumsi bahwa objek yang diikuti tidak akan bergerak jauh dalam rentang dua buah gambar yang berurutan. Pada umumnya asumsi ini dapat dimanfaatkan, dengan pengecualian jika terjadi penutupan objek selama beberapa frame ataupun jika ada lebih dari satu objek yang diikuti dalam area yang berdekatan atau bersinggungan.
Berikut ini akan dijabarkan contoh penjejakan objek secara sederhana dengan memanfaatkan informasi dari hasil deteksi dan template matching. Teknik ini sangat sederhana karena informasi yang diestimasi hanyalah posisi dua dimensi (tidak menangani perubahan skala atau rotasi). Sederhananya proses penjejakan dilakukan dalam dua tahap yaitu deteksi dan estimasi. Jika belum ada objek yang terdeteksi maka proses deteksi akan dijalankan hingga ada yang terdeteksi. Jika sudah ada objek yang terdeteksi maka sudah ada informasi sebelumnya yang dapat dimanfaatkan yaitu posisi, area, dan isi area yang mendeskripsikan objek yang diikuti. Dengan demikian posisi objek pada gambar berikutnya dapat dilakukan dengan mencari area yang paling mirip di sekitar posisi awal (posisi hasil deteksi atau estimasi di gambar sebelumnya). Ukuran kemiripan dihitung dengan menggunakan beberapa cara. Cara yang paling umum adalah menggunakan metrik euclidean yaitu selisih dua buah vektor yang kemudian tiap elemennya dikuadratkan dan dijumlahkan sehingga menghasilkan konotasi jarak.
Kode berikut dapat dicoba dan dipelajari lebih lanjut agar konsep penjejakan dapat dipahami.
import numpy as np
import cv2
import cv
#video_src = 0 #webcam
video_src = r"angklung\angklung.avi"
cascade_fn = "lbpcascade_frontalface.xml"
#cascade_fn = "haarcascade_frontalface_alt.xml"
cascade = cv2.CascadeClassifier(cascade_fn)
cam = cv2.VideoCapture(video_src)
gotface = False
while True:
ret, img = cam.read()
if not ret: break
gray = cv2.cvtColor(img, cv.CV_BGR2GRAY)
if not gotface: #detect a face
rects = cascade.detectMultiScale(img, scaleFactor=1.1, minNeighbors=2, minSize=(20, 20))
if len(rects)>0:
gotface = True
x,y,width,height = rects[0]
#create the first template for tracking from detected area
face = np.array([0]*width*height, dtype=np.uint8).reshape((width,height))
face[:,:] = gray[y:y+height,x:x+width]
else: #track that face
#window enlargement value to be used as search area
wnd = min(width, height)/4
#track using squared difference measurement
result = cv2.matchTemplate(gray[y-wnd:y+height+wnd,x-wnd:x+width+wnd], face, cv.CV_TM_SQDIFF)
#alternative measurement to track object, but more prone to drifting (COEFF > CCORR) than previous approach
#result = cv2.matchTemplate(gray[y-wnd:y+height+wnd,x-wnd:x+width+wnd], face, cv.CV_TM_CCORR)
#result = result.max()-result #inverse the value if CCOEFF is used
yy,xx = np.unravel_index(result.argmin(), result.shape)
x,y = (x-wnd) + xx, (y-wnd) + yy
alpha = 0.5 #blending factor for template updating
face[:,:] = face*alpha + (1.0-alpha) * gray[y:y+height, x:x+width]
if gotface: #display tracked face
cv2.rectangle(img, (x, y), (x+width, y+height), (255,0,0), 2)
cv2.imshow('faceregion',face)
cv2.imshow('facedetect',img)
if cv2.waitKey(20) == 27: break
Pada kode di atas, kedua tahapan diimplementasi dengan menggunakan analisa kasus terhadap variabel gotface yang menyatakan ada atau tidaknya objek yang sudah terdeteksi. Contoh di atas juga ada beberapa bagian yang dikomentari dengan tujuan sebagai percobaan mandiri misalnya pada bagian ukuran alternatif yang secara prinsip menggunakan operasi perkalian bukan pengurangan seperti pada metode SQDIFF.
Gambar berikut menunjukkan kinerja beberapa metode yang digunakan dalam Template Matching. Kotak berwarna biru adalah metode CV_TM_SQDIFF, kotak berwarna hijau adalah metode CV_TM_CCORR, dan kotak berwarna merah adalah metode CV_TM_CCOEFF. Gambar diambil dari frame terakhir yang diproses. Pada awal deteksi setiap metode berangkat dari tempat yang sama. Pada gambar tersebut terlihat metode CCOEFF paling melenceng dari objek wajah sedangkan kinerja yang hampir sama ditunjukkan oleh metode CCORR dan SQDIFF.
perbandingan beberapa metode template matching untuk tracking objek. Video diambil dari youtube tentang saung angklung Udjo.
NB:Oya, saya lupa mencantumkan informasi kode tersebut dijalankan di OpenCV versi 2.3.1