2014-11-26 19 views
6

trước hết, tôi hoàn toàn mới với kivy, vì vậy tôi đang đấu tranh một chút.Hiển thị một mảng tối đa ở Kivy

Tôi đang cố gắng hiển thị mảng có nhiều mảng trong cửa sổ kivy. Cho đến nay tôi đã tìm ra rằng điều này sẽ làm việc bằng cách sử dụng lớp Texture (http://kivy.org/docs/api-kivy.graphics.texture.html).

Vì mảng numpy của tôi thay đổi theo thời gian, tôi đang cố điều chỉnh mã sau đây cho ứng dụng của mình.

# 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)) 

Dường như việc tạo ra các kết cấu và thay đổi nó hoạt động như mong muốn, nhưng tôi không nhận được, làm thế nào để hiển thị các kết cấu.

Ai có thể giải thích cho tôi, làm thế nào để sử dụng

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

theo một cách, mà tôi có thể nhìn thấy hình ảnh/mảng NumPy tôi.

Cảm ơn rất nhiều trước! Holzroller

Chỉnh sửa: Tôi đã tìm ra rằng việc sử dụng Kivy 1.8.0 và Lớp kết cấu hơi lộn xộn một chút. Vì vậy, tôi nâng cấp lên Kivy 1.9.0 thông qua github (cài đặt Kivy qua apt-get trong Ubuntu 14.04 LTS phục vụ bạn phiên bản 1.8.0) và tôi có thể thấy Texture bằng cách sử dụng đoạn mã sau. Tôi hy vọng rằng sẽ giúp những người có cùng một vấn đề như tôi.

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: Về cơ bản tôi trở lại vấn đề ban đầu: Tôi có một mảng NumPy (gõ 'numpy.ndarray'; dtype 'uint8') và tôi đang cố gắng để chuyển đổi nó thành một định dạng, để kết cấu sẽ hiển thị cho tôi hình ảnh. Tôi đã cố gắng để phá vỡ nó xuống theo cùng một cách nó được thực hiện trong mã ví dụ tôi được đăng ở trên. Nhưng tôi buồn bã không làm việc. Tôi thực sự không biết mình đang làm gì sai ở đây. (mảng NumPy tôi được gọi là im2 trong mã folling)

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

arr = array('B', list1) 

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

Trả lời

5

NumPy có một thuộc tính tostring(), mà bạn có thể sử dụng trực tiếp, nếu mảng nguồn là kiểu uint8. Bạn thậm chí không cần phải định hình lại:

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" 

Về vấn đề bạn đang nói chuyện trong các bình luận, tôi thấy 2 điểm:

  1. Đảm bảo gọi lại từ ROS được gọi trong mainthread. Có lẽ bản cập nhật chỉ đơn giản là bị bỏ qua.
  2. Khi bạn thay đổi thủ công tại chỗ kết cấu, đối tượng liên quan sử dụng nó sẽ không được thông báo, bạn cần làm điều đó. Thêm self.canvas.ask_update() để đảm bảo canvas sẽ hiển thị lại ở khung tiếp theo.
+0

anks, tôi đã thử bevor đó. Có lẽ lỗi của tôi là cập nhật mảng đó. Vì vậy, tôi sẽ cố gắng giải thích toàn bộ ứng dụng của tôi. Tôi nhận được một hình ảnh thông qua một nút ROS. Tôi sẽ đưa hình ảnh đó trở lại định dạng rgb im2 = CvBridge(). Imgmsg_to_cv2 (dữ liệu, "rgb8") vì vậy tôi về cơ bản trở lại một mảng có nhiều mảng. Người đăng ký ROS có chức năng gọi lại nơi kết cấu được thay đổi. Nhưng tôi không thể thấy sự thay đổi này. Có thể nó trở nên rõ ràng hơn khi bạn xem: (https://gist.github.com/Holzroller/1ec092ce798afd9c8b34) – Holzroller

+0

đến 1.Tôi không nghĩ rằng bản cập nhật bị bỏ qua, vì lý do đó tôi đã thêm một số chức năng in để xem liệu cuộc gọi lại có được thực hiện hay không. Hơn nữa tôi đã có thể xuất hình ảnh tôi đã nhận thông qua ROS trong một JPEG bằng cách sử dụng OpenCV. để 2. Tôi thêm self.canvas.ask_update() trong mỗi chức năng, nhưng thật đáng buồn Tôi không có thể nhìn thấy hình ảnh :( Anyways, cảm ơn bạn rất nhiều vì đã hỗ trợ của bạn https:.! // ý chính .github.com/Holzroller/2f7f95b0958d6e406667 – Holzroller

+1

Không bỏ qua trong python, bỏ qua trong GL vì bạn không phải là trong chủ đề chính/opengl.Nhưng bình thường nếu bạn không, nó bị rơi.Tôi vẫn không hiểu làm thế nào opencv/ros gọi callback mà không cần beeing trong mainthread – tito

Các vấn đề liên quan