Python中将PIL图像转换为numpy数组非常缓慢

6
我正在评估一个Tensorflow模型,并使用open cv视频帧进行测试。我需要将传入的PIL图像重塑为numpy数组,以便可以对其进行推理。 但是我发现,在我的笔记本电脑上,使用16 GiB内存和2.6 GHz英特尔Core i7处理器将PIL图像转换为numpy数组需要大约900毫秒以上。我需要将此时间缩短到几毫秒,这样我才能在我的相机上每秒处理多个帧。
有谁能建议如何使下面的方法运行更快?
def load_image_into_numpy_array(pil_image):
    (im_width, im_height) = pil_image.size
    data = pil_image.getdata()

    data_array = np.array(data)

    return data_array.reshape((im_height, im_width, 3)).astype(np.uint8)

经过进一步测试,我意识到np.array(data)所占用的时间最长…接近于900毫秒。因此,将图像数据转换为numpy数组是真正的罪魁祸首。


你在哪个步骤中获取了PIL图像? - unlut
我之前获取了PIL图像并将其传递给这个函数。 - Pratik Khadloya
图片有多大? - Warren Weckesser
(720, 1280, 3) - Pratik Khadloya
2个回答

9
您可以直接让numpy处理转换,而不是自己进行重塑。
def pil_image_to_numpy_array(pil_image):
    return np.asarray(pil_image)  

你正在将图像转换为(高度,宽度,通道)格式。这是numpy.asarray函数在PIL图像上默认执行的转换,因此不需要进行显式的重塑。

感谢您提供的解决方案。需要进行重塑以便我可以获得正确形状的图像进行推理...请查看 https://github.com/tensorflow/models/blob/master/research/object_detection/object_detection_tutorial.ipynb 中的 load_image_into_numpy_array 方法。 - Pratik Khadloya
我不确定为什么需要显式转换,因为你已经将图像转换为(高度、宽度、通道)格式。当你使用默认的numpy方法将PIL图像转换为numpy数组时,你已经得到了(高度、宽度、通道)格式的numpy数组。如果我漏掉了什么,请见谅。 - unlut
哦,好的...谢谢你提供的信息。我只是在跟随tensorflow的做法...顺便说一下,np.asarray(pil_image)非常快...只需要1毫秒... - Pratik Khadloya
有趣的是,当我打印pil_image.size时,我得到了(1280, 720),但当我打印np.asarray(pil_image).size时,我得到了(720, 1280, 3)。我想知道是否反转了高度和宽度,这可能会导致不正确的结果。 - Pratik Khadloya
2
PIL使用(宽度,高度)顺序https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#attributes,而numpy使用(高度,宽度)如此处所述https://dev59.com/M1gQ5IYBdhLWcg3wIAWb。 - unlut
比我之前做的任何事情都快50倍! - legel

0
非常感谢!它运行得非常快!
def load_image_into_numpy_array(path):
    """Load an image from file into a numpy array.

    Puts image into numpy array to feed into tensorflow graph.
    Note that by convention we put it into a numpy array with shape
    (height, width, channels), where channels=3 for RGB.

    Args:
    path: a file path (this can be local or on colossus)

    Returns:
    uint8 numpy array with shape (img_height, img_width, 3)
    """
    img_data = tf.io.gfile.GFile(path, 'rb').read()
    image = Image.open(BytesIO(img_data))

    return np.array(image)

尺寸为(3684, 4912, 3)的图像需要0.3~0.4秒。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接