【问题标题】:assigning a value from one of the parameters in list to a new array将列表中参数之一的值分配给新数组
【发布时间】:2017-08-04 08:18:55
【问题描述】:

我正在开展一个项目,以使用 haar 级联检测视频中的汽车。它工作正常,但仍然有点不稳定,例如检测到不是汽车的意外物体并在一两秒内消失。所以我试着把检测到的物体的坐标突然变化的逻辑,这不是我们所期望的,但如果它没有太大变化,那就是汽车。所以我创建了以下代码

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]。但是,如果我不知道一帧中将给出多少数据,如何将值分配给固定数组?

【问题讨论】:

  • 请发布错误的完整回溯。
  • 您首先创建一个名为x 的列表,然后在您的for 循环中命名其他名称x...因为这是两个不同的对象,所以给它们不同的名称!

标签: python arrays list opencv


【解决方案1】:

写入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

这样做,您不会错过出现在视频中间的新车,也不会丢失因任何原因在一帧中无法检测到的汽车,并且很有可能避免误报。

【讨论】:

  • 哦,我是愚蠢的。我是 python 新手,所以仍然对它们感到困惑。是的,在写这篇文章之前,我实际上已经用视频进行了测试,它实际上首先发现了汽车,所以我并不担心。问题是正如你所提到的,它只能跟踪它首先检测到的汽车。你知道怎么做吗?
  • 一种简单的改进方法是维护一个检测到的区域列表(例如,最后 10 帧中的区域),然后仅在它接近 5 个时打印矩形记忆区域。
  • 查看我添加到答案中的伪代码以获得更清晰的解释。
猜你喜欢
  • 1970-01-01
  • 2019-11-25
  • 2020-05-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多