Main Content

이 번역 페이지는 최신 내용을 담고 있지 않습니다. 최신 내용을 영문으로 보려면 여기를 클릭하십시오.

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

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

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

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

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

% Visualize camera extrinsics.
showExtrinsics(stereoParams);

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

비디오를 읽고 표시하기 위한 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');

시차 계산하기

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

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

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

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

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

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

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

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  = im2gray(frameLeftRect);
    frameRightGray = im2gray(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

% Clean up
release(player);

요약

이 예제에서는 보정된 스테레오 카메라를 사용하여 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.