Стереодиспарение

В этом примере показано, как сгенерировать функцию CUDA ® MEX из функции MATLAB ®, которая вычисляет стереодиспарение двух изображений.

Необходимые условия для третьих лиц

Необходимый

Этот пример генерирует CUDA MEX и имеет следующие требования к третьим лицам.

  • CUDA включает графический процессор NVIDIA ® и совместимый драйвер. Для генерации кода половинной точности графический процессор должно иметь минимальную вычислительную способность 6.0.

Дополнительный

Для сборок, не являющихся MEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.

Проверьте окружение GPU

Чтобы убедиться, что компиляторы и библиотеки, необходимые для выполнения этого примера, настроены правильно, используйте coder.checkGpuInstall функция.

envCfg = coder.gpuEnvConfig('host');
envCfg.BasicCodegen = 1;
envCfg.Quiet = 1;
coder.checkGpuInstall(envCfg);

Вычисление стереодиспарения

The stereoDisparity.m функция точки входа делает два изображения и возвращает карту стереодиспарения, вычисленную из этих двух изображений.

type stereoDisparity
%% Modified Algorithm for Stereo Disparity Block Matching
% In this implementation, instead of finding shifted image, indices are 
% mapped accordingly to save memory and some processing. RGBA column major 
% packed data is used as input for compatibility with CUDA intrinsics. 
% Convolution is performed using separable filters (horizontal and then 
% vertical).

function [out_disp] = stereoDisparity(img0,img1) %#codegen

%   Copyright 2017-2019 The MathWorks, Inc.

% GPU code generation pragma
coder.gpu.kernelfun;

%% Stereo Disparity Parameters
% |WIN_RAD| is the radius of the window to be operated. |min_disparity| is 
% the minimum disparity level the search continues for. |max_disparity| is 
% the maximum disparity level the search continues for.
WIN_RAD = 8;
min_disparity = -16;
max_disparity = 0;

%% Image Dimensions for Loop Control
% The number of channels packed are 4 (RGBA) so as nChannels are 4.
[imgHeight,imgWidth]=size(img0);
nChannels = 4;
imgHeight = imgHeight/nChannels;

%% Store the Raw Differences
diff_img = zeros([imgHeight+2*WIN_RAD,imgWidth+2*WIN_RAD],'int32');

% Store the minimum cost
min_cost = zeros([imgHeight,imgWidth],'int32');
min_cost(:,:) = 99999999;

% Store the final disparity
out_disp = zeros([imgHeight,imgWidth],'int16');

%% Filters for Aggregating the Differences
% |filter_h| is the horizontal filter used in separable convolution.
% |filter_v| is the vertical filter used in separable convolution which
% operates on the output of the row convolution.
filt_h = ones([1 17],'int32');
filt_v = ones([17 1],'int32');

% Main Loop that runs for all the disparity levels. This loop is
% expected to run on CPU.
for d=min_disparity:max_disparity
    
    % Find the difference matrix for the current disparity level. Expect
    % this to generate a Kernel function.
    coder.gpu.kernel;
    for colIdx=1:imgWidth+2*WIN_RAD
        coder.gpu.kernel;
        for rowIdx=1:imgHeight+2*WIN_RAD
            % Row index calculation.
            ind_h = rowIdx - WIN_RAD;
            
            % Column indices calculation for left image.
            ind_w1 = colIdx - WIN_RAD;
            
            % Row indices calculation for right image.
            ind_w2 = colIdx + d - WIN_RAD;
            
            % Border clamping for row Indices.
            if ind_h <= 0
                ind_h = 1;
            end
            if ind_h > imgHeight
                ind_h = imgHeight;
            end
            
            % Border clamping for column indices for left image.
            if ind_w1 <= 0
                ind_w1 = 1;
            end
            if ind_w1 > imgWidth
                ind_w1 = imgWidth;
            end
            
            % Border clamping for column indices for right image.
            if ind_w2 <= 0
                ind_w2 = 1;
            end
            if ind_w2 > imgWidth
                ind_w2 = imgWidth;
            end
            
            % In this step, Sum of absolute Differences is performed
            % across tour channels.
            tDiff = int32(0);
            for chIdx = 1:nChannels
                tDiff = tDiff + abs(int32(img0((ind_h-1)*(nChannels)+chIdx,ind_w1))-int32(img1((ind_h-1)*(nChannels)+chIdx,ind_w2)));
            end
            
            % Store the SAD cost into a matrix.
            diff_img(rowIdx,colIdx) = tDiff;
        end
    end
    
    % Aggregating the differences using separable convolution. Expect this
    % to generate two kernels using shared memory.The first kernel is the 
    % convolution with the horizontal kernel and second kernel operates on 
    % its output the column wise convolution.
    cost_v = conv2(diff_img,filt_h,'valid');
    cost = conv2(cost_v,filt_v,'valid');
    
    % This part updates the min_cost matrix with by comparing the values
    % with current disparity level.
    for ll=1:imgWidth
        for kk=1:imgHeight
            % load the cost
            temp_cost = int32(cost(kk,ll));
            
            % Compare against the minimum cost available and store the
            % disparity value.
            if min_cost(kk,ll) > temp_cost
                min_cost(kk,ll) = temp_cost;
                out_disp(kk,ll) = abs(d) + 8;
            end
            
        end
    end
    
end
end

Чтение изображений и упаковка данных в упакованный столбец RGBA - Основной порядок

img0 = imread('scene_left.png');
img1 = imread('scene_right.png');

[imgRGB0] = pack_rgbData(img0);
[imgRGB1] = pack_rgbData(img1);

Изображение слева

Правильное изображение

Сгенерируйте код GPU

cfg = coder.gpuConfig('mex');
codegen -config cfg -args {imgRGB0, imgRGB1} stereoDisparity;
Code generation successful: To view the report, open('codegen/mex/stereoDisparity/html/report.mldatx').

Запуск сгенерированного MEX и отображение Выхода неоднородности

out_disp = stereoDisparity_mex(imgRGB0,imgRGB1);
imagesc(out_disp);

Половинная точность

Расчеты в этом примере могут также выполняться в числах с плавающей точностью половинной точности, с помощью функции точки входа stereoDisparityHalfPrecision.m. Чтобы сгенерировать и выполнить код с типами данных половинной точности, требуется вычислительная способность CUDA 6.0 или выше. Установите ComputeCapability свойство объекта строения кода, чтобы '6.0'. Для половинной точности режим выделения памяти (malloc) для генерации кода CUDA должен быть установлен на 'Discrete'.

cfg.GpuConfig.ComputeCapability = '6.0';
cfg.GpuConfig.MallocMode = 'Discrete';

Стандартная imread команда представляет каналы RGB изображений с целыми числами, по одному для каждого пикселя. Целые числа варьируются от 0 до 255. Простое приведение входов к половинному типу может привести к переполнению во время сверток. В этом случае мы можем масштабировать изображения до значений от 0 до 1. «imread» представляет каналы RGB изображений с целыми числами, по одному для каждого пикселя. Целые числа варьируются от 0 до 255. Простое приведение входов к половинному типу может привести к переполнению во время сверток. В этом случае мы можем масштабировать изображения до значений от 0 до 1.

img0 = imread('scene_left.png');
img1 = imread('scene_right.png');

[imgRGB0] = half(pack_rgbData(img0))/255;
[imgRGB1] = half(pack_rgbData(img1))/255;

Сгенерируйте MEX CUDA для функции

Генерация кода на stereo_disparity_half_precision.m функция.

codegen -config cfg -args {imgRGB0, imgRGB1} stereoDisparityHalfPrecision;
Code generation successful: To view the report, open('codegen/mex/stereoDisparityHalfPrecision/html/report.mldatx').

См. также

Функции

Объекты

Похожие темы