参考网址:https://microsoft.github.io/AirSim/image_apis/#segmentation
使用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
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
首先获取无压缩的图像,并按如下方式转成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)
可用的ImageType
如上所述,一共有8种,分别是:
Scene = 0,
DepthPlanner = 1,
DepthPerspective = 2,
DepthVis = 3,
DisparityNormalized = 4,
Segmentation = 5,
SurfaceNormals = 6,
Infrared = 7
下面分别介绍其含义。
通常设置pixels_as_float = true
以及ImageType = DepthPlanner
或 ImageType = DepthPerspective
来得到浮点数的深度图像。根据官方文档的介绍,这两种深度图像似乎是计算景深的方式不一样,DepthPlanner
似乎是以摄像机所在平面为基准来计算景深的,而DepthPerspective
似乎是以摄像机镜头(一个点)为基准来计算景深的。但是我对计算成像学的了解太过浅薄,具体含义请参见https://microsoft.github.io/AirSim/image_apis/#depthplanner-and-depthperspective。
使用ImageType=DepthVis
表示:输出的景深图像的每一个像素值都表示该像素点距离摄像机所处平面的距离,单位是米。即,越白表示距离越远,纯白表示100m或100m开外;越黑表示距离越近,纯黑表示距离0m。
通常可以采用pixels_as_float = true
以及ImageType = DisparityNormalized
的设置来得到归一化的浮点数图像,也就是每个像素取值为 [ 0 , 1 ] [0,1] [0,1]。归一化公式(Xl - Xr)/Xmax
,不过没看懂。
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
在目前,所谓的红外线图像,只是将ObjectID映射到[0,255]
的像素值,例如,ObjectID=42,则该像素点被映射为(42,42,42)
。 有关如何设置ObjectID的更多详细信息,请参见Segmentation部分。 通常可以添加噪声应用于此图像类型,以获得稍微更逼真的效果。 AirSim团队仍在开发其他红外伪像的图像功能,所以该图像类型还不太完善。
通过不同的名字可以选择不同方位的摄像机摄取图像。如front_center
,front_right
,front_left
,bottom_center
,back_center
。也可以用0
,1
,2
,3
,4
来代替上述字符串。
在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)
同样是修改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/。