Несоизмеримость стерео

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

Сторонние необходимые условия

Необходимый

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

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

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

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

Проверьте среду графического процессора

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

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

Вычисление несоизмеримости стерео

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);

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

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

Сгенерируйте код графического процессора

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 вычисляют возможность 5,3, или выше требуется. Установите ComputeCapability свойство настройки кода возражает против '5.3'. Для полуточности выделение памяти (malloc) режим для генерации кода CUDA должно быть установлено в 'Дискретный'.

cfg.GpuConfig.ComputeCapability = '5.3';
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').