numpy数组的对象列表

Posted

技术标签:

【中文标题】numpy数组的对象列表【英文标题】:List of objects to numpy array 【发布时间】:2015-05-05 21:49:21 【问题描述】:

对于我的一个图像处理项目,我需要使用关键点。为了计算它们,我发现 OpenCV 使用起来非常快速和方便。但是,当使用例如 FAST 算法计算图像的关键点时,我们会收到一个 KeyPoint objects 数组。

当我得到这些关键点时,我只想获取它们的坐标,而不是附加信息(角度等)。这些坐标将用于使用 numpy 进行多次计算。问题是从 KeyPoint 数组到 numpy 数组的转换时间。它大约需要总执行时间的 60%。有什么建议可以改善下面的循环吗?

import cv2
import numpy as np

image_cv2 = cv2.imread("sample.jpg")
fast = cv2.FastFeatureDetector(threshold=25)
keypoints = fast.detect(image_cv2)

n = len(keypoints)
cd_x = np.zeros(n, dtype=np.int)
cd_y = np.zeros(n, dtype=np.int)
for i in xrange(0, n):
    cd_x[i] = keypoints[i].pt[0]
    cd_y[i] = keypoints[i].pt[1]

PS:我尝试使用 np.vectorize 但没有发现任何改进。作为信息,按图像的关键点数量通常在 5 000 左右。

更新: 正如一些人指出的那样,从关键点到 numpy 数组的简单分配应该非常快。经过一些测试,确实非常快。比如一个275张图片的数据集,1个线程,完整的执行时间是22.9s,keypoints->numpy的执行时间只有0.2s,而cv2.imread()用了20s左右。

我的错误是同时使用了太多线程,因为每个内核至少没有使用 80%,我不断增加它们的数量直到这个任意限制,这减慢了循环执行。谢谢大家让我看到代码中其他地方的愚蠢错误!

【问题讨论】:

keypoints 是对象列表,还是带有dtype=objectnumpy 数组? vectorize 是什么意思?使用np.vectorize 函数,还是别的什么? 有时理解更快:cd_x=np.array([k.pt[0] for k in keypoints]) @hpaulj keypoints 是对象列表,而不是 numpy 数组。我已经更新了标题和正文,我在谈论 np.vectorize 因为我不知道如何在 python 中真正矢量化。 当你说它需要 60% 的执行时间时,我们说的是秒还是分钟?从 5000 个对象中取出 2 个整数并将它们粘贴到 numpy 数组中肯定不会花费太长时间,并且会随着更多对象线性缩放。 np.vectorize 只是在你的函数周围包裹了一个循环。这是一个方便的工具,而不是加速代码的方法。 【参考方案1】:

一个审判案例:

In [765]: class Keypoints(object):
    def __init__(self):
        self.pt=[1.,2.]
   .....:         
In [766]: keypoints=[Keypoints() for i in xrange(1000)]
In [767]: cd=np.array([k.pt for k in keypoints])
In [768]: cd
Out[768]: 
array([[ 1.,  2.],
       [ 1.,  2.],
       [ 1.,  2.],
       ..., 
       [ 1.,  2.],
       [ 1.,  2.],
       [ 1.,  2.]])
In [769]: cd_x=cd[:,0]

在 timeit 测试中,keypoints 步骤所用的时间与 cd 计算的时间一样长,1 毫秒。

但是两个更简单的迭代

cd_x=np.array([k.pt[0] for k in keypoints])
cd_y=np.array([k.pt[1] for k in keypoints])

需要一半的时间。我期待单次迭代可以节省时间。但是在这些简单的情况下,推导本身只需要一半的时间,剩下的就是创建数组。

In [789]: timeit [k.pt[0] for k in keypoints]
10000 loops, best of 3: 136 us per loop
In [790]: timeit np.array([k.pt[0] for k in keypoints])
1000 loops, best of 3: 282 us per loop

【讨论】:

我刚刚编辑了我的帖子,你是对的!现在瓶颈是cv2.imread(),但我没有真正希望减少它(使用标志 cv2.IMREAD_GRAYSCALE 加载速度快 2 倍,但仅此而已)。感谢您的帮助。

以上是关于numpy数组的对象列表的主要内容,如果未能解决你的问题,请参考以下文章

TensorFlow ValueError:无法将 NumPy 数组转换为张量(不支持的对象类型列表)

Keras:ValueError:无法将 NumPy 数组转换为张量(不支持的对象类型列表)

AttributeError:“列表”对象没有属性“numpy”

Numpy - 数组array的构造

Numpy的那些事儿

NumPy简介