Main Content

스테레오 비디오에서 깊이 추정

이 예제에서는 보정된 스테레오 카메라로 촬영한 비디오에서 사람을 검출하고 카메라와의 거리를 확인하는 방법을 보여줍니다.

스테레오 카메라의 파라미터 불러오기

stereoParameters 객체를 불러옵니다. 이 객체는 stereoCameraCalibrator 앱 또는 estimateCameraParameters 함수를 사용하여 카메라를 보정한 결과입니다.

% Load the stereoParameters object.
load('handshakeStereoParams.mat');

% Visualize camera extrinsics.
showExtrinsics(stereoParams);

Figure contains an axes object. The axes object with title Extrinsic Parameters Visualization contains 32 objects of type patch, text, line.

비디오 파일 리더와 비디오 플레이어 만들기

비디오를 읽고 표시하기 위한 System Object를 만듭니다.

videoFileLeft = 'handshake_left.avi';
videoFileRight = 'handshake_right.avi';

readerLeft = VideoReader(videoFileLeft);
readerRight = VideoReader(videoFileRight);
player = vision.VideoPlayer('Position', [20,200,740 560]);

비디오 프레임 읽기 및 편위수정하기

시차를 계산하고 3차원 장면을 복원하기 위해 왼쪽 카메라와 오른쪽 카메라의 프레임을 편위수정해야 합니다. 편위수정된 영상은 에피폴라 선을 가지며, 행 단위로 정렬되어 있습니다. 이는 매칭 점의 검색 공간을 1차원으로 줄여 시차 계산을 단순화합니다. 편위수정된 영상들을 하나의 입체사진(anaglyph)으로 결합할 수도 있습니다. 이러한 입체사진을 스테레오 적청(red-cyan) 안경으로 보면 3차원 효과가 나타납니다.

frameLeft = readFrame(readerLeft);
frameRight = readFrame(readerRight);

[frameLeftRect, frameRightRect, reprojectionMatrix] = ...
    rectifyStereoImages(frameLeft, frameRight, stereoParams);

figure;
imshow(stereoAnaglyph(frameLeftRect, frameRightRect));
title('Rectified Video Frames');

Figure contains an axes object. The axes object with title Rectified Video Frames contains an object of type image.

시차 계산하기

편위수정된 스테레오 영상에서 대응하는 점들의 쌍은 동일한 픽셀 행에 위치합니다. 왼쪽 영상의 각 픽셀에 대해, 오른쪽 영상에서 대응하는 픽셀까지의 거리를 계산합니다. 이 거리를 시차(disparity)라고 하며, 카메라로부터 대응하는 세계 좌표 점까지의 거리에 비례합니다.

frameLeftGray  = rgb2gray(frameLeftRect);
frameRightGray = rgb2gray(frameRightRect);
    
disparityMap = disparitySGM(frameLeftGray, frameRightGray);
figure;
imshow(disparityMap, [0, 64]);
title('Disparity Map');
colormap jet
colorbar

Figure contains an axes object. The axes object with title Disparity Map contains an object of type image.

3차원 장면 복원하기

시차 지도의 각 픽셀에 대응하는 점들의 3차원 세계 좌표를 복원합니다.

points3D = reconstructScene(disparityMap, reprojectionMatrix);

% Convert to meters and create a pointCloud object
points3D = points3D ./ 1000;
ptCloud = pointCloud(points3D, 'Color', frameLeftRect);

% Create a streaming point cloud viewer
player3D = pcplayer([-3, 3], [-3, 3], [0, 8], 'VerticalAxis', 'y', ...
    'VerticalAxisDir', 'down');

% Visualize the point cloud
view(player3D, ptCloud);

{"String":"Figure Point Cloud Player contains an axes object. The axes object contains an object of type scatter.","Tex":[],"LaTex":[]}

왼쪽 영상에서 사람 검출하기

vision.PeopleDetector System Object를 사용하여 사람을 검출합니다.

% Create the people detector object. Limit the minimum object size for
% speed.
peopleDetector = vision.PeopleDetector('MinSize', [166 83]);

% Detect people.
bboxes = peopleDetector.step(frameLeftGray);

각각의 사람과 카메라와의 거리 확인하기

검출된 개개인의 중심의 3차원 세계 좌표를 구하고 중심에서 카메라까지의 거리(단위: 미터)를 계산합니다.

% Find the centroids of detected people.
centroids = [round(bboxes(:, 1) + bboxes(:, 3) / 2), ...
    round(bboxes(:, 2) + bboxes(:, 4) / 2)];

% Find the 3-D world coordinates of the centroids.
centroidsIdx = sub2ind(size(disparityMap), centroids(:, 2), centroids(:, 1));
X = points3D(:, :, 1);
Y = points3D(:, :, 2);
Z = points3D(:, :, 3);
centroids3D = [X(centroidsIdx)'; Y(centroidsIdx)'; Z(centroidsIdx)'];

% Find the distances from the camera in meters.
dists = sqrt(sum(centroids3D .^ 2));
    
% Display the detected people and their distances.
labels = cell(1, numel(dists));
for i = 1:numel(dists)
    labels{i} = sprintf('%0.2f meters', dists(i));
end
figure;
imshow(insertObjectAnnotation(frameLeftRect, 'rectangle', bboxes, labels));
title('Detected People');

Figure contains an axes object. The axes object with title Detected People contains an object of type image.

비디오의 나머지 부분 처리하기

위에서 설명된 단계를 적용하여 비디오의 모든 프레임에서 사람을 검출하고 카메라와의 거리를 측정합니다.

while hasFrame(readerLeft) && hasFrame(readerRight)
    % Read the frames.
    frameLeft = readFrame(readerLeft);
    frameRight = readFrame(readerRight);
    
    % Rectify the frames.
    [frameLeftRect, frameRightRect] = ...
        rectifyStereoImages(frameLeft, frameRight, stereoParams);
    
    % Convert to grayscale.
    frameLeftGray  = rgb2gray(frameLeftRect);
    frameRightGray = rgb2gray(frameRightRect);
    
    % Compute disparity. 
    disparityMap = disparitySGM(frameLeftGray, frameRightGray);
    
    % Reconstruct 3-D scene.
    points3D = reconstructScene(disparityMap, reprojectionMatrix);
    points3D = points3D ./ 1000;
    ptCloud = pointCloud(points3D, 'Color', frameLeftRect);
    view(player3D, ptCloud);
    
    % Detect people.
    bboxes = peopleDetector.step(frameLeftGray);
    
    if ~isempty(bboxes)
        % Find the centroids of detected people.
        centroids = [round(bboxes(:, 1) + bboxes(:, 3) / 2), ...
            round(bboxes(:, 2) + bboxes(:, 4) / 2)];
        
        % Find the 3-D world coordinates of the centroids.
        centroidsIdx = sub2ind(size(disparityMap), centroids(:, 2), centroids(:, 1));
        X = points3D(:, :, 1);
        Y = points3D(:, :, 2);
        Z = points3D(:, :, 3);
        centroids3D = [X(centroidsIdx), Y(centroidsIdx), Z(centroidsIdx)];
        
        % Find the distances from the camera in meters.
        dists = sqrt(sum(centroids3D .^ 2, 2));
        
        % Display the detect people and their distances.
        labels = cell(1, numel(dists));
        for i = 1:numel(dists)
            labels{i} = sprintf('%0.2f meters', dists(i));
        end
        dispFrame = insertObjectAnnotation(frameLeftRect, 'rectangle', bboxes,...
            labels);
    else
        dispFrame = frameLeftRect;
    end
    
    % Display the frame.
    step(player, dispFrame);
end

{"String":"Figure Point Cloud Player contains an axes object. The axes object contains an object of type scatter.","Tex":[],"LaTex":[]}

% Clean up
release(player);

{"String":"Figure Video Player contains an axes object and other objects of type uiflowcontainer, uimenu, uitoolbar. The axes object contains an object of type image.","Tex":[],"LaTex":[]}

요약

이 예제에서는 보정된 스테레오 카메라를 사용하여 3차원에서 보행자의 위치를 확인하는 방법을 다루었습니다.

참고 문헌

[1] G. Bradski and A. Kaehler, "Learning OpenCV : Computer Vision with the OpenCV Library," O'Reilly, Sebastopol, CA, 2008.

[2] Dalal, N. and Triggs, B., Histograms of Oriented Gradients for Human Detection. CVPR 2005.