1

我想从位于鱼缸顶部的摄像头女巫追踪一条移动的鱼。到目前为止,我能够使用移动平均和背景减法方法跟踪多个移动对象。我把文字放在每个轮廓上。但问题是我无法为同一条移动的鱼保留相同的标签。鱼可以从每一帧中检测到,但跟踪的对象数量正在变化。我附上了我当前的 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)
4

1 回答 1

1

我已经编辑了我的代码。现在,如果移动的物体在同一个水平面上,它就可以正常工作了。我所做的是,创建名为matched_contoursand的列表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)
于 2018-05-26T07:56:29.823 回答