代码之家  ›  专栏  ›  技术社区  ›  Matias Andina

将deque保存到csv数据帧中

  •  0
  • Matias Andina  · 技术社区  · 6 年前

    我正在使用跟踪元素视频 opencv (基本上计算HSV阈值后的元素数)。我有一个 deque 用于存储质心位置的缓冲区。我选择了64个有限的缓冲区(30 fps时大约2秒,可能更长)。我的目标是将数据保存到 .csv 文件的格式,我可以随时使用(见下文)。另外,我正在计算检测到的区域的数量。格式应该是

    cX  cY  number
    444 265   19
    444 265   19
    444 264   19
    444 264   19
    ...
    

    cX 在x和 cY 最大元素y的形心,以及检测区域的数目。列命名不是主要的目标,尽管这很好。

    出于显示目的,我需要将质心 tuple . 我让他们一帧一帧地成长 appendleft :

    center_points = deque(maxlen=64)
    object_number = deque(maxlen=64)
    iteration_counter = 1
    
        while True
    
    
            # read video frames..
            # do stuff...
            # get contours
                my_cnts = cv2.findContours(...)
            # get largest object
                c = max(my_cnts, key=cv2.contourArea)
                ((x, y), radius) = cv2.minEnclosingCircle(c)
                M = cv2.moments(c)
                big_center = (int(M["m10"] / M["m00"]), int(M["m01"] / M["m00"]))
    # count object number as int name it 'num'
    
    center_points.appendleft(big_center)
    object_number.appendleft(num)
    

    现在,当缓冲区已满时,我要将数据保存到文件中):

    # Convert to array to save
        # Wait until the iteration number is divisible by the buffer length
        if(iteration_number % 64 == 0):
            print("Saving on iteration..." + str(iteration_number))
            array_to_save = np.array([center_points, object_number]).T
    
    
            with open(filename,'a') as outfile:
                np.savetxt(outfile, array_to_save,
                           delimiter=',', fmt='%s')
    # Add 1 to the counter
        iteration_number = iteration_number + 1
    

    问题

    上面的代码工作并编写如下内容:

    (444 265) 19
    (444 265) 19
    (444 264) 19
    (444 263) 19
    

    我想做点什么 np.array(center_points) 把它绑在 object_number . 我在尺寸方面遇到了问题(例如,(64,2)和(64)不兼容)。我试过了 np.append np.stack 但是找不到正确的数据格式。

    否则,我可以保持代码的原样,但我想以某种方式去掉列1和列2上的括号,然后保存该对象(尝试了对 array_to_save 没有成功)。所有三列都应该是数字或保存为字符串,但在以后的读取中很容易检索为数字。

    更新

    基于我尝试的评论

    array_to_save = np.concatenate([np.array(center_points), object_number[:, None]])
        TypeError: sequence index must be integer, not 'tuple'
    

    我也尝试过

    array_to_save = np.concatenate([np.array(center_points), np.array(object_number)[:, None]])
        ValueError: all the input array dimensions except for the concatenation axis must match exactly
    
    2 回复  |  直到 6 年前
        1
  •  1
  •   a_guest    6 年前

    你可以 concatenate 沿列维度的数组以创建 (X, 3) 数组超出 (X, 2) (X,) 数组。为了准备好连接,所有数组都需要具有相同数量的维度,因此需要向平面数组添加额外的维度。 object_number : (X,) -> (X, 1) . 这可以通过 object_number[:, np.newaxis] object_number[:, None] . 完整的解决方案是:

    np.concatenate([np.array(center_points),
                    np.array(object_number)[:, None]], axis=-1)
    
        2
  •  0
  •   Simon    6 年前

    我认为,你的部分困难在于 np.savetxt() 在numpy数组中保存的元组不能很好地工作。我开发了一些测试代码,我认为它们可以复制问题的关键方面,并为它们提供解决方案:

    import numpy as np
    from collections import deque
    
    # Create test data
    center_points = deque(maxlen=64)
    number = deque(maxlen=64)
    for i in range(10):
        big_center = (i*3,i*100)
        center_points.appendleft(big_center)
        number.appendleft(19)
    
    # Write the test data
    
    array_to_save = np.array([center_points,number]).T
    print (array_to_save)
    with open("test.txt","w") as outfile:
        outfile.write("\n".join([" ".join([str(a[0]),str(a[1]),str(b)]) for a,b in
            array_to_save]))
    
    # Re-read the test data
    center_points2 = deque(maxlen=64)
    number2 = deque(maxlen=64)
    
    with open("test.txt","r") as infile:
        for line in infile:
            x = [int(xx) for xx in line.split()]
            center_points2.append((x[0],x[1]))
            number2.append(x[2])
        new_array = np.array([center_points2,number2]).T
    
    print (new_array)
    

    运行时,此代码输出以下内容,显示 array_to_save new_array 已被重新阅读:

    [[(27, 900) 19]
     [(24, 800) 19]
     [(21, 700) 19]
     [(18, 600) 19]
     [(15, 500) 19]
     [(12, 400) 19]
     [(9, 300) 19]
     [(6, 200) 19]
     [(3, 100) 19]
     [(0, 0) 19]]
    [[(27, 900) 19]
     [(24, 800) 19]
     [(21, 700) 19]
     [(18, 600) 19]
     [(15, 500) 19]
     [(12, 400) 19]
     [(9, 300) 19]
     [(6, 200) 19]
     [(3, 100) 19]
     [(0, 0) 19]]
    

    文件 test.txt 如下:

    27 900 19
    24 800 19
    21 700 19
    18 600 19
    15 500 19
    12 400 19
    9 300 19
    6 200 19
    3 100 19
    0 0 19
    

    这个版本中的文件读写代码比仅仅调用 SaveTXT() 但它显式地处理元组。

    更新

    或者,如果您希望在 numpy 数组,可以使用:

    import numpy as np
    from collections import deque
    
    # Create test data
    center_points = deque(maxlen=64)
    number = deque(maxlen=64)
    for i in range(10):
        big_center = (i*3,i*100)
        center_points.appendleft(big_center)
        number.appendleft(19)
    
    print (center_points)
    print (number)
    
    # Write the test data
    
    x, y = zip(*center_points)
    array_to_save = np.array([x,y,number]).T
    print (array_to_save)
    np.savetxt("test.txt", array_to_save, fmt="%d")
    
    # Re-read the test data
    new_array = np.loadtxt("test.txt", dtype=int)
    print (new_array)
    
    center_points2 = deque(zip(new_array.T[0],new_array.T[1]),maxlen=64)
    number2 = deque(new_array.T[2],maxlen=64)
    print (center_points2)
    print (number2)
    

    这使用中描述的方法 Transpose/Unzip Function (inverse of zip)? 将每个元组的两个元素分为两个列表,然后将这些列表包含在 number 单列 麻木的 可以保存的数组 savetxt() 重新装载 loadtxt() .

    这个 print() 调用只是为了说明程序完成时使用的数据与它开始时使用的数据完全相同。它们产生以下输出:

    deque([(27, 900), (24, 800), (21, 700), (18, 600), (15, 500), (12, 400), (9, 300), (6, 200), (3, 100), (0, 0)], maxlen=64)
    deque([19, 19, 19, 19, 19, 19, 19, 19, 19, 19], maxlen=64)
    [[ 27 900  19]
     [ 24 800  19]
     [ 21 700  19]
     [ 18 600  19]
     [ 15 500  19]
     [ 12 400  19]
     [  9 300  19]
     [  6 200  19]
     [  3 100  19]
     [  0   0  19]]
    [[ 27 900  19]
     [ 24 800  19]
     [ 21 700  19]
     [ 18 600  19]
     [ 15 500  19]
     [ 12 400  19]
     [  9 300  19]
     [  6 200  19]
     [  3 100  19]
     [  0   0  19]]
    deque([(27, 900), (24, 800), (21, 700), (18, 600), (15, 500), (12, 400), (9, 300), (6, 200), (3, 100), (0, 0)], maxlen=64)
    deque([19, 19, 19, 19, 19, 19, 19, 19, 19, 19], maxlen=64)