1 用到的函数
python
# initialize env
env = gym.make()
frame = env.render()
frame = np.transpose(frame, (1, 0, 2)) # 调整图像方向
frame = pygame.surfarray.make_surface(frame)
screen.blit(frame, (0, 0))
pygame.display.flip()
1.1 检查图像的形状
首先,我们需要确认从 env.render()
返回的图像的形状。通常情况下,rgb_array
模式返回的图像形状是 (height, width, channels)
,其中 channels
通常是 3(RGB)。
python
import gym
import numpy as np
env = gym.make('Pendulum-v1',render_mode="rgb_array")
env.reset()
# 获取一帧图像
frame = env.render()
print(f"Frame shape: {frame.shape}")
env.close()
1.2 根据图像形状调整
假设 frame.shape
输出的结果是 (height, width, 3)
,那么我们不需要调整图像方向。如果确实需要调整图像方向,可以根据实际情况调整 np.transpose
的参数。
例如,如果你需要将图像的宽度和高度对调,可以使用以下代码:
python
frame = np.transpose(frame, (1, 0, 2)) # 将宽度和高度对调
但如果 frame.shape
是 (height, width, 3)
,那么直接使用 frame
即可,无需调整。
1.3 代码解读
首先,需要确保您已经导入了 pygame
,并正确地初始化了 pygame
显示窗口。
python
import pygame
import numpy as np
# 初始化 pygame
pygame.init()
# 假设您的环境分辨率为 800x600
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))
# 训练或测试中的代码部分,处理帧显示
for episode in range(test_episodes):
state = env.reset()
done = False
while not done:
# 渲染环境并获取帧
frame = env.render(mode='rgb_array') # 使用 'rgb_array' 模式来获取帧
frame = np.transpose(frame, (1, 0, 2)) # 转置 frame,使得宽度和高度与显示的顺序一致
# 将 numpy 数组转换为 pygame.Surface
frame_surface = pygame.surfarray.make_surface(frame)
# 显示帧
screen.blit(frame_surface, (0, 0))
pygame.display.flip()
# 智能体选择动作
action = agent.select_action(state)
# 执行动作
next_state, reward, done, _ = env.step(action)
state = next_state
# 结束后保持一段时间
pygame.time.wait(500)
# 关闭 pygame 和环境
pygame.quit()
env.close()
代码详细说明
-
获取环境渲染帧:
frame = env.render()
:使用'rgb_array'
模式从环境中获取帧,这样返回的是一个numpy
数组,形状为(height, width, channels)
,通常是 RGB 三通道图像。
-
转换 numpy 数组为 Pygame Surface:
- 使用
pygame.surfarray.make_surface(frame)
将numpy.ndarray
转换为pygame.Surface
。 pygame.surfarray.make_surface()
只能处理二维数组的转置形式,因此如果渲染出来的帧的维度是(height, width, channels)
,您可能需要调整顺序(例如使用np.transpose(frame, (1, 0, 2))
),以便适应make_surface
的输入要求。
- 使用
-
显示帧:
screen.blit(frame_surface, (0, 0))
:将转换后的Surface
对象绘制到屏幕上。pygame.display.flip()
刷新显示以确保更新的帧在屏幕上显示。
-
初始化 Pygame:
- 使用
pygame.init()
进行初始化,并使用pygame.display.set_mode()
来创建显示窗口。
- 使用
-
延迟以查看效果:
- 使用
pygame.time.wait(500)
保持画面以便观察智能体的效果。
- 使用
注意
- 问题来源 :
env.render()
返回的是numpy.ndarray
,而pygame
的blit()
方法需要一个Surface
对象。 - 解决方法 :使用
pygame.surfarray.make_surface()
将numpy.ndarray
转换为pygame.Surface
,这样就可以正确地显示在屏幕上。
这样就能将 OpenAI Gym 环境的帧显示到 Pygame 窗口中,并使用智能体执行的动作来实时观察它在环境中的行为。
2 完整示例代码
以下是一个完整的示例代码,展示了如何在 PyGame 中显示 Gym 环境的渲染结果,并控制帧率:
python
import gym
import pygame
import numpy as np
import time
pygame.init()
screen_width, screen_height = 800, 600
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('CartPole-v1')
env = gym.make('CartPole-v1',render_mode="rgb_array")
env.reset()
# 获取一帧图像,检查形状
frame = env.render()
print(f"Frame shape: {frame.shape}")
for _ in range(100):
frame = env.render() # 获取图像帧
# 检查并调整图像方向(如果需要)
if frame.shape[0] > frame.shape[1]:
frame = np.transpose(frame, (1, 0, 2)) # 将宽度和高度对调
# 将图像转换为 PyGame 表面
frame = pygame.surfarray.make_surface(frame)
frame_surface = pygame.transform.scale(frame, (screen_width, screen_height))
screen.blit(frame_surface, (0, 0))
pygame.display.flip()
# 控制帧率
time.sleep(0.05)
for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
quit()
action = env.action_space.sample()
_, _, done, _, _ = env.step(action)
if done:
break
env.close()
pygame.quit()
解释
- 初始化 PyGame:设置 PyGame 环境,创建一个窗口。
- 创建 Gym 环境 :加载
CartPole-v1
环境并重置。 - 检查图像形状:获取一帧图像并打印其形状,确保你知道图像的尺寸。
- 调整图像方向 :根据需要调整图像的方向。如果
frame.shape
是(height, width, 3)
,则不需要调整。 - 显示图像:将图像转换为 PyGame 表面并显示在窗口中。
- 控制帧率 :使用
time.sleep
控制每帧图像的显示时间。 - 处理事件:处理 PyGame 事件,如窗口关闭。
- 执行动作:随机选择一个动作并执行。
- 关闭环境:关闭 Gym 环境和 PyGame 窗口。
结果