利用pygame绘制窗口并获取无人机FPV实时图像呈现的代码如下:
import sys
import time
import airsim
import pygame
import cv2
import numpy as np
# >------>>> pygame settings <<<------< #
pygame.init()
# 创建 pygame 窗口
screen = pygame.display.set_mode((800, 144))
pygame.display.set_caption('screen')
screen.fill((0, 0, 0))
# >------>>> AirSim settings <<<------< #
# 这里改为你要控制的无人机名称(settings文件里面设置的)
vehicle_name = "Drone"
AirSim_client = airsim.MultirotorClient()
AirSim_client.confirmConnection()
AirSim_client.enableApiControl(True, vehicle_name=vehicle_name)
AirSim_client.armDisarm(True, vehicle_name=vehicle_name)
AirSim_client.takeoffAsync(vehicle_name=vehicle_name).join()
# 图像类型字典
image_types = {
"scene": airsim.ImageType.Scene,
"depth": airsim.ImageType.DepthVis,
"seg": airsim.ImageType.Segmentation,
"normals": airsim.ImageType.SurfaceNormals,
"segmentation": airsim.ImageType.Segmentation,
"disparity": airsim.ImageType.DisparityNormalized,
"Infrared": airsim.ImageType.Infrared
}
# 基础的控制速度(m/s)
vehicle_velocity = 2.0
# 设置临时加速比例
speedup_ratio = 10.0
# 用来设置临时加速
speedup_flag = False
# 基础的偏航速率
vehicle_yaw_rate = 5.0
# 主循环
while True:
yaw_rate = 0.0
velocity_x = 0.0
velocity_y = 0.0
velocity_z = 0.0
# 小暂停,避免过度占用CPU
time.sleep(0.02)
# 处理pygame事件
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
# 获取键盘输入状态
scan_wrapper = pygame.key.get_pressed()
# 按下空格键加速10倍
if scan_wrapper[pygame.K_SPACE]:
scale_ratio = speedup_ratio
else:
scale_ratio = 1.0
# 根据 'A' 和 'D' 按键来设置偏航速率变量
if scan_wrapper[pygame.K_a] or scan_wrapper[pygame.K_d]:
yaw_rate = (scan_wrapper[pygame.K_d] - scan_wrapper[pygame.K_a]) * scale_ratio * vehicle_yaw_rate
# 根据 'UP' 和 'DOWN' 按键来设置pitch轴速度变量(NED坐标系,x为机头向前)
if scan_wrapper[pygame.K_UP] or scan_wrapper[pygame.K_DOWN]:
velocity_x = (scan_wrapper[pygame.K_UP] - scan_wrapper[pygame.K_DOWN]) * scale_ratio
# 根据 'LEFT' 和 'RIGHT' 按键来设置roll轴速度变量(NED坐标系,y为正右方)
if scan_wrapper[pygame.K_LEFT] or scan_wrapper[pygame.K_RIGHT]:
velocity_y = -(scan_wrapper[pygame.K_LEFT] - scan_wrapper[pygame.K_RIGHT]) * scale_ratio
# 根据 'W' 和 'S' 按键来设置z轴速度变量(NED坐标系,z轴向上为负)
if scan_wrapper[pygame.K_w] or scan_wrapper[pygame.K_s]:
velocity_z = -(scan_wrapper[pygame.K_w] - scan_wrapper[pygame.K_s]) * scale_ratio
# 设置速度控制以及设置偏航控制
AirSim_client.moveByVelocityBodyFrameAsync(vx=velocity_x, vy=velocity_y, vz=velocity_z, duration=1,
yaw_mode=airsim.YawMode(True, yaw_or_rate=yaw_rate), vehicle_name=vehicle_name)
# 获取场景图像
temp_image1 = AirSim_client.simGetImage('0', image_types["scene"], vehicle_name=vehicle_name)
image1 = cv2.imdecode(airsim.string_to_uint8_array(temp_image1), cv2.IMREAD_COLOR)
cv2.imwrite('screen/visual1.png', image1)
# 显示场景图像
screen_image1 = pygame.image.load("screen/visual1.png")
screen.blit(screen_image1, (0, 0))
pygame.display.flip()
# 获取红外图像
temp_image2 = AirSim_client.simGetImage('0', image_types["Infrared"], vehicle_name=vehicle_name)
image2 = cv2.imdecode(airsim.string_to_uint8_array(temp_image2), cv2.IMREAD_COLOR)
cv2.imwrite('screen/visual2.png', image2)
# 显示红外图像
screen_image2 = pygame.image.load("screen/visual2.png")
screen.blit(screen_image2, (272, 0))
pygame.display.flip()
# 获取分割图像
temp_image3 = AirSim_client.simGetImage('0', image_types["segmentation"], vehicle_name=vehicle_name)
image3 = cv2.imdecode(airsim.string_to_uint8_array(temp_image3), cv2.IMREAD_COLOR)
cv2.imwrite('screen/visual3.png', image3)
# 显示分割图像
screen_image3 = pygame.image.load("screen/visual3.png")
screen.blit(screen_image3, (544, 0))
pygame.display.flip()
# 如果按下 ESC 键退出程序
if scan_wrapper[pygame.K_ESCAPE]:
pygame.quit()
sys.exit()
前面的内容和pygame使用键盘控制无人机一致,大家可以查看之前的博客AirSim 使用Pygame鼠标键盘控制无人机-CSDN博客
主要不同点在这一块,即图像的获取与显示。
# 获取场景图像
temp_image1 = AirSim_client.simGetImage('0', image_types["scene"], vehicle_name=vehicle_name)
image1 = cv2.imdecode(airsim.string_to_uint8_array(temp_image1), cv2.IMREAD_COLOR)
cv2.imwrite('screen/visual1.png', image1)
# 显示场景图像
screen_image1 = pygame.image.load("screen/visual1.png")
screen.blit(screen_image1, (0, 0))
pygame.display.flip()
# 获取红外图像
temp_image2 = AirSim_client.simGetImage('0', image_types["Infrared"], vehicle_name=vehicle_name)
image2 = cv2.imdecode(airsim.string_to_uint8_array(temp_image2), cv2.IMREAD_COLOR)
cv2.imwrite('screen/visual2.png', image2)
# 显示红外图像
screen_image2 = pygame.image.load("screen/visual2.png")
screen.blit(screen_image2, (272, 0))
pygame.display.flip()
# 获取分割图像
temp_image3 = AirSim_client.simGetImage('0', image_types["segmentation"], vehicle_name=vehicle_name)
image3 = cv2.imdecode(airsim.string_to_uint8_array(temp_image3), cv2.IMREAD_COLOR)
cv2.imwrite('screen/visual3.png', image3)
# 显示分割图像
screen_image3 = pygame.image.load("screen/visual3.png")
screen.blit(screen_image3, (544, 0))
pygame.display.flip()
我们通过键盘来移动无人机,不断的用无人机的前摄像头采集图像,再不断的显示。
采集图像与显示我们以场景图为例子:
# 获取场景图像
temp_image1 = AirSim_client.simGetImage('0', image_types["scene"], vehicle_name=vehicle_name)
image1 = cv2.imdecode(airsim.string_to_uint8_array(temp_image1), cv2.IMREAD_COLOR)
cv2.imwrite('screen/visual1.png', image1)
# 显示场景图像
screen_image1 = pygame.image.load("screen/visual1.png")
screen.blit(screen_image1, (0, 0))
pygame.display.flip()
首先调用客户端AirSim_client的成员函数simGetImage来采集图片
temp_image1 = AirSim_client.simGetImage('0', image_types["scene"], vehicle_name=vehicle_name)
传入参数第一个为相机名称,0为前相机
第二个参数是采集图像的类别,我们传入我们之前图像类型字典中的scene的值,即采集airsim.ImageType.Scene类型图像。
第三个参数是无人机的名称。
然后调用cv2的imdecode方法,
image1 = cv2.imdecode(airsim.string_to_uint8_array(temp_image1), cv2.IMREAD_COLOR)
我们之前采集到的是字节流的数据,airsim.string_to_uint8_array(temp_image1) 将从 AirSim 获取的字节流(temp_image1)转换为 NumPy 数组(3通道的图像数组),cv2.IMREAD_COLOR 表示以彩色方式读取图像。
cv2.imwrite('screen/visual1.png', image1)
然后将图像保存到文件中,传入保存路径和三维图像数组。
screen_image1 = pygame.image.load("screen/visual1.png")
然后调用pygame的image.load()方法,加载图像文件,传入我们之前保存的图像路径。
之后显示图像
screen.blit(screen_image1, (0, 0))
pygame.display.flip()
screen.blit(screen_image1, (0, 0)) 将图像 screen_image1 绘制到 pygame 窗口上。(0, 0) 是绘制图像的左上角位置,表示图像会被绘制在窗口的最左上角。
pygame.display.flip() 更新显示的窗口,将图像显示在屏幕上。