关于numpy.array和列表list的区别

2022-09-24 08:07:28

某一天写代码的时候突然遇到一个场景,需要批量对标注信息box进行操作(box包括[x1,y1,x2,y2])。

最简单的操作就是,for循环遍历将box一个一个存到list中最终转化为numpy的二维数组进行操作:

bboxes=[]for kinrange(num_objs):
    ann= anns[k]
    bbox= self._coco_box_to_bbox(ann['bbox'])# 构造array的时候需要 [[]] 二维方式构造
    sbbox= np.array([[bbox[0], bbox[1], bbox[2], bbox[3]]])
    bboxes.append(sbbox)if bboxes!=[]:
    bboxes= np.concatenate(bboxes,0)

需要注意的是我们在构造numpy数组的时候,需要提前把二维这个维度信息告诉np.array:

>>>import numpyas np>>> a= np.array([1,2,3,4])>>> b=[]>>> b.append(a)>>> b.append(a)>>> b[array([1,2,3,4]), array([1,2,3,4])]>>> c= np.concatenate(b)>>> c
array([1,2,3,4,1,2,3,4])>>> c.shape# 此时concat后的c还是一维的(8,)# 这样>>> a= np.array([[1,2,3,4]])# 需要提前指明2维>>> b=[]>>> b.append(a)>>> b.append(a)>>> b[array([[1,2,3,4]]), array([[1,2,3,4]])]>>> c= np.concatenate(b)>>> c
array([[1,2,3,4],[1,2,3,4]])>>> c.shape# 此时concat后的维度才是2维(2,4)

np.concatenate后bboxes的维度是(N,5),此时可以通过这种方式去批量处理x1,y1,x2,y2

offset_x=1
offset_y=2
bboxes[:,0]= bboxes[:,0]+ offset_x
bboxes[:,1]= bboxes[:,1]+ offset_y
bboxes[:,2]= bboxes[:,2]+ offset_x
bboxes[:,3]= bboxes[:,3]+ offset_y

numpy的array可以这样操作,但是对于list来说是不行的:

>>> a=[[1,2,3],[4,5,6]]>>> a[0]#取第一行是可以的[1,2,3]>>> a[:,0]#尝试用数组索引方式失败
TypeError:list indices must be integersor slices,nottuple

这是因为python中的list和numpy中的array是完全不一样的两个东西,list可以存放不同类型的数据,比如int、float和str,甚至布尔型;而一个numpy数组中存放的数据类型必须全部相同,例如int或float。

在list中的数据类型保存的是数据的存放的地址,即指针而非数据(底层是C语言,这样想想也很正常),例如a=[1,2,3,4]需要4个指针和四个数据,增加了存储和消耗cpu,而a=np.array([1,2,3,4])只需要存放四个数据,读取和计算更加方便。

所以列表List可以存放不同类型的数据,因此列表中每个元素的大小可以相同,也可以不同,所以也就不支持一次性读取一列。即使是对于标准的二维数字列表([[1,2,3,4]]这种),所以纯数字的我们最好都使用numpy的数据类型去操作。

如果你与我志同道合于此,很愿意与你交流
如果你喜欢我的内容,欢迎关注和支持
微信公众号 : oldpan博客
丢给你一个神秘链接:oldpan.me


  • 作者:老潘的博客
  • 原文链接:https://oldpan.blog.csdn.net/article/details/112756717
    更新时间:2022-09-24 08:07:28