微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 OpenCV 的占用计数器

如何解决使用 OpenCV 的占用计数器

我使用 OpenCV 创建了一个占用计数器。当我导入视频时,代码运行良好,并在他们通过时计算人数。但是当我将数据输入更改为网络摄像头时,计数无法正常工作。有时它会计算一个人,有时它不会(尽管它可以正确跟踪它们),有时它会将一个人计算为多个。我假设该算法不够快,无法处理实时数据输入,并且视频输入帧比实时视频输入少。有关如何解决此问题的任何想法?

请在下面找到最少的可重现代码

cap = cv.VideoCapture("C:\\Users\\USER_NAME\\Downloads\\example_01.mp4")

# Print the capture properties to console

for i in range(19):
    print( i,cap.get(i))

h = 480
w = 640

frameArea = h*w
areaTH = frameArea/250
print( 'Area Threshold',areaTH)

# Entry / exit lines
line_up = int(1*(h/5))
line_down   = int(2*(h/5))

up_limit =   int(0.5*(h/5))
down_limit = int(2.5*(h/5))

#Background Subtractor

fgbg = cv.createBackgroundSubtractormog2(detectShadows = True)
while(cap.isOpened()):
    ret,frame = cap.read()

try:
    ret,imBin= cv.threshold(fgmask,200,255,cv.THRESH_BINARY)
    ret,imBin2 = cv.threshold(fgmask2,cv.THRESH_BINARY)
    #opening (erode-> dilate) to remove noise.
    mask = cv.morphologyEx(imBin,cv.MORPH_OPEN,kernelOp)
    mask2 = cv.morphologyEx(imBin2,kernelOp)
    #Closing (dilate -> erode) to join white regions.
    mask =  cv.morphologyEx(mask,cv.MORPH_CLOSE,kernelCl)
    mask2 = cv.morphologyEx(mask2,kernelCl)
except:
    print('EOF')enter code here
    print( 'UP:',cnt_up)
    print ('DOWN:',cnt_down)
    break

contours0,hierarchy = 
cv.findContours(mask2,cv.RETR_EXTERNAL,cv.CHAIN_APPROX_SIMPLE)
for cnt in contours0:
    area = cv.contourArea(cnt)
    if area > areaTH:
        #################
        #   TRACKING    #
        #################
        
        M = cv.moments(cnt)
        cx = int(M['m10']/M['m00'])
        cy = int(M['m01']/M['m00'])
        x,y,w,h = cv.boundingRect(cnt)

        new = True
        if cy in range(up_limit,down_limit):
            for i in persons:
                if abs(x-i.getX()) <= w and abs(y-i.getY()) <= h:
                    # the object is close to one that has already been detected before
                    new = False
                    i.updateCoords(cx,cy)   # update coordinates in the object and resets age
                    if i.going_UP(line_down,line_up) == True:
                        cnt_up += 1;
                        print( "ID:",i.getId(),'crossed going up at',time.strftime("%c"))
                        log.write("ID: "+str(i.getId())+' crossed going up at ' + time.strftime("%c") + '\n')
                    elif i.going_DOWN(line_down,line_up) == True:
                        cnt_down += 1;
                        print( "ID:",'crossed going down at',time.strftime("%c"))
                        log.write("ID: " + str(i.getId()) + ' crossed going down at ' + time.strftime("%c") + '\n')
                    break
                if i.getState() == '1':
                    if i.getDir() == 'down' and i.getY() > down_limit:
                        i.setDone()
                    elif i.getDir() == 'up' and i.getY() < up_limit:
                        i.setDone()
                if i.timedOut():
                    #sacar i de la lista persons
                    index = persons.index(i)
                    persons.pop(index)
                    del i     #release the memory of i
            if new == True:
                p = Person1.MyPerson(pid,cx,cy,max_p_age)
                persons.append(p)
                pid += 1     
        
        cv.circle(frame,(cx,cy),5,(0,255),-1)
        img = cv.rectangle(frame,(x,y),(x+w,y+h),0),2)

感谢和问候

苏拉布

解决方法

我无法运行您的代码,但如果是实时视频源的问题,我为您提供了以下解决方案:

# Define the thread that will continuously pull frames from the camera
class CameraBufferCleanerThread(threading.Thread):
    def __init__(self,camera,name='camera-buffer-cleaner-thread'):
        self.camera = camera
        self.last_frame = None
        self.cancel = False
        super(CameraBufferCleanerThread,self).__init__(name=name)
        self.start()

    def run(self):
        while not self.cancel:
            ret,self.last_frame = self.camera.read()

这将创建一个线程并始终拉取最新的帧并将其存储在 last_frame 属性中。

要使用它,只需在上述类中填充视频捕获并获取循环中的最新帧。

vcap = cv2.VideoCapture("rtsp://user:pass@10.0.0.5:554/s0")
# Start the cleaning thread
cam_cleaner = CameraBufferCleanerThread(vcap)

while(1):
    if cam_cleaner.last_frame is None:
        continue

    image = cam_cleaner.last_frame.copy()

我遇到了类似的问题,这为我解决了。看来这也能帮你解决。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。