Создайте сетку заполнения с помощью монокулярной камеры и семантической сегментации

Этот пример показывает, как оценить свободное пространство вокруг транспортного средства и создать сетку заполнения с помощью семантической сегментации и глубокого обучения. Затем эта сетка заполнения используется для создания косметической карты транспортного средства, которая может использоваться для планирования пути.

Об оценке свободного пространства

Оценка свободного пространства определяет области в окружение, где автомобиль , оборудованный датчиком может вращаться, не задевая никаких препятствий, таких как пешеходы, бордюры или другие транспортные средства. Транспортное средство может использовать различные датчики для оценки свободного пространства, такого как радар, лидар или камеры. Этот пример фокусируется на оценке свободного пространства от датчика изображения с помощью семантической сегментации.

В этом примере вы узнаете, как:

  • Используйте семантическую сегментацию изображений, чтобы оценить свободное пространство.

  • Создайте сетку заполнения с помощью оценки свободного пространства.

  • Визуализируйте сетку заполнения на графике птичьего глаза.

  • Создайте транспортное средство косметику с помощью сетки заполнения.

  • Проверяйте, заняты ли места в мире или свободны.

Загрузка предварительно обученной сети

Этот пример использует предварительно обученную сеть семантической сегментации, которая может классифицировать пиксели в 11 различных классов, включая Road, Pedestrian, Car, и Sky. Свободное пространство в изображении может быть оценено путем определения пикселей изображения, классифицированных как Road как свободное пространство. Все другие классы определяются как несвободное пространство или препятствия.

Полная процедура настройки этой сети показана в примере Семантическая Сегментация Using Deep Learning (Computer Vision Toolbox). Загрузите предварительно обученную сеть.

% Download the pretrained network.
pretrainedURL = 'https://www.mathworks.com/supportfiles/vision/data/segnetVGG16CamVid.mat';
pretrainedFolder = fullfile(tempdir,'pretrainedSegNet');
pretrainedSegNet = fullfile(pretrainedFolder,'segnetVGG16CamVid.mat');
if ~exist(pretrainedFolder,'dir')
    mkdir(pretrainedFolder);
    disp('Downloading pretrained SegNet (107 MB)...');
    websave(pretrainedSegNet,pretrainedURL);
    disp('Download complete.');
end

% % Load the network.
data = load(pretrainedSegNet);
net = data.net;

Примечание: Время загрузки данных зависит от вашего подключения к Интернету. Команды, используемые выше, блокируют MATLAB до завершения загрузки. Кроме того, можно использовать веб-браузер для первой загрузки набора данных на локальный диск. В этом случае, чтобы использовать файл, который вы загрузили из Интернета, измените pretrainedFolder переменная выше в местоположении загруженного файла.

Оценка свободного пространства

Оцените свободное пространство путем обработки изображения с помощью загруженной семантической сети сегментации. Сеть возвращает классификации для каждого пикселя изображения в изображении. Свободное пространство идентифицируется как пиксели изображения, которые были классифицированы как Road.

Изображение, используемое в этом примере, является одной системой координат из последовательности изображений в наборе данных CamVid [1]. Процедура, показанная в этом примере, может быть применена к последовательности систем координат для оценки свободного пространства, когда транспортное средство двигается вдоль. Однако, поскольку в этом примере используется очень глубокая сверточная нейронная сеть архитектура (SegNet с VGG-16 энкодером), обработка каждой системы координат занимает около 1 секунды. Поэтому для целесообразности обработайте одну систему координат.

% Read the image.
I = imread('seq05vd_snap_shot.jpg');

% Segment the image.
[C,scores,allScores] = semanticseg(I,net);

% Overlay free space onto the image.
B = labeloverlay(I,C,'IncludedLabels',"Road");

% Display free space and image.
figure
imshow(B)

Чтобы понять доверие в оценке свободного пространства, отобразите выход счета для Road класс для каждого пикселя. Доверительные значения могут использоваться, чтобы информировать нисходящие алгоритмы о валидности оценки. Например, даже если сеть классифицирует пиксель как Road, оценка достоверности может быть достаточно низким, чтобы игнорировать эту классификацию по соображениям безопасности.

% Use the network's output score for Road as the free space confidence.
roadClassIdx = 4;
freeSpaceConfidence = allScores(:,:,roadClassIdx);
    
% Display the free space confidence.
figure
imagesc(freeSpaceConfidence)
title('Free Space Confidence Scores')
colorbar

Хотя начальный результат сегментации для Road пиксели, показанные большинством пикселей на дороге, были классифицированы правильно, визуализация счетов дает более подробную информацию о доверии классификатора к этим классификациям. Например, доверие уменьшается, когда вы приближаетесь к контуру автомобиля.

Создайте изображение вида птицы

Оценка свободного пространства генерируется в пространстве изображений. Чтобы облегчить генерацию сетки заполнения, которая полезна для навигации, оценка свободного пространства должна быть преобразована в систему координат транспортного средства. Это может быть сделано путем преобразования оценки свободного пространства в изображение с видом на глаз птицы.

Чтобы создать изображение вида птицы, сначала задайте строение датчика камеры. Вспомогательная функция, перечисленная в конце этого примера, camvidMonoCameraSensor, возвращает monoCamera (Automated Driving Toolbox) объект, представляющий монокулярную камеру, используемую для сбора данных CamVid [1]. Конфигурирование monoCamera (Automated Driving Toolbox) требует встроенных и внешних данных камеры, которые были оценены с использованием данных, представленных в наборе данных CamVid. Чтобы оценить внутренность камеры, функция использовала калибровочные изображения CamVid и приложение Camera Calibrator (Computer Vision Toolbox). Оценки внешности камеры, такие как высота и тангаж, были получены из внешних данных, оцененных авторами набора данных CamVid.

% Create monoCamera for CamVid data.
sensor = camvidMonoCameraSensor();

Учитывая настройку камеры, birdsEyeView Объект (Automated Driving Toolbox) преобразует исходное изображение в вид птичьего полета. Этот объект позволяет вам задать область, которую вы хотите преобразовать с помощью координат транспортного средства. Обратите внимание, что модули координат транспортного средства были установлены monoCamera (Automated Driving Toolbox), когда высота установки камеры была задана в метрах. Например, если бы высота была задана в миллиметрах, в остальной части симуляции использовались бы миллиметры.

% Define bird's-eye-view transformation parameters.
distAheadOfSensor = 20; % in meters, as previously specified in monoCamera height input
spaceToOneSide    = 3;  % look 3 meters to the right and left
bottomOffset      = 0;  
outView = [bottomOffset, distAheadOfSensor, -spaceToOneSide, spaceToOneSide];

outImageSize = [NaN, 256]; % output image width in pixels; height is chosen automatically to preserve units per pixel ratio

birdsEyeConfig = birdsEyeView(sensor,outView,outImageSize);

Сгенерируйте изображение вида птицы для изображения и доверия свободного пространства.

% Resize image and free space estimate to size of CamVid sensor. 
imageSize = sensor.Intrinsics.ImageSize;
I = imresize(I,imageSize);
freeSpaceConfidence = imresize(freeSpaceConfidence,imageSize);

% Transform image and free space confidence scores into bird's-eye view.
imageBEV = transformImage(birdsEyeConfig,I);
freeSpaceBEV = transformImage(birdsEyeConfig,freeSpaceConfidence); 

% Display image frame in bird's-eye view.
figure
imshow(imageBEV)

Преобразуйте изображение в вид птичьего полета и генерируйте доверие в свободном пространстве.

figure
imagesc(freeSpaceBEV)
title('Free Space Confidence')

Области, удаленные от датчика, являются более размытыми из-за наличия меньшего количества пикселей и, таким образом, требующих большей интерполяции.

Создайте сетку заполнения на основе оценки свободного пространства

Сетки заполнения используются для представления окружающей среды транспортного средства как дискретной сетки в координатах транспортного средства и используются для планирования пути. Каждая камера в сетке заполнения имеет значение, представляющее вероятность заполнения этой камеры. Предполагаемое свободное пространство может использоваться для заполнения значений сетки заполнения.

Процедура заполнения сетки заполнения с помощью оценки свободного пространства заключается в следующем:

  1. Определите размерности сетки заполнения в координатах транспортного средства.

  2. Сгенерируйте набор (X, Y) точек для каждой камеры сетки. Эти точки находятся в системе координат транспортного средства.

  3. Преобразуйте точки из координатного пространства автомобиля (X, Y) в координатное пространство изображения вида птицы (x, y) с помощью vehicleToImage (Automated Driving Toolbox) преобразование.

  4. Выборка доверительных значений свободного пространства в (x, y) местоположениях с помощью griddedInterpolant для интерполяции доверительных значений свободного пространства, которые не совсем в пиксельных центрах на изображении.

  5. Заполните камеру сетки заполнения средним доверительным значением свободного пространства для всех (x, y) точек, которые соответствуют этой камере сетки.

Для краткости процедура, показанная выше, реализована в вспомогательной функции, createOccupancyGridFromFreeSpaceEstimate, который перечислен в конце этого примера. Определите размерности сетки заполнения с точки зрения строения «птичий глаз» и создайте сетку заполнения путем вызова createOccupancyGridFromFreeSpaceEstimate.

% Define dimensions and resolution of the occupancy grid.
gridX = distAheadOfSensor;
gridY = 2 * spaceToOneSide;
cellSize = 0.25; % in meters to match units used by CamVid sensor

% Create the occupancy grid from the free space estimate.
occupancyGrid = createOccupancyGridFromFreeSpaceEstimate(...
    freeSpaceBEV, birdsEyeConfig, gridX, gridY, cellSize);

Визуализируйте сетку заполнения с помощью birdsEyePlot (Automated Driving Toolbox). Создайте birdsEyePlot (Automated Driving Toolbox) и добавить сетку заполнения сверху с помощью pcolor.

% Create bird's-eye plot.
bep = birdsEyePlot('XLimits',[0 distAheadOfSensor],'YLimits', [-5 5]);

% Add occupancy grid to bird's-eye plot.
hold on
[numCellsY,numCellsX] = size(occupancyGrid);
X = linspace(0, gridX, numCellsX);
Y = linspace(-gridY/2, gridY/2, numCellsY);
h = pcolor(X,Y,occupancyGrid);
title('Occupancy Grid (probability)')
colorbar
delete(legend)

% Make the occupancy grid visualization transparent and remove grid lines.
h.FaceAlpha = 0.5;
h.LineStyle = 'none';

График птичьего глаза может также отображать данные с нескольких датчиков. Для примера добавьте зону покрытия радара, используя coverageAreaPlotter (Automated Driving Toolbox).

% Add coverage area to plot.
caPlotter = coverageAreaPlotter(bep, 'DisplayName', 'Coverage Area');

% Update it with a field of view of 35 degrees and a range of 60 meters
mountPosition = [0 0];
range = 15;
orientation = 0;
fieldOfView = 35;
plotCoverageArea(caPlotter, mountPosition, range, orientation, fieldOfView);
hold off

Отображение данных с нескольких датчиков полезно для диагностики и отладки решений, принятых автономными транспортными средствами.

Создайте карту стоимости транспортного средства, используя сетку заполнения

The vehicleCostmap (Automated Driving Toolbox) предоставляет функциональные возможности для проверки того, заняты или свободны ли местоположения в координатах транспортного средства или мира. Эта проверка необходима для любого алгоритма планирования пути или принятия решений. Создайте vehicleCostmap (Automated Driving Toolbox) с использованием сгенерированного occupancyGrid.

% Create the costmap.
costmap = vehicleCostmap(flipud(occupancyGrid), ...
    'CellSize',cellSize, ...
    'MapLocation',[0,-spaceToOneSide]);
costmap.CollisionChecker.InflationRadius = 0;

% Display the costmap.
figure
plot(costmap,'Inflation','off')
colormap(parula)
colorbar
title('Vehicle Costmap')

% Orient the costmap so that it lines up with the vehicle coordinate
% system, where the X-axis points in front of the ego vehicle and the
% Y-axis points to the left.
view(gca,-90,90)

Чтобы проиллюстрировать, как использовать vehicleCostmap (Automated Driving Toolbox), создайте набор местоположений в мировых координатах. Эти местоположения представляют путь, через который может проходить транспортное средство.

% Create a set of locations in vehicle coordinates.
candidateLocations = [
    8 0.375
    10 0.375
    12 2
    14 0.375   
    ];

Использование checkOccupied (Automated Driving Toolbox), чтобы проверить, занято ли каждое место или нет. На основе результатов потенциальный путь может оказаться невозможным, потому что он сталкивается с препятствиями, определенными в costmap.

% Check if locations are occupied.
isOccupied = checkOccupied(costmap,candidateLocations);

% Partition locations into free and occupied for visualization purposes.
occupiedLocations = candidateLocations(isOccupied,:);
freeLocations = candidateLocations(~isOccupied,:);

% Display free and occupied points on top of costmap.
hold on
markerSize = 100;
scatter(freeLocations(:,1),freeLocations(:,2),markerSize,'g','filled')
scatter(occupiedLocations(:,1),occupiedLocations(:,2),markerSize,'r','filled');
legend(["Free" "Occupied"])
hold off

Использование occupancyGrid, vehicleCostmap (Automated Driving Toolbox), и checkOccupied (Automated Driving Toolbox), показанный выше, иллюстрирует основные операции, используемые планировщиками путей, такими как pathPlannerRRT (Automated Driving Toolbox). Дополнительные сведения о планировании пути см. в примере Automated Parking Valet (Automated Driving Toolbox).

Ссылки

[1] Brostow, Gabriel J., Julien Fauqueur, and Roberto Cipolla. Semantic Object Classes in Video: A high-definition основная истина database (неопр.) (недоступная ссылка). Распознавание Букв. Том 30, Выпуск 2, 2009, стр. 88-97.

Вспомогательные функции

function sensor = camvidMonoCameraSensor()
% Return a monoCamera camera configuration based on data from the CamVid 
% data set[1].
%
% The cameraCalibrator app was used to calibrate the camera using the
% calibration images provided in CamVid:
%
% http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/data/CalibrationSeq_and_Files_0010YU.zip
%
% Calibration pattern grid size is 28 mm. 
%
% Camera pitch is computed from camera pose matrices [R t] stored here:
%
% http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/data/EgoBoost_trax_matFiles.zip

% References
% ----------
% [1] Brostow, Gabriel J., Julien Fauqueur, and Roberto Cipolla. "Semantic Object 
% Classes in Video: A high-definition ground truth database." _Pattern Recognition 
% Letters_. Vol. 30, Issue 2, 2009, pp. 88-97.

calibrationData = load('camera_params_camvid.mat');

% Describe camera configuration.
focalLength    = calibrationData.cameraParams.FocalLength;
principalPoint = calibrationData.cameraParams.PrincipalPoint;
imageSize      = calibrationData.cameraParams.ImageSize;

% Camera height estimated based on camera setup pictured in [1].
height = 0.5;  % height in meters from the ground

% Camera pitch was computed using camera extrinsics provided in data set.
pitch = 0;  % pitch of the camera, towards the ground, in degrees

camIntrinsics = cameraIntrinsics(focalLength,principalPoint,imageSize);
sensor = monoCamera(camIntrinsics,height,'Pitch',pitch);
end
function occupancyGrid = createOccupancyGridFromFreeSpaceEstimate(...
    freeSpaceBEV,birdsEyeConfig,gridX,gridY,cellSize)
% Return an occupancy grid that contains the occupancy probability over
% a uniform 2-D grid.

% Number of cells in occupancy grid.
numCellsX = ceil(gridX / cellSize);
numCellsY = ceil(gridY / cellSize);

% Generate a set of (X,Y) points for each grid cell. These points are in
% the vehicle's coordinate system. Start by defining the edges of each grid
% cell.

% Define the edges of each grid cell in vehicle coordinates.
XEdges = linspace(0,gridX,numCellsX);
YEdges = linspace(-gridY/2,gridY/2,numCellsY);

% Next, specify the number of sample points to generate along each
% dimension within a grid cell. Use these to compute the step size in the
% X and Y direction. The step size will be used to shift the edge values of
% each grid to produce points that cover the entire area of a grid cell at
% the desired resolution.

% Sample 20 points from each grid cell. Sampling more points may produce
% smoother estimates at the cost of additional computation.
numSamplePoints = 20;

% Step size needed to sample number of desired points.
XStep = (XEdges(2)-XEdges(1)) / (numSamplePoints-1);
YStep = (YEdges(2)-YEdges(1)) / (numSamplePoints-1);

% Finally, slide the set of points across both dimensions of the grid
% cells. Sample the occupancy probability along the way using
% griddedInterpolant.

% Create griddedInterpolant for sampling occupancy probability. Use 1
% minus the free space confidence to represent the probability of occupancy.
occupancyProb = 1 - freeSpaceBEV;
sz = size(occupancyProb);
[y,x] = ndgrid(1:sz(1),1:sz(2));
F = griddedInterpolant(y,x,occupancyProb);

% Initialize the occupancy grid to zero.
occupancyGrid = zeros(numCellsY*numCellsX,1);

% Slide the set of points XEdges and YEdges across both dimensions of the
% grid cell. 
for j = 1:numSamplePoints
    
    % Increment sample points in the X-direction
    X = XEdges + (j-1)*XStep;
   
    for i = 1:numSamplePoints
        
        % Increment sample points in the Y-direction
        Y = YEdges + (i-1)*YStep;
        
        % Generate a grid of sample points in bird's-eye-view vehicle coordinates
        [XGrid,YGrid] = meshgrid(X,Y);
        
        % Transform grid of sample points to image coordinates
        xy = vehicleToImage(birdsEyeConfig,[XGrid(:) YGrid(:)]);
        
        % Clip sample points to lie within image boundaries
        xy = max(xy,1);
        xq = min(xy(:,1),sz(2));        
        yq = min(xy(:,2),sz(1));
        
        % Sample occupancy probabilities using griddedInterpolant and keep
        % a running sum.
        occupancyGrid = occupancyGrid + F(yq,xq);  
    end
    
end

% Determine mean occupancy probability.
occupancyGrid = occupancyGrid / numSamplePoints^2;
occupancyGrid = reshape(occupancyGrid,numCellsY,numCellsX);
end