【问题标题】:Save deque into csv data frame将双端队列保存到 csv 数据框中
【发布时间】:2019-01-14 00:02:22
【问题描述】:

我正在使用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.appendnp.stack,但找不到正确的数据格式化方式。

否则,我可以保持代码不变,但我想以某种方式摆脱第 1 列和第 2 列上的括号并保存该对象(已在 array_to_save 上尝试过正则表达式但没有成功)。所有三列都应该是数字或保存为字符串,但在以后阅读时很容易检索为数字。

更新

基于我尝试过的 cmets

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

【问题讨论】:

  • 您可以使用np.concatenate(x, y[:, None]),即添加额外的列维度以具有(64, 2)(64, 1),然后您可以连接。
  • @a_guest 这不起作用我运行正确吗? array_to_save = np.concatenate(np.array(center_points), object_number[:, None]) TypeError: sequence index must be integer, not 'tuple'
  • 您需要将参数包含在一个额外的序列中,即np.concatenate([np.array(center_points), object_number[:, None]])
  • @a_guest 请查看更新。
  • 看来object_number 没有center_points 那么多项目。无论如何,一般规则是沿着公共轴,在我们的例子中这是0-th 轴,要连接的两个数组需要具有相同的长度。您可以通过.shape查看每个维度的长度。 IE。执行c = np.array(center_points); o = np.array(object_number)[:, None],然后检查c.shapeo.shape。由于shape[0] 是公共轴,因此它必须是相同的编号。例如c.shape == (60, 2); o.shape == (60, 1) 可以,c.shape == (60, 2); o.shape == (58, 1) 不行。

标签: python regex deque saving-data


【解决方案1】:

您可以concatenate 沿列维度的数组,以便从(X, 2)(X,) 数组中创建(X, 3) 数组。为了准备好连接,所有数组都需要具有相同的维数,因此您需要向平面数组 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】:

    我认为,您的部分困难在于 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
    

    这个版本的文件读写代码比仅仅调用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)
    
    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 列表一起包含在单个numpy 数组中,该数组可以用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)
    

    【讨论】:

    • 这个解决方案可能会起作用,尽管我更喜欢在保存之前处理数据,并有办法处理进入 np.array 的元组,在它们连接之前或之后转换它们。有什么想法吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-20
    • 2021-05-16
    • 2018-07-02
    • 2018-09-11
    • 2020-06-15
    • 2019-03-06
    • 1970-01-01
    相关资源
    最近更新 更多