В этом примере показано, как сгенерировать MEX-функцию CUDA® от функции MATLAB®, которая вычисляет несоизмеримость стерео двух изображений.
Необходимый
Этот пример генерирует MEX CUDA и имеет следующие сторонние требования.
CUDA включил NVIDIA® графический процессор и совместимый драйвер. Для генерации кода полуточности устройство графического процессора должно иметь минимум, вычисляют возможность 6,0.
Дополнительный
Для сборок неMEX, таких как статические, динамические библиотеки или исполняемые файлы, этот пример имеет следующие дополнительные требования.
Инструментарий NVIDIA.
Переменные окружения для компиляторов и библиотек. Для получения дополнительной информации смотрите Стороннее Оборудование и Подготовку Необходимых как условие продуктов.
Чтобы проверить, что компиляторы и библиотеки, необходимые для выполнения этого примера, настраиваются правильно, используйте 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). % Copyright 2017-2021 The MathWorks, Inc. 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
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: View report
out_disp = stereoDisparity_mex(imgRGB0,imgRGB1); imagesc(out_disp);
Расчеты в этом примере могут также быть сделаны в числах с плавающей точкой полуточности, с помощью stereoDisparityHalfPrecision.m функции точки входа. Чтобы сгенерировать и выполнить код с типами данных полуточности, CUDA вычисляют возможность 6,0, или выше требуется. Установите ComputeCapability
свойство настройки кода возражает против '6.0'
. Для полуточности выделение памяти (malloc) режим для генерации кода CUDA должно быть установлено в 'Дискретный'.
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;
Генерация кода на stereo_disparity_half_precision.m
функция.
codegen -config cfg -args {imgRGB0, imgRGB1} stereoDisparityHalfPrecision;
Code generation successful: View report
codegen
| coder.gpu.kernel
| coder.gpu.kernelfun
| gpucoder.matrixMatrixKernel
| coder.gpu.constantMemory
| gpucoder.stencilKernel
| coder.checkGpuInstall