first of all, I'm totally new to kivy, so I'm struggling a bit.
首先,我对kivy完全不熟悉,所以我有点挣扎。
I'm trying to display a numpy array in a kivy window. So far i figured out that this should work using the Texture Class (http://kivy.org/docs/api-kivy.graphics.texture.html).
我正试图在kivy窗口中显示一个numpy数组。到目前为止,我发现这应该使用Texture Class(http://kivy.org/docs/api-kivy.graphics.texture.html)。
As my numpy array changes from time to time, I'm trying to adjust the following code to my application.
由于我的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))
It seems that creating the texture and changing it works as it should, but i dont get, how to display the texture.
似乎创建纹理并改变它的工作原理应该如此,但我不知道,如何显示纹理。
Can anybody explain to me, how to use the
任何人都可以向我解释,如何使用
with self.canvas:
Rectangle(texture=texture, pos=self.pos, size=(64, 64))
in a way, that I get to see my picture/numpy array.
在某种程度上,我可以看到我的图片/ numpy数组。
Thanks alot in advance! Holzroller
非常感谢! Holzroller
Edit: I figured out that using Kivy 1.8.0 and the Texture Class is a bit messy. So I upgraded to Kivy 1.9.0 via github (installing Kivy via apt-get in Ubuntu 14.04 LTS serves you the 1.8.0 version) and I get to see the Texture using the following code. I hope that helps people who are having the same problem as me.
编辑:我发现使用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: Basically I'm back to the original Problem: I have a numpy array (type 'numpy.ndarray'; dtype 'uint8') and I'm trying to convert it into a format, so that the texture will show me the image. I tried to break it down to the same way it is done in the example code i posted above. But i sadly doesn't work. I really do not know what I'm doing wrong here. (my numpy array is called im2 in the folling code)
编辑2:基本上我回到原来的问题:我有一个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 个解决方案
#1
5
Numpy have a tostring()
attribute, that you could use directly, if the source array is uint8 type. You don't even need to reshape:
Numpy有一个tostring()属性,如果源数组是uint8类型,你可以直接使用它。你甚至不需要重塑:
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"
About the issue you're talking in the comment, i see 2 points:
关于你在评论中谈到的问题,我看到2点:
- Ensure the callback from the ROS is called in the mainthread. Maybe the update is simply ignored.
- When you manually change inplace the texture, the associated object that use it are not notified, you need to do it. Add a self.canvas.ask_update() to ensure the canvas redisplay at the next frame.
确保在mainthread中调用ROS的回调。也许简单地忽略了更新。
手动更改纹理时,不会通知使用它的关联对象,您需要这样做。添加一个self.canvas.ask_update()以确保画布在下一帧重新显示。
#1
5
Numpy have a tostring()
attribute, that you could use directly, if the source array is uint8 type. You don't even need to reshape:
Numpy有一个tostring()属性,如果源数组是uint8类型,你可以直接使用它。你甚至不需要重塑:
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"
About the issue you're talking in the comment, i see 2 points:
关于你在评论中谈到的问题,我看到2点:
- Ensure the callback from the ROS is called in the mainthread. Maybe the update is simply ignored.
- When you manually change inplace the texture, the associated object that use it are not notified, you need to do it. Add a self.canvas.ask_update() to ensure the canvas redisplay at the next frame.
确保在mainthread中调用ROS的回调。也许简单地忽略了更新。
手动更改纹理时,不会通知使用它的关联对象,您需要这样做。添加一个self.canvas.ask_update()以确保画布在下一帧重新显示。