基于Carla模拟环境的目标检测

object_dection.py 脚本主要是在 Carla 中使用 YOLOv3 检测车辆。相关链接

湖工商场景(WindowsNoEditor),并运行generate_traffic.py

导入必要的库及变量

import random
import weakref
import cv2
import pygame
import numpy as np
from imutils.video import FPS
import carla
VIEW_WIDTH = 1920 // 2
VIEW_HEIGHT = 1080 // 2
VIEW_FOV = 90

加载模型和配置文件

model = cv2.dnn.readNet("weights/yolov3.weights", "cfg/yolov3.cfg")
classes = [line.strip() for line in open("cfg/coco.names", "r").readlines()]
layers_names = model.getLayerNames()
output_layers = [layers_names[i[0] - 1] for i in model.getUnconnectedOutLayers()]
colors = np.random.uniform(0, 255, size=(len(classes), 3))

定义绘制标签的函数

def draw_labels(boxes, confs, colors, class_ids, classes, img):
    indexes = cv2.dnn.NMSBoxes(boxes, confs, 0.5, 0.4)
    font = cv2.FONT_HERSHEY_PLAIN
    for i in range(len(boxes)):
        if i in indexes:
            x, y, w, h = boxes[i]
            label = str(classes[class_ids[i]])
            color = colors[i]
            cv2.rectangle(img, (x, y), (x + w, y + h), color, 2)
            cv2.putText(img, label, (x, y - 5), font, 1, color, 1)
    return img

定义获取框维度的函数

def get_box_dimensions(outputs, height, width):
    boxes = []
    confs = []
    class_ids = []
    for output in outputs:
        for detect in output:
            scores = detect[5:]
            class_id = np.argmax(scores)
            conf = scores[class_id]
            if conf > 0.5:
                center_x = int(detect[0] * width)
                center_y = int(detect[1] * height)
                w = int(detect[2] * width)
                h = int(detect[3] * height)
                x = int(center_x - w / 2)
                y = int(center_y - h / 2)
                boxes.append([x, y, w, h])
                confs.append(float(conf))
                class_ids.append(class_id)
    return boxes, confs, class_ids

定义 Carla 客户端类

class CarlaClient():
    def __init__(self): #初始化实例变量
        self.client = None
        self.world = None
        self.camera = None
        self.car = None
        self.image = None
        self.capture = True
        self.display = None

    def set_synchronous_mode(self, synchronous_mode): #设置Carla世界的同步模式
        settings = self.world.get_settings()
        settings.synchronous_mode = synchronous_mode
        self.world.apply_settings(settings)

    def setup_car(self):  #从蓝图库中选中一个汽车对象
        blueprint_library = self.world.get_blueprint_library()
        car_bp = blueprint_library.filter('vehicle.*')[0]
        spawn_point = random.choice(self.world.get_map().get_spawn_points())
        self.car = self.world.spawn_actor(car_bp, spawn_point)

    def setup_camera(self): #获取摄像头对象,并将其附加到汽车上
        camera_bp = self.world.get_blueprint_library().find('sensor.camera.rgb')
        camera_transform = carla.Transform(carla.Location(x=1.5, z=2.4))
        camera_bp.set_attribute('image_size_x', f'{VIEW_WIDTH}')
        camera_bp.set_attribute('image_size_y', f'{VIEW_HEIGHT}')
        camera_bp.set_attribute('fov', f'{VIEW_FOV}')
        self.camera = self.world.spawn_actor(camera_bp, camera_transform, attach_to=self.car)
        weak_self = weakref.ref(self)
        self.camera.listen(lambda image: weak_self().set_image(weak_self, image))

    @staticmethod
    def set_image(weak_self, img): #捕获图像
        self = weak_self()
        if self.capture:
            self.image = img
            self.capture = False

    def render(self, display): #渲染捕获的图像,并在图像上绘制物体检测标签
        if self.image is not None:
            array = np.frombuffer(self.image.raw_data, dtype=np.dtype("uint8"))
            array = np.reshape(array, (self.image.height, self.image.width, 4))
            array = array[:, :, :3]

            # draw labels
            img = cv2.resize(array, None, fx=1, fy=1)
            height, width, channels = img.shape
            blob = cv2.dnn.blobFromImage(img, scalefactor=0.00392, size=(320, 320), mean=(0, 0, 0), swapRB=True, crop=False)
            model.setInput(blob)
            outputs = model.forward(output_layers)
            boxes, confs, class_ids = get_box_dimensions(outputs, height, width)
            array = draw_labels(boxes, confs, colors, class_ids, classes, img)

            array = array[:, :, ::-1]
            surface = pygame.surfarray.make_surface(array.swapaxes(0, 1))
            display.blit(surface, (0, 0))

main 函数中主要是在Carla模拟器中运行自动驾驶,并通过摄像头捕获图像后采用YOLOv3模型进行车辆物体的检测,最后使用Pygame显示处理后的图像。

if __name__ == '__main__':
    cc = CarlaClient()
    try:
        pygame.init()
        clock = pygame.time.Clock()
        cc.client = carla.Client('127.0.0.1', 2000)
        cc.client.set_timeout(5.0)
        cc.world = cc.client.get_world()

        cc.setup_car()
        cc.setup_camera()
        cc.display = pygame.display.set_mode((VIEW_WIDTH, VIEW_HEIGHT), pygame.HWSURFACE | pygame.DOUBLEBUF)
        pygame_clock = pygame.time.Clock()

        cc.car.set_autopilot(True)

        while True:
            fps = FPS().start()
            cc.world.tick()
            cc.capture = True
            pygame_clock.tick_busy_loop(30)
            cc.render(cc.display)
            pygame.display.flip()
            pygame.event.pump()
            cv2.waitKey(1)
            fps.stop()
            print("[INFO] elapsed time: {:.2f}".format(fps.elapsed()))

    except Exception as e:
        print(e)

    finally:
        cc.set_synchronous_mode(False)
        cc.camera.destroy()
        cc.car.destroy()
        pygame.quit()
        cv2.destroyAllWindows()