GUI系统¶
Taichi具有内置的GUI系统,可帮助用户可视化结果。
创建一个窗口¶
-
ti.
GUI
(title, res, bgcolor = 0x000000)¶ 参数: - title – (字符串)窗口标题
- res – (标量或元组)分辨率/窗口大小
- bgcolor – (可选,RGB十六进制)窗口的背景颜色
返回: (GUI)对象代表窗口
创建一个窗口。 如果
res
是标量,则宽度将等于高度。以下代码创建了一个分辨率为
640x360
的窗口:gui = ti.GUI('Window Title', (640, 360))
-
gui.
show
(filename = None)¶ 参数: - gui – (GUI)窗口对象
- filename – (可选,字符串)请参阅以下注释
在屏幕上显示窗口。
注解
如果指定了
文件名
,则屏幕截图将被保存到该名称指定的文件中。 例如,以下将窗口的框架保存到.png
文件中:for frame in range(10000): render(img) gui.set_image(img) gui.show(f'{frame:06d}.png')
在窗口上作画¶
-
gui.
set_image
(img)¶ 参数: - gui – (GUI)窗口对象
- img – (numpy 数组或 Taichi 张量)包含图像的张量,请参见下面的注释
设置要在窗口上显示的图像。
图像像素由
img[i, j]
的值设定,其中i
表示水平坐标(从左到右),j
表示垂直坐标(从下到上) 。如果窗口大小是
(x, y)
,则img
必须是以下之一:ti.var(shape=(x, y))
,灰度图像ti.var(shape=(x, y, 3))
,其中 3 代表(r, g, b)
通道ti.Vector(3, shape=(x, y))
(参见 向量)np.ndarray(shape=(x, y))
np.ndarray(shape=(x, y, 3))
img
的数据类型必须是以下之一:uint8
,范围[0, 255]
uint16
,范围[0, 65535]
uint32
,范围[0, 4294967295]
float32
,范围[0, 1]
float64
,范围[0, 1]
注解
When using
float32
orfloat64
as the data type,img
entries will be clipped into range[0, 1]
for display.
-
gui.
circle
(pos, color = 0xFFFFFF, radius = 1)¶ 参数: - gui – (GUI)窗口对象
- pos – (2元组)圆的位置
- color – (可选,RGB十六进制)颜色填充圆圈
- radius – (可选,标量)圆的半径
画一个实心圆。
-
gui.
circles
(pos, color = 0xFFFFFF, radius = 1)¶ 参数: - gui – (GUI)窗口对象
- pos – (numpy 数组)一系列圆的位置
- color – (可选,RGB十六进制或 uint32 的 numpy 数组)颜色以填充圆圈
- radius – (可选,float32的标量或np.array)圆的半径(半径)
画多个实心圆。
注解
如果 color
是一个 numpy 数组,则位于 pos[i]
的圆圈将使用 color[i]
作为颜色,因此 color
的数组长度必须与 pos
相同。
-
gui.
line
(begin, end, color = 0xFFFFFF, radius = 1)¶ 参数: - gui – (GUI)窗口对象
- begin – (2元组)直线的第一个端点位置
- end – (2元组)直线的第二个端点位置
- color – (可选,RGB十六进制)线条颜色
- radius – (可选,标量)线的宽度
画一条线。
-
gui.
lines
(begin, end, color = 0xFFFFFF, radius = 1)¶ 参数: - gui – (GUI)窗口对象
- begin – (np.array) the positions of the first end point of lines
- end – (np.array) the positions of the second end point of lines
- color – (optional, RGB hex or np.array of uint32) the color(s) of lines
- radius – (optional, scalar or np.array of float32) the width(s) of the lines
Draw lines.
-
gui.
triangle
(a, b, c, color = 0xFFFFFF)¶ 参数: - gui – (GUI)窗口对象
- a – (2元组)三角形的第一个端点位置
- b – (2元组)三角形的第二个端点位置
- c – (2元组)三角形的第三个端点位置
- color – (可选,RGB十六进制)填充三角形的颜色
画一个实心三角形。
-
gui.
triangles
(a, b, c, color = 0xFFFFFF)¶ 参数: - gui – (GUI)窗口对象
- a – (np.array) the positions of the first end point of triangles
- b – (np.array) the positions of the second end point of triangles
- c – (np.array) the positions of the third end point of triangles
- color – (optional, RGB hex or np.array of uint32) the color(s) to fill the triangles
Draw solid triangles.
-
gui.
rect
(topleft, bottomright, radius = 1, color = 0xFFFFFF)¶ 参数: - gui – (GUI)窗口对象
- topleft – (2元组)矩形的左上角位置
- bottomright – (2元组)矩形的右下角位置
- color – (可选,RGB十六进制)描边线的颜色
- radius – (可选,标量)描边线的宽度
画一个空心的矩形。
-
gui.
text
(content, pos, font_size = 15, color = 0xFFFFFF)¶ 参数: - gui – (GUI)窗口对象
- content – (str) the text to draw
- pos – (tuple of 2) the top-left point position of the fonts / texts
- font_size – (optional, scalar) the size of font (in height)
- color – (optional, RGB hex) the foreground color of text
Draw a line of text on screen.
-
ti.rgb_to_hex(rgb):
参数: rgb – (tuple of 3 floats) The (R, G, B) float values, in range [0, 1] 返回: (RGB hex or np.array of uint32) The converted hex value Convert a (R, G, B) tuple of floats into a single integer value. E.g.,
rgb = (0.4, 0.8, 1.0) hex = ti.rgb_to_hex(rgb) # 0x66ccff rgb = np.array([[0.4, 0.8, 1.0], [0.0, 0.5, 1.0]]) hex = ti.rgb_to_hex(rgb) # np.array([0x66ccff, 0x007fff])
The return values can be used in GUI drawing APIs.
事件处理¶
Every event have a key and type.
type
是事件的类型,目前只有三种类型的事件:
ti.GUI.RELEASE # key up or mouse button up
ti.GUI.PRESS # key down or mouse button down
ti.GUI.MOTION # mouse motion or mouse wheel
Event key is the key that you pressed on keyboard or mouse, can be one of:
# for ti.GUI.PRESS and ti.GUI.RELEASE event:
ti.GUI.ESCAPE # Esc
ti.GUI.SHIFT # Shift
ti.GUI.LEFT # Left Arrow
'a' # we use lowercase for alphabet
'b'
...
ti.GUI.LMB # Left Mouse Button
ti.GUI.RMB # Right Mouse Button
# for ti.GUI.MOTION event:
ti.GUI.MOVE # Mouse Moved
ti.GUI.WHEEL # Mouse Wheel Scrolling
事件过滤器 是一个由 key
,type
和 (type, key)
元组组成的列表,例如:
# 如果按下或释放ESC:
gui.get_event(ti.GUI.ESCAPE)
# 如果按下任何键:
gui.get_event(ti.GUI.PRESS)
# 如果按ESC或释放SPACE:
gui.get_event((ti.GUI.PRESS, ti.GUI.ESCAPE), (ti.GUI.RELEASE, ti.GUI.SPACE))
-
gui.
running
¶ 参数: gui – (GUI) 返回: (bool) True
ifti.GUI.EXIT
event occurred, vice versati.GUI.EXIT
occurs when you click on the close (X) button of a window. Sogui.running
will obtainFalse
when the GUI is being closed.For example, loop until the close button is clicked:
while gui.running: render() gui.set_image(pixels) gui.show()
You can also close the window by manually setting
gui.running
toFalse
:while gui.running: if gui.get_event(ti.GUI.ESCAPE): gui.running = False render() gui.set_image(pixels) gui.show()
-
gui.
get_event
(a, ...)¶ 参数: - gui – (GUI)
- a – (可选,事件过滤器)过滤掉匹配的事件
返回: (bool) 如果没有待处理的事件,返回
False
,反之亦然尝试从队列中弹出事件,并将其存储在
gui.event
中。例如:
if gui.get_event(): print('Got event, key =', gui.event.key)
例如,循环直到按下ESC:
gui = ti.GUI('Title', (640, 480)) while not gui.get_event(ti.GUI.ESCAPE): gui.set_image(img) gui.show()
-
gui.
get_events
(a, ...)¶ 参数: - gui – (GUI)
- a – (可选,事件过滤器)过滤掉匹配的事件
返回: (生成器)python生成器,请参见下文
基本上与
gui.get_event
相同,只不过它返回一个事件生成器,而不是存储到gui.event
中:for e in gui.get_events(): if e.key == ti.GUI.ESCAPE: exit() elif e.key == ti.GUI.SPACE: do_something() elif e.key in ['a', ti.GUI.LEFT]: ...
-
gui.
is_pressed
(key, ...)¶ 参数: - gui – (GUI)
- key – (事件的 key) 您要检测的键
返回: (bool) 其中一个键处于按下状态,返回
True
,反之亦然警告
必须与
gui.get_event
一起使用,否则将不会更新! 例如:while True: gui.get_event() # must be called before is_pressed if gui.is_pressed('a', ti.GUI.LEFT): print('Go left!') elif gui.is_pressed('d', ti.GUI.RIGHT): print('Go right!')
-
gui.
get_cursor_pos
()¶ 参数: gui – (GUI) 返回: (2元组)窗口中的当前光标位置 例如:
mouse_x, mouse_y = gui.get_cursor_pos()
GUI Widgets¶
Sometimes it’s more intuitive to use widgets like slider, button to control program variables instead of chaotic keyboard bindings. Taichi GUI provides a set of widgets that hopefully could make variable control more intuitive:
-
gui.
slider
(text, minimum, maximum, step=1)¶ 参数: - text – (str) the text to be displayed above this slider.
- minumum – (float) the minimum value of the slider value.
- maxumum – (float) the maximum value of the slider value.
- step – (optional, float) the step between two separate value.
返回: (WidgetValue) a value getter / setter, see
WidgetValue
.The widget will be display as:
{text}: {value:.3f}
, followed with a slider.
-
gui.
label
(text)¶ 参数: text – (str) the text to be displayed in the label. 返回: (WidgetValue) a value getter / setter, see WidgetValue
.The widget will be display as:
{text}: {value:.3f}
.
参数: - text – (str) the text to be displayed in the button.
- event_name – (optional, str) customize the event name.
返回: (EventKey) the event key for this button, see Event processing.
图片输入/输出¶
-
gui.
get_image
()¶ 返回: a np.ndarray
which is the current image shown on the GUI.Get the RGBA shown image from the current GUI system which has four channels.
-
ti.
imwrite
(img, filename)¶ 参数: - img – (Matrix or Expr) the image you want to export
- filename – (string) the location you want to save to
Export a
np.ndarray
or Taichi tensor (ti.Matrix
,ti.Vector
, orti.var
) to a specified locationfilename
.Same as
ti.GUI.show(filename)
, the format of the exported image is determined by the suffix offilename
as well. Nowti.imwrite
supports exporting images topng
,img
andjpg
and we recommend usingpng
.Please make sure that the input image has a valid shape. If you want to export a grayscale image, the input shape of tensor should be
(height, weight)
or(height, weight, 1)
. For example:import taichi as ti ti.init() shape = (512, 512) type = ti.u8 pixels = ti.var(dt=type, shape=shape) @ti.kernel def draw(): for i, j in pixels: pixels[i, j] = ti.random() * 255 # integars between [0, 255] for ti.u8 draw() ti.imwrite(pixels, f"export_u8.png")
Besides, for RGB or RGBA images,
ti.imwrite
needs to receive a tensor which has shape(height, width, 3)
and(height, width, 4)
individually.Generally the value of the pixels on each channel of a
png
image is an integar in [0, 255]. For this reason,ti.imwrite
will cast tensors which has different datatypes all into integars between [0, 255]. As a result,ti.imwrite
has the following requirements for different datatypes of input tensors:- For float-type (
ti.f16
,ti.f32
, etc) input tensors, the value of each pixel should be float between [0.0, 1.0]. Otherwiseti.imwrite
will first clip them into [0.0, 1.0]. Then they are multiplied by 256 and casted to integaters ranging from [0, 255]. - For int-type (
ti.u8
,ti.u16
, etc) input tensors, the value of each pixel can be any valid integer in its own bounds. These integers in this tensor will be scaled to [0, 255] by being divided over the upper bound of its basic type accordingly.
Here is another example:
import taichi as ti ti.init() shape = (512, 512) channels = 3 type = ti.f32 pixels = ti.Matrix(channels, dt=type, shape=shape) @ti.kernel def draw(): for i, j in pixels: for k in ti.static(range(channels)): pixels[i, j][k] = ti.random() # floats between [0, 1] for ti.f32 draw() ti.imwrite(pixels, f"export_f32.png")
-
ti.
imread
(filename, channels=0)¶ 参数: - filename – (string) the filename of the image to load
- channels – (optional int) the number of channels in your specified image. The default value
0
means the channels of the returned image is adaptive to the image file
返回: (np.ndarray) the image read from
filename
This function loads an image from the target filename and returns it as a
np.ndarray(dtype=np.uint8)
.Each value in this returned tensor is an integer in [0, 255].
-
ti.
imshow
(img, windname)¶ 参数: - img – (Matrix or Expr) the image to show in the GUI
- windname – (string) the name of the GUI window
This function will create an instance of
ti.GUI
and show the input image on the screen.It has the same logic as
ti.imwrite
for different datatypes.