我正在尝试在Python中创建一个嵌套列表,以包含有关视频中点的信息,而且我在创建数组时遇到了很多问题,需要将结果保存到。列表的结构很简单:顶层是对框架的引用,下一层是对标记的引用,最后一层是标记的点。例如,列表设置如下:
markerList # a long list of every marker in every frame
markerList[0] # every marker in the first frame
markerList[0][0] # the first marker of the first frame
markerList[0][0][0] # the x value of the first marker of the first frame
调用markerList [0]如下所示:
array([[ 922.04443359, 903. ],
[ 987.83850098, 891.38830566],
[ 843.27374268, 891.70471191],
[ 936.38446045, 873.34661865],
[ 965.52880859, 840.44445801],
[ 822.19567871, 834.06298828],
[ 903.48956299, 830.62268066],
[ 938.70031738, 825.71557617],
[ 853.09545898, 824.47247314],
[ 817.84277344, 816.05029297],
[ 1057.91186523, 815.52935791],
[ 833.23632812, 787.48504639],
[ 924.24224854, 755.53997803],
[ 836.07800293, 720.02764893],
[ 937.83880615, 714.11199951],
[ 813.3493042 , 720.30566406],
[ 797.09521484, 705.72729492],
[ 964.31713867, 703.246521 ],
[ 934.9864502 , 697.27099609],
[ 815.1550293 , 688.91473389],
[ 954.94085693, 685.88171387],
[ 797.70239258, 672.35119629],
[ 877.05749512, 659.94250488],
[ 962.24786377, 659.26495361],
[ 843.66131592, 618.83868408],
[ 901.50476074, 585.42541504],
[ 863.41851807, 584.4977417 ]], dtype=float32)
问题是每个帧包含不同数量的标记。我想创建一个与markerList相同长度的空数组(即相同数量的帧),其中每个元素的大小与markerList中最大的帧相同。一些重要的警告:首先,我想将结果保存到.mat文件中,最终的数组(我称之为finalStack)是一个单元格的单元格。其次,我需要能够引用并分配给finalStack的任何特定部分。所以,如果我想将一个点移到finalStack [0] [22],我需要能够在没有冲突的情况下这样做。这基本上只意味着我不能在任何地方使用append方法,但它也是我发现的第一个问题 - 找到一种方法来创建finalStack,它不会导致每个新的赋值在整个父列表中重复。我尝试过几种不同的方法,但都没有正常工作。
尝试解决方案:
在另一个SO问题之后,我试图迭代地创建finalStack,但无济于事。我创建了以下函数:
def createFinalStack(numMarkers, numPoints, frames):
step = [[0]*numPoints for x in xrange(numMarkers)]
finalStack = [step]*frames
return finalStack
但是,这会导致所有分配都在父列表中复制,因此分配finalStack[0][12]
会导致finalStack[2][12] == finalStack[20][12] == finalStack[0][12]
。在此示例中,numMarkers = 40,numPoints = 2(仅x& y),帧= 200.(因此最终数组应为200 x 40 x 2。)
那说,这似乎是做我想要的最简单的方法,我只是无法克服复制错误(我知道这是一个参考问题,我只是不知道如何在这种情况下避免它)。
另一个看似简单的解决方案是使用copy.deepcopy(markerList)
复制markerList,并填充少于40个标记的任何帧以使其达到numMarkers = 40,并将其他任何内容归零。但是我无法想出一个好方法来循环遍历所有帧,以正确的格式添加点,然后清空所有其他帧。
如果这不是足够的信息,我可以尝试提供更好的上下文和一些根本不起作用的其他不好的方法。我已经坚持了这么久,以至于我确信解决方案非常简单,我只是错过了显而易见的事情。我希望你能证明我是对的!
谢谢!
答案 0 :(得分:1)
这说明了发生了什么:
In [1334]: step=[[0]*3 for x in range(3)]
In [1335]: step
Out[1335]: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
In [1336]: stack=[step]*4
In [1337]: stack
Out[1337]:
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
In [1338]: stack[0]
Out[1338]: [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
In [1339]: stack[0][2]=3
In [1340]: stack
Out[1340]:
[[[0, 0, 0], [0, 0, 0], 3],
[[0, 0, 0], [0, 0, 0], 3],
[[0, 0, 0], [0, 0, 0], 3],
[[0, 0, 0], [0, 0, 0], 3]]
In [1341]: step
Out[1341]: [[0, 0, 0], [0, 0, 0], 3]
使用alist*n
创建新列表时,新列表包含指向同一基础对象的多个指针。作为一般规则,如果您计划稍后更改值,则使用*n
复制列表会很危险。
如果我做了一个正确尺寸的数组,我没有这个问题:
In [1342]: np.zeros((4,3,3),int)
Out[1342]:
array([[[0, 0, 0],
[0, 0, 0],
[0, 0, 0]],
...
[0, 0, 0]]])
或以列表形式:
In [1343]: np.zeros((4,3,3),int).tolist()
Out[1343]:
[[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
如果我在此列表中指定一个值,我只会更改一个项目:
In [1344]: stack=np.zeros((4,3,3),int).tolist()
In [1345]: stack[0][2]=3
In [1346]: stack
Out[1346]:
[[[0, 0, 0], [0, 0, 0], 3],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]],
[[0, 0, 0], [0, 0, 0], [0, 0, 0]]]
我真的应该使用stack[0][2][1]=3
,但你明白了。如果我以数组形式进行相同的赋值,我最终会改变整行
In [1347]: stack=np.zeros((4,3,3),int)
In [1348]: stack[0][2]=3
In [1349]: stack
Out[1349]:
array([[[0, 0, 0],
[0, 0, 0],
[3, 3, 3]],
[[0, 0, 0],
...
[0, 0, 0]]])
我应该使用像stack[0,2,:]=4
这样的表达式。
可能构建一个像这样的三重下一个列表,其中所有初始值都是独立的。但这种阵列方法更简单。