Mapping a numpy array in Kivy

First of all, I'm completely new to kivy, so I'm struggling a bit.

I am trying to display a numpy array in a kivy window. So far, I realized that this should work using the Texture class ( http://kivy.org/docs/api-kivy.graphics.texture.html ).

As my numpy array changes from time to time, I'm trying to set up the following code for my application.

# 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 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 don't get how to display the texture.

Can someone explain me how to use

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

in a way, what I get to see my / numpy image array.

Thanks in advance! Holzroller

Edit: I realized that using Kivy 1.8.0 and Texture Class is a bit messy. So I upgraded to Kivy 1.9.0 via github (installing Kivy via apt-get on Ubuntu 14.04 LTS serves you version 1.8.0), and I can see Texture using the following code. Hope this helps people who have the same problem as me.

 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 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 returned to the original problem: I have a numpy array (type 'numpy.ndarray'; dtype 'uint8') and I'm trying to convert it to a format so that the texture will show me the image. I tried to break it in the same way as in the above code example. But I, unfortunately, do not work. I really don't know what I'm doing wrong here. (my numpy matrix is ​​called im2 in the folling code)

 list1 = numpy.array(im2).reshape(-1,).tolist() arr = array('B', list1) texture.blit_buffer(arr, colorfmt='rgb', bufferfmt='ubyte') 
+6
source share
1 answer

Numpy has a tostring() attribute, which can be used directly if the source array is of type uint8. You do not even need to change the form:

 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 problem that you are talking about in the comment, I see 2 points:

  • Make sure the callback from ROS is called in mainthread. Perhaps the update is simply ignored.
  • When you manually change the texture in place, the object associated with it is not notified, you need to do this. Add self.canvas.ask_update () to ensure that the canvas appears again in the next frame.
+5
source

Source: https://habr.com/ru/post/978740/


All Articles