【问题标题】:Display a numpy array in Kivy在 Kivy 中显示一个 numpy 数组
【发布时间】:2015-01-25 00:39:36
【问题描述】:

首先,我对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 和纹理类有点乱。所以我通过 github 升级到 Kivy 1.9.0(在 Ubuntu 14.04 LTS 中通过 apt-get 安装 Kivy 为您提供 1.8.0 版本),我可以使用以下代码查看纹理。希望对和我有同样问题的人有所帮助。

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)

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

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

arr = array('B', list1)

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

【问题讨论】:

    标签: arrays numpy textures kivy


    【解决方案1】:

    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"
    

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

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

    【讨论】:

    • anks,我试过了。也许我的错在于更新该数组。因此,我将尝试解释我的整个应用程序。我通过 ROS 节点获取图像。我将该图像恢复为 rgb 格式 im2 = CvBridge().imgmsg_to_cv2(data, "rgb8") 所以我基本上回到了一个 numpy 数组。 ROS 订阅者有一个回调函数,其中纹理被更改。但我看不到这种变化。看一下可能会更清楚:(gist.github.com/Holzroller/1ec092ce798afd9c8b34)
    • to 1. 我不认为更新被忽略了,因此我添加了一些打印函数来查看回调是否被执行。此外,我还能够使用 OpenCV 将通过 ROS 获得的图像导出为 JPEG 格式。到 2. 我在每个函数中都添加了 self.canvas.ask_update(),但遗憾的是我没有看到图像 :(。无论如何,非常感谢您的支持!gist.github.com/Holzroller/2f7f95b0958d6e406667
    • 在 python 中不被忽略,在 GL 中被忽略,因为您不在 opengl/主线程中。但通常如果你不这样做,它就会崩溃。我仍然不明白 opencv/ros 如何在没有在主线程中运行的情况下调用回调。
    • 尝试用@mainthread(来自kivy.clock)或Clock.schedule_once装饰方法,当从ROS调用回调时更新(主线程为你做)。
    • 对不起,我不能真正理解...你所说的“主线程”是什么意思? ROS 回调是否应该在 MyApp 类中并从那里调用 Screen(widget) 类?
    猜你喜欢
    • 2015-10-05
    • 2012-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    • 2017-12-27
    • 2016-07-30
    • 1970-01-01
    相关资源
    最近更新 更多