2017-08-04 84 views
-2

我正在研究使用哈尔级联在视频中检测汽车的项目。它运转良好,但仍然有点不稳定,比如意外的物体不是汽车被检测到并在一秒钟或两秒钟内消失。所以我试图把被检测物体的坐标逻辑突然改变,这不是我们所期望的,但是如果它没有太大改变,那就是汽车。所以,我创建了下面的代码将列表中的参数中的值分配给新阵列

import cv2 

cap = cv2.VideoCapture('C:\\Users\\john\\Desktop\\bbd3.avi') 
car_cascade = cv2.CascadeClassifier('C:\\Users\\john\\Desktop\\cars.xml') 

i=0 
x = [None] * 10000000 
y = [None] * 10000000 

while (cap.isOpened()): 
    ret, frame = cap.read() 
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 
    roi_gray = gray[0:480, 100:300] 
    roi_color = frame[0:480, 100:300] 

    # roi_gray defines area in the video that we will apply haar cascade detection 
    # we add roi_color with same area to draw rectangle on the color frame axis 

    cars = car_cascade.detectMultiScale(roi_gray, 1.05, 5, minSize=(30,30)) 
    # we can specify the value of certain parameter by mentioned name of that parameter before that value. parameter is image, scalefactor, minneigbors, minsize. 

    for (x,y,w,h) in cars: 
     x[i]=x 
     y[i]=y 
     if i>= 1: 
      if abs(x[i]-x[i-1]) < 10 and abs(y[i]-y[i-1]) < 10 : 
       cv2.rectangle(roi_color, (x,y), (x+w,y+h), (255,0,0),2) 


    cv2.imshow('frame', frame) 
    i=i+1 
    if cv2.waitKey(1) == 27: 
     break 


cv2.destroyAllWindows() 

这里detectmultiscale返回将检测到的物体位于矩形的名单。基本上是创建一个空阵列并将左底部坐标分配给阵列并在连续帧之间进行比较。然而,它不断返回

TypeError: 'numpy.int32' object does not support item assignment 

所以,我可以得到任何想法,为什么这首先发生,如何解决它?提前致谢。

*另外,对于那些之前没有处理过opencv的人,detectmultiscale会返回矩形列表,但根据视频中检测到多少物体,可能会返回多个矩形。例如,如果在第一帧中检测到一辆车,则它只返回一个矩形,但如果在第二帧中检测到三辆车,则返回三个矩形。我认为这是这里的主要问题。将多个值分配给一个参数x [i]。但是,如果我不知道在一个帧中将给出多少数据,我如何将值赋给一个固定数组?

+1

请发布错误的完整追溯。 –

+0

您首先创建一个名为'x'的列表,然后在'for'循环中命名其他'x' ...因为这些是两个不同的对象,请给它们不同的名称! –

回答

0

当编写for (x,y,w,h) in cars时,名为x的对象变为由detectMultiScale返回的numpy.int32(整数)。

现在,当Python到达x[i]=x时,它首先评估正确的值。这是一个整数。 然后它试图“评估”左边的值,但3[2]在Python中没有意义,所以它失败了。

下面我将如何重构代码:

import cv2 

MAX_DIST = 10 

cap = cv2.VideoCapture('C:\\Users\\john\\Desktop\\bbd3.avi') 
car_cascade = cv2.CascadeClassifier('C:\\Users\\john\\Desktop\\cars.xml') 

cars_coordinates = [] 

while (cap.isOpened()): 
    ret, frame = cap.read() 
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) 
    roi_gray = gray[0:480, 100:300] 
    roi_color = frame[0:480, 100:300] 

    cars = car_cascade.detectMultiScale(roi_gray, 1.05, 5, minSize=(30,30)) 

    for (x,y,w,h) in cars: 
     if cars_coordinates: 
      last_x, last_y = cars_coordinates[-1] 
      if abs(x - last_x) < MAX_DIST and abs(y - last_y) < MAX_DIST : 
       cv2.rectangle(roi_color, (x,y), (x+w,y+h), (255,0,0),2) 
       cars_coordinates.append((x,y)) # adding the coordinates here allows to keep track of only your past detected cars 


    cv2.imshow('frame', frame) 
    if cv2.waitKey(1) == 27: 
     break 

警告你的算法:我纠正原样,但该算法,如果detectMultiScale第一检测是假阳性,你不会“回到”真正的汽车。另外,你只能跟踪一辆车。对于一个稍微好一点的算法

伪代码:

During 5 frames, only memorize the detected areas 

When handling a new frame, for each detected car: 
    if the car is near a memorized area in at least 4 of the last 5 frames: 
     Consider it as a car 
    Append it anyway to the detected areas for this frame 

这样这样,你将不会错过新车出现在您的视频中,也没有松动,不会一直在检测到车无论出于何种原因都有一个框架,误报有很好的机会可以避免。

+0

哦,我很愚蠢。我是python的新手,所以仍然与他们混淆。是的,在写这个之前我已经用视频测试过了,它实际上首先发现了汽车,所以我不担心这个问题。问题就像你刚才提到的那样,它只能跟踪它首先检测到的汽车。你有什么想法如何做到这一点? –

+0

改进它的一个简单方法是维护一个检测到的区域列表(例如,在最后10帧中的区域),然后只在接近5个记忆区域时才打印该矩形。 – b1ch0u

+0

查看我添加到我的答案中的伪代码以获得更清晰的解释。 – b1ch0u