[英]numpy array is shown incorrect with pyglet
我在使用pyglet顯示numpy數組時遇到問題。 我找到了一個非常相似的主題( 如何顯示帶有pyglet的numpy數組? )。 我想以灰度顯示數組,但是pyglet用顏色顯示它看到圖像: http : //i.stack.imgur.com/pL6Yr.jpg
def create(self, X,Y):
IMG = random((X,Y)) * 255
self.IMG = dstack((IMG,IMG,IMG))
return self.IMG
def image(self):
self.img_data = self.create(X,Y).data.__str__()
self.image = pyglet.image.ImageData(X,Y, 'RGB', self.img_data, pitch = -X*3)
return self.image
如果我保存並加載數組而不是它可以工作(但它會慢得多):
def image(self):
self.im_save=scipy.misc.toimage(self.create(X,Y),cmin=0, cmax=255)
self.im_save.save('outfile.png')
self.image = pyglet.image.load('outfile.png')
return self.image
我得到了我想要的東西:
i.stack.imgur.com/FCY1v.jpg
我在第一個代碼示例中找不到錯誤:(
編輯:
非常感謝你的回答。 有了Bago的提示我得到了這個代碼工作:)確實nfirvine的建議是合理的,因為我只想在灰度顯示矩陣。
def create(self, X,Y):
self.IMG = (random((X,Y)) * 255).astype('uint8')
return self.IMG
def image(self):
self.img_data = self.create(X,Y).data.__str__()
self.image = pyglet.image.ImageData(X,Y, 'L', self.img_data)
return self.image
我花了最后一周玩NumPy來生成隨機紋理。 我遇到了這篇文章並嘗試了接受的答案。
我可以確認之前接受的答案是不正確的 。
這似乎是正確的,因為您使用的是灰度圖像。 但是如果你要使用彩色圖像(例如RGBA)並將GBA通道歸零,你會發現這一點,因為你的紋理中仍然會出現綠色和藍色。
通過使用__str __(),您實際上是在發送垃圾而不是您真正想要的值。
我將使用我的代碼來證明這一點。
import numpy
import pyglet
from pyglet.gl import *
# the size of our texture
dimensions = (16, 16)
# we need RGBA textures
# which has 4 channels
format_size = 4
bytes_per_channel = 1
# populate our array with some random data
data = numpy.random.random_integers(
low = 0,
high = 1,
size = (dimensions[ 0 ] * dimensions[ 1 ], format_size)
)
# convert any 1's to 255
data *= 255
# set the GB channels (from RGBA) to 0
data[ :, 1:-1 ] = 0
# ensure alpha is always 255
data[ :, 3 ] = 255
# we need to flatten the array
data.shape = -1
使用上面的答案,您將執行以下操作
tex_data = data.astype('uint8').__str__()
如果您嘗試使用代碼,您將獲得所有顏色,而不僅僅是紅色!
正確的方法是轉換為ctype GLubytes。
# convert to GLubytes
tex_data = (GLubyte * data.size)( *data.astype('uint8') )
然后,您可以將其傳遞到紋理中。
# create an image
# pitch is 'texture width * number of channels per element * per channel size in bytes'
return pyglet.image.ImageData(
dimensions[ 0 ],
dimensions[ 1 ],
"RGBA",
tex_data,
pitch = dimensions[ 1 ] * format_size * bytes_per_channel
)
我一直在玩這個以獲得一個numpy數組的動態視圖。 @Rebs的答案有效,但當我想在每一幀更新圖像時效率低下。 在分析之后,我發現ctypes值轉換是速率限制步驟,並且可以通過使用ctype類型對象的from_buffer
方法來共享numpy數組和GLubyte數組之間的內存中的基礎位來加速。
這是一個將在2d numpy數組和pyglet圖像之間進行映射的類,使用matplotlib的顏色映射來實現。 如果你有一個numpy數組,在它周圍創建一個ArrayView包裝器,然后在窗口on_draw
方法中更新並blit它:
my_arr = np.random.random((nx, ny))
arr_img = ArrayImage(my_arr)
@window.event
def on_draw():
arr_img.update()
arr_img.image.blit(x, y)
全班實施:
import numpy as np
import matplotlib.cm as cmaps
from matplotlib.colors import Normalize
import pyglet
import pyglet.gl
class ArrayImage:
"""Dynamic pyglet image of a 2d numpy array using matplotlib colormaps."""
def __init__(self, array, cmap=cmaps.viridis, norm=None, rescale=True):
self.array = array
self.cmap = cmap
if norm is None:
norm = Normalize()
self.norm = norm
self.rescale = rescale
self._array_normed = np.zeros(array.shape+(4,), dtype=np.uint8)
# this line below was the bottleneck...
# we have removed it by setting the _tex_data array to share the buffer
# of the normalised data _array_normed
# self._tex_data = (pyglet.gl.GLubyte * self._array_normed_data.size)( *self._array_normed_data )
self._tex_data = (pyglet.gl.GLubyte * self._array_normed.size).from_buffer(self._array_normed)
self._update_array()
format_size = 4
bytes_per_channel = 1
self.pitch = array.shape[1] * format_size * bytes_per_channel
self.image = pyglet.image.ImageData(array.shape[0], array.shape[1], "RGBA", self._tex_data)
self._update_image()
def set_array(self, data):
self.array = data
self.update()
def _update_array(self):
if self.rescale:
self.norm.autoscale(self.array)
self._array_normed[:] = self.cmap(self.norm(self.array), bytes=True)
# don't need the below any more as _tex_data points to _array_normed memory
# self._tex_data[:] = self._array_normed
def _update_image(self):
self.image.set_data("RGBA", self.pitch, self._tex_data)
def update(self):
self._update_array()
self._update_image()
根據pyglet.image
上的Pyglet文檔 ,如果你想要灰度,你應該使用'L'
格式代碼,而不是'RGB'
,因為你只有一個通道。
我認為pyglet期待uint8,你試過嗎?
IMG = ( random((X,Y)) * 255 ).astype('uint8')
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.