在Kivy中显示一个numpy数组

时间:2014-11-26 15:46:42

标签: arrays numpy textures kivy

首先,我对kivy完全不熟悉,所以我有点挣扎。

我正试图在kivy窗口中显示一个numpy数组。 到目前为止,我发现这应该使用Texture Class(http://kivy.org/docs/api-kivy.graphics.texture.html)。

由于我的numpy数组不时更改,我正在尝试将以下代码调整到我的应用程序。

# create a 64x64 texture, defaults to rgb / ubyte
texture = Texture.create(size=(64, 64))

# create 64x64 rgb tab, and fill with values from 0 to 255
# we'll have a gradient from black to white
size = 64 * 64 * 3
buf = [int(x * 255 / size) for x in range(size)]

# then, convert the array to a ubyte string
buf = b''.join(map(chr, buf))

# then blit the buffer
texture.blit_buffer(buf, colorfmt='rgb', bufferfmt='ubyte')

# that's all ! you can use it in your graphics now :)
# if self is a widget, you can do this
with self.canvas:
    Rectangle(texture=texture, pos=self.pos, size=(64, 64))

似乎创建纹理并更改它的工作原理应该如此,但我不知道,如何显示纹理。

有人可以向我解释,如何使用

with self.canvas:
    Rectangle(texture=texture, pos=self.pos, size=(64, 64))

在某种程度上,我可以看到我的图片/ numpy数组。

提前多多谢谢! Holzroller

编辑: 我发现使用Kivy 1.8.0和Texture Class有点乱。所以我通过github升级到Kivy 1.9.0(在Ubuntu 14.04中通过apt-get安装Kivy LTS为你提供1.8.0版本)我可以使用以下代码看到Texture。我希望能帮助那些和我有同样问题的人。

from kivy.graphics.texture import Texture
from kivy.graphics import Rectangle
from kivy.uix.widget import Widget
from kivy.base import runTouchApp
from array import array
from kivy.core.window import Window


# create a 64x64 texture, defaults to rgb / ubyte
texture = Texture.create(size=(1280, 1024), colorfmt='rgb')

# create 64x64 rgb tab, and fill with values from 0 to 255
# we'll have a gradient from black to white
size = 1280 * 1024 * 3
buf = [int(x * 255 / size) for x in range(size)]

# then, convert the array to a ubyte string
arr = array('B', buf)
# buf = b''.join(map(chr, buf))

# then blit the buffer
texture.blit_buffer(arr, colorfmt='rgb', bufferfmt='ubyte')

# that's all ! you can use it in your graphics now :)
# if self is a widget, you can do this
root = Widget()
with root.canvas:
    Rectangle(texture=texture, pos=(0, 0), size=(1280*3, 1024*3))

runTouchApp(root)

EDIT2: 基本上我回到原来的问题: 我有一个numpy数组(类型'numpy.ndarray'; dtype'int8'),我正在尝试将其转换为格式,以便纹理将显示我的图像。我试图将其分解为与我在上面发布的示例代码中完成的方式相同。但我遗憾地不起作用。我真的不知道我在这里做错了什么。 (我的numpy数组在后续代码中称为im2)

list1 = numpy.array(im2).reshape(-1,).tolist()

arr = array('B', list1)

texture.blit_buffer(arr, colorfmt='rgb', bufferfmt='ubyte')

1 个答案:

答案 0 :(得分:5)

如果源数组是uint8类型,Numpy有一个tostring()属性,可以直接使用。你甚至不需要重塑:

texture = Texture.create(size=(16, 16), colorfmt="rgb"))
arr = numpy.ndarray(shape=[16, 16, 3], dtype=numpy.uint8)
# fill your numpy array here
data = arr.tostring()
texture.blit_buffer(data, bufferfmt="ubyte", colorfmt="rgb"

关于你在评论中谈论的问题,我看到2分:

  1. 确保在主线程中调用ROS的回调。可能只是忽略了更新。
  2. 当您手动更改纹理时,不会通知使用它的关联对象,您需要这样做。添加一个self.canvas.ask_update()以确保画布在下一帧重新显示。