Сохраните ту же метку для движущегося объекта, используя opencv

Я хочу отслеживать движущуюся рыбу с помощью камеры, которую ведьма разместила наверху аквариума. До сих пор я мог отслеживать несколько движущихся объектов, используя методы скользящего среднего и вычитания фона. И я нанесла текст на каждый контур. Но проблема в том, что я не могу оставить одну и ту же этикетку для одной и той же движущейся рыбы. Рыбу можно обнаружить по каждому кадру, но количество отслеживаемых объектов меняется. Я прикрепил свой текущий код на Python. ? Что я здесь делаю не так? Может ли кто-нибудь подсказать мне другой возможный способ сделать это.

Спасибо

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()

У меня есть идея, но я не уверен в этом. Теперь я изменил код, чтобы определять центр каждого контура. Итак, могу ли я сохранить информацию о координатах в массиве, а затем проверить новую центральную точку контуров кадра, близкую к значениям массива. затем попробуйте угадать контур, который хранится в массиве в предыдущем кадре. Я не знаю возможности этого, так как я новичок в python и 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)

person iuhettiarachchi    schedule 20.05.2018    source источник
comment
Я нашел потоки для отслеживания нескольких объектов здесь и здесь   -  person bfris    schedule 21.05.2018
comment
Также посетите класс Multitracker. Существует учебник по нему на C ++, но его нет не выглядит слишком сложным для преобразования в Python.   -  person bfris    schedule 21.05.2018
comment
@bfris Спасибо за комментарии. Я пробовал использовать класс Multitracker. Но это не дает точного отслеживания. И это очень медленно.   -  person iuhettiarachchi    schedule 25.05.2018


Ответы (1)


Я отредактировал свой код. Теперь он отлично работает, если движущиеся объекты находятся в одной горизонтальной плоскости. Я создал список под названием matched_contours и paths. Затем добавьте вычисленные центральные точки в paths, который находится в элементе matched_contours. И использовал min_dist, чтобы проверить, представлены ли контуры в предыдущем кадре или нет. Если он появился, я обновил новые центральные точки в matched_contour. Если нет, то воспринимал как новый matched_contour.

ЭТО ОБНОВЛЕННАЯ ЧАСТЬ

im2, contours, hierarchy = cv2.findContours(dilation, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_TC89_L1)
for (_, contour) in enumerate(contours):
    (x, y, w, h) = cv2.boundingRect(contour)
    if (w >= 50) or (h >= 50): # Find targeting size moving objects
        x1 = int(w / 2)
        y1 = int(h / 2)
        cx = x + x1
        cy = y + y1

        if len(matched_contours) == 0: #No previous moving objects
            paths = []
            paths.append((cx,cy))
            object_num = object_num + 1
            matched_contours.append(((x, y, w, h), (cx,cy), object_num, paths))
            cv2.circle(frame,(cx,cy), 2, (0,0,255), -1)
            #cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255), 2)
            rect = cv2.minAreaRect(contour)
            box = cv2.boxPoints(rect)
            box = np.int0(box)
            cv2.drawContours(frame,[box],0,(0,255,0),2)
            cv2.putText(frame,"object " + str(object_num),(x,y+h), font, 0.5,(255,255,255),1,cv2.LINE_AA)

        else:
            found = False
            for i in range(len(matched_contours)):
                ponits, center, num, path = matched_contours[i]
                old_cx, old_cy = center
                #Calculate euclidian distances between new center and old centers to check this contour is existing or not
                euc_dist = math.sqrt(float((cx - old_cx)**2) + float((cy - old_cy)**2))

                if euc_dist <= min_dist:          
                    if len(path) == max_path_length:
                        for t in range(len(path)):
                            if t == max_path_length - 1:
                                path[t] = (cx,cy)
                            else:
                                path[t] = path[t+1]
                    else:
                        path.append((cx,cy))                                                  
                    matched_contours[i] = ((x, y, w, h), (cx,cy), num, path)
                    cv2.circle(frame,(cx,cy), 2, (0,0,255), -1)
                    #cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255), 2)
                    rect = cv2.minAreaRect(contour)
                    box = cv2.boxPoints(rect)
                    box = np.int0(box)
                    cv2.drawContours(frame,[box],0,(0,255,0),2)
                    cv2.putText(frame,"object " + str(num),(x,y+h), font, 0.5,(255,255,255),1,cv2.LINE_AA)    
                    #Draw path of the moving object
                    for point in range(len(path)-1):
                        cv2.line(frame, path[point], path[point+1], (255,0,0), 1)
                        cv2.circle(frame,path[point+1], 3, (0,0,255), -1)                            

            if not found: #New moving object has found
                object_num = object_num + 1
                paths = []
                paths.append((cx,cy))
                matched_contours.append(((x, y, w, h), (cx,cy), object_num, paths))
                cv2.circle(frame,(cx,cy), 2, (0,0,255), -1)
                #cv2.rectangle(frame,(x,y),(x+w,y+h),(0,0,255), 2)
                rect = cv2.minAreaRect(contour)
                box = cv2.boxPoints(rect)
                box = np.int0(box)
                cv2.drawContours(frame,[box],0,(0,255,0),2)
                cv2.putText(frame,"object " + str(object_num),(x,y+h), font, 0.5,(255,255,255),1,cv2.LINE_AA)

Надеюсь, это будет полезно.

person iuhettiarachchi    schedule 26.05.2018