在Kivy中显示一个numpy数组

时间:2021-03-14 18:18:23

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点:

  1. Ensure the callback from the ROS is called in the mainthread. Maybe the update is simply ignored.
  2. 确保在mainthread中调用ROS的回调。也许简单地忽略了更新。

  3. 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.
  4. 手动更改纹理时,不会通知使用它的关联对象,您需要这样做。添加一个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点:

  1. Ensure the callback from the ROS is called in the mainthread. Maybe the update is simply ignored.
  2. 确保在mainthread中调用ROS的回调。也许简单地忽略了更新。

  3. 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.
  4. 手动更改纹理时,不会通知使用它的关联对象,您需要这样做。添加一个self.canvas.ask_update()以确保画布在下一帧重新显示。