I want to track a moving fish from camera witch has located on top of a fish tank. Till now I was able to track the multiple moving objects using moving average and background subtraction methods. And I put text on each contour. But the problem is I couldn't keep the same label for same moving fish. Fish can detect from every frame but tracked object number is changing. I have attached my current Python code. What am I doing wrong here? Can someone tell me a another possible way to do this?
import cv2
import numpy as np
device = cv2.VideoCapture(0)
flag, frame = device.read()
movingaverage = np.float32(frame)
background = cv2.createBackgroundSubtractorMOG2()
font=cv2.FONT_HERSHEY_SIMPLEX
kernelOpen=np.ones((5,5))
kernelClose=np.ones((20,20))
while True:
flag, frame = device.read()
alpha = float(1.0/2.0)
cv2.accumulateWeighted(frame,movingaverage,alpha)
gaussion = background.apply(frame)
res = cv2.convertScaleAbs(movingaverage)
difference_img = cv2.absdiff(res, frame)
grey_difference_img = cv2.cvtColor(difference_img, cv2.COLOR_BGR2GRAY)
ret,th1 = cv2.threshold(grey_difference_img, 10, 255, cv2.THRESH_BINARY)
combine = cv2.bitwise_and(gaussion, gaussion, mask = grey_difference_img)
_, conts, h1 =cv2.findContours(combine.copy(), cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
if len(conts) == 0:
cv2.putText(frame,"No moving objects found!",(50,200), font, 1,(255,255,255),2,cv2.LINE_AA)
else:
number = 0
for i in range(len(conts)):
x,y,w,h = cv2.boundingRect(conts[i])
if (w > 50) and (h > 50):
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255), 2)
cv2.putText(frame,str(number +1)+ "object",(x,y+h), font, 1,(255,255,255),2,cv2.LINE_AA)
number = number + 1
cv2.imshow("Gaussian",gaussion)
cv2.imshow("Track",frame)
if cv2.waitKey(1) == 27:
break
device.release()
cv2.destroyAllWindows()
I have an idea but I'm not sure about that. Now I have modified the code to detect center of each and every contour. So, can I store the information about the coordinates to an array, then check the new frame contours center point such that close to array values. Then try to guess the contour which stored in array in previous frame. I don't know the possibility of this since I'm new to Python and OpenCV.
if (w > 50) and (h > 50):
cnt = conts[i]
M = cv2.moments(cnt)
if M['m00'] != 0:
cx = int(M['m10']/M['m00'])
cy = int(M['m01']/M['m00'])
#draw a circle at center of contours.
cv2.circle(frame,(cx,cy), 2, (0,0,255), -1)
print( "(",cx,",",cy,")" )
cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255), 2)
cv2.putText(frame,str(number +1)+ "object",(x,y+h), font, 1,(255,255,255),2,cv2.LINE_AA)
I have edited my code. Now it works fine if the moving objects are in the same horizontal plane. What I did was, create list called
matched_contours
andpaths
. Then append calculated center points intopaths
which in element ofmatched_contours
. And usedmin_dist
to check whether contours has presented in previous frame or not. If it has presented I have updated new center points inmatched_contour
. If not, I took it as a newmatched_contour
.THIS IS THE UPDATED PART