强化学习系列文章(二十三):AirSim Python API图像与图像处理

强化学习系列文章(二十三):AirSim Python API图像与图像处理

参考网址:https://microsoft.github.io/AirSim/image_apis/#segmentation

1.simGetImage函数

使用0号相机得到单张图像。返回值是PNG格式的图像。

import airsim #pip install airsim

# for car use CarClient() 
client = airsim.MultirotorClient()

png_image = client.simGetImage("0", airsim.ImageType.Scene)
# do something with image

2.simGetImages函数

simGetImages函数提供了更多可能性,如选择不同相机位置,得到不同类型图像等等,例如单通道的浮点数图像或者三通道的uint8图像。

import airsim #pip install airsim

# for car use CarClient() 
client = airsim.MultirotorClient()

responses = client.simGetImages([
    # png format
    airsim.ImageRequest(0, airsim.ImageType.Scene),  # 相机名称,图像类型,是否浮点数,是否压缩图像(默认压缩)
    # uncompressed RGB array bytes
    airsim.ImageRequest(1, airsim.ImageType.Scene, False, False),
    # floating point uncompressed image
    airsim.ImageRequest(1, airsim.ImageType.DepthPlanner, True)])

# do something with response which contains image data, pose, timestamp etc

ImageRequest函数源代码:

class ImageRequest(MsgpackMixin):
    camera_name = '0'
    image_type = ImageType.Scene
    pixels_as_float = False
    compress = False

    def __init__(self, camera_name, image_type, pixels_as_float = False, compress = True):
        # todo: in future remove str(), it's only for compatibility to pre v1.2
        self.camera_name = str(camera_name)
        self.image_type = image_type
        self.pixels_as_float = pixels_as_float
        self.compress = compress

常用的ImageType有:

airsim.ImageType.Scene                # = 0 最普通的场景,主界面的图像
airsim.ImageType.DepthPlanner         # = 1 
airsim.ImageType.DepthPerspective     # = 2
airsim.ImageType.DepthVis             # = 3 景深图像
airsim.ImageType.DisparityNormalized  # = 4
airsim.ImageType.Segmentation         # = 5 目标分割图像
airsim.ImageType.SurfaceNormals       # = 6
airsim.ImageType.Infrared             # = 7

3.AirSim图像转Numpy格式

首先获取无压缩的图像,并按如下方式转成Numpy:

responses = client.simGetImages([airsim.ImageRequest("0", airsim.ImageType.Scene, False, False)]) # 第2个False表示不压缩
response = responses[0]

# get numpy array
img1d = np.fromstring(response.image_data_uint8, dtype=np.uint8) 

# reshape array to 4 channel image array H X W X 4
img_rgb = img1d.reshape(response.height, response.width, 3)

# original image is fliped vertically
img_rgb = np.flipud(img_rgb)

# write to png 
airsim.write_png(os.path.normpath(filename + '.png'), img_rgb) 

4.不同ImageType之含义

可用的ImageType如上所述,一共有8种,分别是:

Scene = 0, 
DepthPlanner = 1, 
DepthPerspective = 2,
DepthVis = 3, 
DisparityNormalized = 4,
Segmentation = 5,
SurfaceNormals = 6,
Infrared = 7

下面分别介绍其含义。

4.1 DepthPlanner & DepthPerspective

通常设置pixels_as_float = true 以及ImageType = DepthPlannerImageType = DepthPerspective 来得到浮点数的深度图像。根据官方文档的介绍,这两种深度图像似乎是计算景深的方式不一样,DepthPlanner似乎是以摄像机所在平面为基准来计算景深的,而DepthPerspective似乎是以摄像机镜头(一个点)为基准来计算景深的。但是我对计算成像学的了解太过浅薄,具体含义请参见https://microsoft.github.io/AirSim/image_apis/#depthplanner-and-depthperspective。

4.2 DepthVis

使用ImageType=DepthVis表示:输出的景深图像的每一个像素值都表示该像素点距离摄像机所处平面的距离,单位是米。即,越白表示距离越远,纯白表示100m或100m开外;越黑表示距离越近,纯黑表示距离0m。

4.3 DisparityNormalized

通常可以采用pixels_as_float = true 以及ImageType = DisparityNormalized的设置来得到归一化的浮点数图像,也就是每个像素取值为 [ 0 , 1 ] [0,1] [0,1]。归一化公式(Xl - Xr)/Xmax,不过没看懂。

4.4 Segmentation

ImageType = Segmentation可以得到对当前场景进行真实分割的图像。AirSim通过为场景中的每一个格点(Mesh)赋以[0,255]的值来实现分割功能。每一个值都对应一个RGB颜色,对照表参见https://microsoft.github.io/AirSim/seg_rgbs.txt。

另外还可以用如下代码修改某个格点对应的ObjectID号:

success = client.simSetSegmentationObjectID("Ground", 20);

获取目标分割图像的推荐代码如下,注意不要压缩图像,即ImageRequest的第二个False

responses = client.simGetImages([ImageRequest(0, AirSimImageType.Segmentation, False, False)])
img1d = np.fromstring(response.image_data_uint8, dtype=np.uint8) #get numpy array
img_rgb = img1d.reshape(response.height, response.width, 3) #reshape array to 3 channel image array H X W X 3
img_rgb = np.flipud(img_rgb) #original image is fliped vertically

#find unique colors
print(np.unique(img_rgb[:,:,0], return_counts=True)) #red
print(np.unique(img_rgb[:,:,1], return_counts=True)) #green
print(np.unique(img_rgb[:,:,2], return_counts=True)) #blue  

4.5 Infrared(红外图像)

在目前,所谓的红外线图像,只是将ObjectID映射到[0,255]的像素值,例如,ObjectID=42,则该像素点被映射为(42,42,42)。 有关如何设置ObjectID的更多详细信息,请参见Segmentation部分。 通常可以添加噪声应用于此图像类型,以获得稍微更逼真的效果。 AirSim团队仍在开发其他红外伪像的图像功能,所以该图像类型还不太完善。

5.选择摄像机

通过不同的名字可以选择不同方位的摄像机摄取图像。如front_centerfront_rightfront_leftbottom_centerback_center。也可以用01234来代替上述字符串。

6.“计算机视觉”模式

在AirSim中可以使用所谓的“计算机视觉”模式,也就是关闭物理引擎,关闭载具,只保留摄像机,可以使用方向键控制摄像机来回移动,并保存图像。在我的Ubuntu18.04操作系统中,在/home/xxx/Documents/AirSim/settings.json中,添加:

{
  "SettingsVersion": 1.2,
  "SimMode": "ComputerVision"
}

就可以打开“计算机视觉“模式,下面是一份操作”计算机视觉“模式的示例代码。

import setup_path
import airsim

import pprint
import os
import time
import math
import tempfile

pp = pprint.PrettyPrinter(indent=4)

client = airsim.VehicleClient()
client.confirmConnection()

airsim.wait_key('Press any key to set camera-0 gimbal to 15-degree pitch')
camera_pose = airsim.Pose(airsim.Vector3r(0, 0, 0), airsim.to_quaternion(math.radians(15), 0, 0)) #radians
client.simSetCameraPose("0", camera_pose)

airsim.wait_key('Press any key to get camera parameters')
for camera_name in range(5):
    camera_info = client.simGetCameraInfo(str(camera_name))
    print("CameraInfo %d:" % camera_name)
    pp.pprint(camera_info)

# 创建保存图像的文件夹
tmp_dir = os.path.join(tempfile.gettempdir(), "airsim_cv_mode")
print ("Saving images to %s" % tmp_dir)
try:
    os.makedirs(tmp_dir)
except OSError:
    if not os.path.isdir(tmp_dir):
        raise

airsim.wait_key('Press any key to get images')
for x in range(3): # do few times
    z = x * -20 - 5 # some random number
    client.simSetVehiclePose(airsim.Pose(airsim.Vector3r(z, z, z), airsim.to_quaternion(x / 3.0, 0, x / 3.0)), True)

    responses = client.simGetImages([
        airsim.ImageRequest("0", airsim.ImageType.DepthVis),
        airsim.ImageRequest("1", airsim.ImageType.DepthPerspective, True),
        airsim.ImageRequest("2", airsim.ImageType.Segmentation),
        airsim.ImageRequest("3", airsim.ImageType.Scene),
        airsim.ImageRequest("4", airsim.ImageType.DisparityNormalized),
        airsim.ImageRequest("4", airsim.ImageType.SurfaceNormals)])

    for i, response in enumerate(responses):
        filename = os.path.join(tmp_dir, str(x) + "_" + str(i))
        if response.pixels_as_float:
            print("Type %d, size %d, pos %s" % (response.image_type, len(response.image_data_float), pprint.pformat(response.camera_position)))
            airsim.write_pfm(os.path.normpath(filename + '.pfm'), airsim.get_pfm_array(response))
        else:
            print("Type %d, size %d, pos %s" % (response.image_type, len(response.image_data_uint8), pprint.pformat(response.camera_position)))
            airsim.write_file(os.path.normpath(filename + '.png'), response.image_data_uint8)

    pose = client.simGetVehiclePose()
    pp.pprint(pose)

    time.sleep(3)

# currently reset() doesn't work in CV mode. Below is the workaround
client.simSetVehiclePose(airsim.Pose(airsim.Vector3r(0, 0, 0), airsim.to_quaternion(0, 0, 0)), True)

7.设置摄像机参数和图像参数

同样是修改settings.json文件,可以修改AirSim摄像机保存图像的尺寸等参数。示例如下:

{
  "SettingsVersion": 1.2,
  "CameraDefaults": {
      "CaptureSettings": [
        {
          "ImageType": 0,
          "Width": 256,
          "Height": 144,
          "FOV_Degrees": 90,
          "AutoExposureSpeed": 100,
          "MotionBlurAmount": 0
        }
    ]
  },
  "SimMode": "ComputerVision"
}

settings.json可以控制的参数非常之多,具体请参见https://microsoft.github.io/AirSim/settings/。

你可能感兴趣的:(强化学习,自动驾驶,AirSim)