Carla自动驾驶仿真六:pygame多个车辆摄像头画面拼接

此文章主要介绍carla前后左右摄像头画面拼接到pygame上


前言

1、使用carla做仿真测试或者开发时,如果能够将车辆周边的画面拼接并渲染,可以直观地查看周围地环境,便于调试。本文将介绍使用carla中的camera传感器监控自车周边的画面,并通过pygame可视化。

一、要点分析

1、如果摄像头的横向分辨率image_x如果不为192的倍数,可能会导致内存对齐问题,拼接效果则会出现闪屏;调试了很久才发现这个规律,知道具体原因的大佬可以交流下,猜测是显卡解析相关导致。即:Image_x = 192 * N (N为正整数),下图为分辨率不为192倍数的拼接情况。

在这里插入图片描述

2、camera.listen(lambda data : callback(data)),listen方法是carla中用于设置摄像头传感器的回调函数的。当摄像头传感器捕获到新的图像数据image时,它会调用这个回调函数,并将图像数据image作为参数传递给它。下图中的cala.SensorData就是carla.Image,具体更多内容可以到carla官网查看。

在这里插入图片描述
在这里插入图片描述

3、使用np.concatenate拼接不同摄像头的数据。
1)numpy.concatenate是一个用于将多个数组沿指定轴连接在一起的函数。它的基本语法如下:

numpy.concatenate((a1, a2, ...), axis=0)

2)其中,a1, a2, …是你想要连接的数组,axis参数指定了连接的轴。默认情况下,axis是0,这意味着数组将在垂直方向上(即行方向)连接,当axis=1时,数组将在水平方向上(即列方向)连接。

import numpy as np

a = np.array([1, 2])
b = np.array([3, 4])
c = np.concatenate((a, b), axis=0)

print(c)  # 输出:[1 2 3 4]

==============================

a1 = np.array([[1, 2], [3, 4]])
a2 = np.array([[5, 6], [7, 8]])

c = np.concatenate((a1, a2), axis=1)

print(c)
#输出
[[1 2 5 6]
 [3 4 7 8]]

二、完整代码

import carla
import random
import pygame
import numpy as np

# 渲染对象来保持和传递 PyGame 表面
class RenderObject(object):
    def __init__(self, width, height):
        init_image = np.random.randint(0, 255, (height, width, 3), dtype='uint8')
        self.surface = pygame.surfarray.make_surface(init_image.swapaxes(0, 1))

# 相机传感器回调,将相机的原始数据重塑为 2D RGB,并应用于 PyGame 表面
def pygame_callback(image, side):
    img = np.reshape(np.copy(image.raw_data), (image.height, image.width, 4))
    img = img[:, :, :3]
    img = img[:, :, ::-1]
    if side == 'Front':
        global Front
        Front = img
    elif side == 'Rear':
        global Rear
        Rear = img
    elif side == 'Left':
        global Left
        Left = img
    elif side == 'Right':
        global Right
        Right = img

    if ('Front' in globals() and 'Rear' in globals()
        and "Left" in globals()and 'Right' in globals()):
        # 横向拼接(前后)(左右)摄像头的画面
        img_combined_front = np.concatenate((Front, Rear), axis=1)
        img_combined_rear = np.concatenate((Left, Right), axis=1)
        # 纵向拼接(前后)(左右)摄像头的画面
        img_combined = np.concatenate((img_combined_front, img_combined_rear), axis=0)
        renderObject.surface = pygame.surfarray.make_surface(img_combined.swapaxes(0, 1))

class cameraManage():
    def __init__(self, world, ego_vehicle, pygame_size):
        self.world = world
        self.cameras = {}
        self.ego_vehicle = ego_vehicle
        self.image_size_x = int(pygame_size.get("image_x") / 2)  # 横向放置两个摄像头的画面
        self.image_size_y = int(pygame_size.get("image_y") / 2)  # 纵向放置两个摄像头的画面

    def camaraGenarate(self):
        cameras_transform = [
            (carla.Transform(carla.Location(x=2.0, y=0.0, z=1.3),  # 前侧摄像头安装位置
                             carla.Rotation(pitch=0, yaw=0, roll=0)), "Front"),
            (carla.Transform(carla.Location(x=-2.0, y=0.0, z=1.3),  # 后侧摄像头安装位置
                             carla.Rotation(pitch=0, yaw=180, roll=0)), "Rear"),
            (carla.Transform(carla.Location(x=0.0, y=2.0, z=1.3),  # 左侧摄像头安装位置
                             carla.Rotation(pitch=0, yaw=90, roll=0)), "Left"),
            (carla.Transform(carla.Location(x=0.0, y=-2.0, z=1.3),  # 右侧的摄像头安装位置
                             carla.Rotation(pitch=0, yaw=-90, roll=0)), "Right")
        ]
        # 查找RGB相机蓝图
        camera_bp = self.world.get_blueprint_library().find('sensor.camera.rgb')
        # 设置摄像头的fov为90°
        camera_bp.set_attribute('fov', "90")
        # 设置摄像头的分辨率
        camera_bp.set_attribute('image_size_x', str(self.image_size_x))
        camera_bp.set_attribute('image_size_y', str(self.image_size_y))
        # 生成摄像头
        for index, (camera_ts, camera_sd) in enumerate(cameras_transform):
            camera = self.world.spawn_actor(camera_bp, camera_ts, attach_to=self.ego_vehicle)
            self.cameras[camera_sd] = camera
        return self.cameras


if __name__ == "__main__":
    # 连接到客户端并检索世界对象
    client = carla.Client('localhost', 2000)
    world = client.get_world()

    # 获取地图的刷出点
    spawn_point = random.choice(world.get_map().get_spawn_points())

    # 生成车辆并设置自动驾驶
    vehicle_bp = world.get_blueprint_library().filter('*vehicle*').filter('vehicle.tesla.*')[0]
    ego_vehicle = world.spawn_actor(vehicle_bp, spawn_point)
    # ego_vehicle.set_autopilot(True)

    #设置pygame窗口size,image_x为192的整数倍,用其他分辨率会闪屏,可能是显卡解析原因导致。
    pygame_size = {
        "image_x": 1152,
        "image_y": 600
    }

    #调用cameraManage类,生成摄像头
    cameras = cameraManage(world, ego_vehicle, pygame_size).camaraGenarate()

    #采集carla世界中camera的图像
    cameras.get("Front").listen(lambda image: pygame_callback(image, 'Front'))
    cameras.get("Rear").listen(lambda image: pygame_callback(image, 'Rear'))
    cameras.get("Left").listen(lambda image: pygame_callback(image, 'Left'))
    cameras.get("Right").listen(lambda image: pygame_callback(image, 'Right'))

    # 为渲染实例化对象
    renderObject = RenderObject(pygame_size.get("image_x"), pygame_size.get("image_y"))

    # 初始化pygame显示
    pygame.init()
    gameDisplay = pygame.display.set_mode((pygame_size.get("image_x"), pygame_size.get("image_y")),
                                          pygame.HWSURFACE | pygame.DOUBLEBUF)
    # 循环执行
    crashed = False
    while not crashed:
        # 等待同步
        world.tick()

        # 按帧更新渲染的 Camera 画面
        gameDisplay.blit(renderObject.surface, (0, 0))
        pygame.display.flip()

        # 获取 pygame 事件
        for event in pygame.event.get():
            # If the window is closed, break the while loop
            if event.type == pygame.QUIT:
                crashed = True

    # 结束
    ego_vehicle.destroy()
    camera = cameras.values()
    for cam in camera:
        cam.stop
    pygame.quit()

三、拼接效果

在这里插入图片描述


四、总结

欢迎各位大佬来交流,特别是为什么只支持192倍数的分辨率设置,还是说我的方法不严谨,欢迎交流。

  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
在视频监控应用中,如何有效实现宽视场范围视频的完整获取,是视频监控系统的关键功能之一。本文针对多摄像头硬件平台,重点研究 360 度全景视频拼接的实现技术。在保证高质量的拼接图像的前提下,满足实际应用场景的实时性要求是本文算法设计的主要目标。针对全景拼接在视频监控领域这一应用背景,本文对多摄像头系统全景拼接存在的一些优势和约束进行详细分析,并在此基础上,采用多个广角镜头进行视频图像采集,实现摄像头个数和单个镜头视角之间的合理折中。在控制成本的前提下,有效实现水平方向 360 度无盲区监控。 针对全景视频拼接算法的实时性能和拼接效果,本文重点在以下几个方面开展了研究工作: 1、本文采用普通的监控 CCD 单板机和广角镜头组装摄像单元,对多个摄像单元通道采用多线程同步视频采集。针对普通监控镜头采集图像质量不高的问题,提出基于颜色校正板的颜色校正方法,对输入图像进行预处理,有效改善图像质量。并采用基于灰度均值的方法,对相邻图像的重叠区域进行亮度调整。 2、本文基于经典的直线标定法思想,提出两步法镜头矫正方案。通过所提出的直线标定法对镜头进行一次矫正,然后通过手动设置并调节畸变参数,对矫正后的图像进行二次矫正,所提出的算法能保证良好的镜头矫正效果。 3、研究了柱面投影模型的原理,提出将柱面映射的投影中心修正为镜头畸变中心,克服了由于畸变和透视失真等因素造成的重叠区物体成像尺寸不一致的问题。然后,利用所提出的坐标映射表的方式,一次性实现镜头畸变矫正和柱面映射,有效提高了算法执行速度。 4、分析了基于 Harris 特征和 SIFT 特征的配准算法原理。SIFT 特征配准算法鲁棒性高,但难以满足硬件系统的实时性要求;基于 Harris 特征的配准算法复杂度低,但难以应对广角镜头畸变引起的图像质量差的问题,匹配性能较差。最后采用了基于积分图像的快速归一化互相关配准方案,实验验证了算法的可行性和有效性。 5、此外,在图像融合方面,基于经典的多频带融合算法,结合线性融合的思想,优化了一种简单的多分辨率线性融合方法。在保证融合质量的基础上,提升了速度。 关键字:多镜头多传感器;图像配准;全景拼接;实时监控;广角镜头
压缩包中包含的具体内容: 对给定数据中的6个不同场景图像,进行全景图拼接操作,具体要求如下: (1) 寻找关键点,获取关键点的位置和尺度信息(DoG检测子已由KeypointDetect文件夹中的detect_features_DoG.m文件实现;请参照该算子,自行编写程序实现Harris-Laplacian检测子)。 (2) 在每一幅图像中,对每个关键点提取待拼接图像的SIFT描述子(编辑SIFTDescriptor.m文件实现该操作,运行EvaluateSIFTDescriptor.m文件检查实现结果)。 (3) 比较来自两幅不同图像的SIFT描述子,寻找匹配关键点(编辑SIFTSimpleMatcher.m文件计算两幅图像SIFT描述子间的Euclidean距离,实现该操作,运行EvaluateSIFTMatcher.m文件检查实现结果)。 (4) 基于图像中的匹配关键点,对两幅图像进行配准。请分别采用最小二乘方法(编辑ComputeAffineMatrix.m文件实现该操作,运行EvaluateAffineMatrix.m文件检查实现结果)和RANSAC方法估计两幅图像间的变换矩阵(编辑RANSACFit.m 文件中的ComputeError()函数实现该操作,运行TransformationTester.m文件检查实现结果)。 (5) 基于变换矩阵,对其中一幅图像进行变换处理,将其与另一幅图像进行拼接。 (6) 对同一场景的多幅图像进行上述操作,实现场景的全景图拼接(编辑MultipleStitch.m文件中的makeTransformToReferenceFrame函数实现该操作)。可以运行StitchTester.m查看拼接结果。 (7) 请比较DoG检测子和Harris-Laplacian检测子的实验结果。图像拼接的效果对实验数据中的几个场景效果不同,请分析原因。 已经实现这些功能,并且编译运行均不报错!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

自动驾驶simulation

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值