스테레오 영상

인간의 시각체계를 모방해 두 대 이상의 카메라를 사용하여 3차원 영상과 정보를 추출하는 기법



두대의 카메라를 사용하여 스테레오 시스템을 만드는 단계

1. 렌즈의 방사왜곡과 접선왜곡을 제거한다.

2. 두 카메라 사이의 각도와 거리를 조절한다.

3. 왼쪽과 오른쪽 영상에서 동일한 특징을 가지는 대응점을 찾는다. 이를 통해 시차지도를 구한다.

4. 카메라 놓여있는 상태를 기반으로 삼각법을 이용하여 시차 지도를 거리로 환산한다. 이 과정을 재투영이라고하며, 이를 통해 깊이지도를 구한다.


스테레오 보정

스테레오 보정은 두 카메라 사이의 기하학적 관계를 계산하는 과정이다. 

스테레오 보정을 위해서는 두카메라 사이의 회전행렬R과 이동백터T를 구해야한다.

회전행렬과 이동백터는 cvSteteoCalibrate() 함수를 이용한다.

※ cvCalibrateCamera2()와 다르게 cvSteteoCalibrate()함수는 카메라두대의 정보가 필요하다.


 double cvStereoCalibrate(

        const CvMat* object_points,

        const CvMat* image_points1,

        const CvMat* image_points2,

        const CvMat* npoints,

        CvMat* camera_matrix1,

        CvMat* dist_coeffs1,

        CvMat* camera_matrix2,

        CvMat* dist_coeffs2,

        CvSize image_size,

        CvMat* R,

        CvMat* T,

        CvMat* E=0,

        CvMat* F=0,

        CvTermCriteria term_crit =cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,30,1e-6),

        int flags=CV_CALIB_FIX_INTRINSIC

);

object_points : N×3 크기의 행렬, M개의 영상에서 각각 K개씩 추출한 점들의 물리적 좌표를 담고있다.

imagePoints1, imagePoint2 : 각각 왼쪽, 오른쪽 픽셀좌표를 담고있는 N×2 행렬

npoints : M×1크기의 행렬이며, 각 영상에서 점들의 개수를 나타낸다.

cameraMatrix1, cameraMatrix2 : 3×3 카메라행렬

distCoeffs1, distCoeffs2 : 1, 2번 카메라에 대한 5×1크기의 왜곡행렬

※ 처음 두개는 방사왜곡, 다음두개는 접선왜곡, 마지막 하나는 방사왜곡

    마지막 하나는 어안렌즈와 같은 광각랜즈에 사용된다.

imageSize : 영상의 크기를 픽셀단위로 나타낸다. (flag값이 CV_CALIB_FIX_INTRINSIC 설정되지 않아 내부 파라미터 계산하거나 갱신할때 사용)

R, T : 회전행렬과 이동백터를 나타나는 행렬로 출력용(아웃파라미터)로 사용된다.

E, F : 선택적으로 사용

term_crit : 최대반복 횟수, 임계값을 지정하여 내부 최적화 과정의 반복횟수를 제어

flag : 광객렌즈와 같은 카메라를 사용할때 내부파라미터는 flag인자에 의해 사용이 조절된다

- CV_CALIB_FIX_INTRINSIC

- CV_CABLE_USE_INTRINSIC_GUESS



스테레오 조정

스테레오  조정은 각각의 영상들을 교정하여 이 영상들이 행-정렬된 카메라에서 촬영된 것처럼 바꾸는 과정이다.

두대의 카메라에서 영상 평면을 재투영하여 동일한 평면에 위치하도록 만들고, 영상의 행들이 정확하게 정면 평행한 구성으로 정렬되도록 만든다.

OpenCV에서는 스테레오 조정을 위해 두가지 방법을 제공한다.


Hartley 알고리즘

오직 기본행렬만을 이용하여 보정되지 않은 스테레오 영상을 조정한다.

두 스테레오 영상 사이에서 계산된 시차가 최소가 되도록 하면서 에피폴들이 무한 위치에 놓이도록 만드는 호모그래피를 찾는다.

두 영상 사이에서 특징점들을 매칭하는 방식으로 수행된다.

장면에서 단순히 점들을 찾는 과정을 통하여 온라인 스테레오 보정이 가능하다는 장점이 있다.

영상 크기에 대한 고려가 없다는 단점이 있다.

 int cvStereoRectifyUncalibrated(

        const CvMat* points1,

        const CvMat* points2,

        const CvMat* F,

        CvSize img_size,

        CvMat* H1,

        CvMat* H2,

        double threshold=5

);

points1, points2 : 왼쪽과 오른쪽 사이의 대응되는 점들을 2×K크기의 행렬 points1, points2로 입력받는다.

F : 기본행렬을 입력 => cvFindFundamentalMat()을 이용하여 얻을수 있다. [기본행렬 구하는 방법 보기]

img_size : 보정에서 사용되는 영상의 크기

H1, H2 : 알고리즘을 통해 구해진 호모그래피 행렬

threshold : 에피폴라 직선까지의 거리가 threshold 인자값보다 큰 점들은 알고리즘에서 사용되지 않는다.


Bouguet 알고리즘

보정되어 있는 카메라에서 회전 및 이동 파라미터를 이용하여 조정을 수행

영상사이의 회전행렬과 이동백터가 주어졌을 경우 두영상에서 재투영에 의한 변화는 최소로 줄이고 공통영역은 최대로 만듬

Hartley알고리즘 보다 Bouguet 알고리즘의 결과가 더 좋다.

 void cvStereoRectify(

        const CvMat* camera_matrix1,

        const CvMat* camera_matrix2,

        const CvMat* dist_coeffs1,

        const CvMat* dist_coeffs2,

        CvSize image_size,

        const CvMat* R,

        const CvMat* T,

        CvMat* R1,

        CvMat* R2,

        CvMat* P1,

        CvMat* P2,

        CvMat* Q=0,

        int flags=CV_CALIB_ZERO_DISPARITY,

        double alpha=-1,

        CvSize new_image_size=cvSize(0,0),

        CvRect* valid_pix_ROI1=0,

        CvRect* valid_pix_ROI2=0

);

cameraMatrix1, cameraMatrix2, distCoeffs1, disCoeff2 : cvStereoCalibrate()함수에 의해 구해진 왜곡백터를 입력으로 받는다

image_size : 보정에 사용한 영상의 크기

R, T : cvStereoCalibrate함수를 이용해 구해진 회전행렬, 이동백터

R1, R2 : 실행결과가 저장되며 왼쪽, 오른쪽 영상 평면에 대한 회전행렬

P1, P2 : 함수실행결과로 3×4크기의 투영행렬

Q : 선택적으로 사용, 4×4크기의 재투영 행렬을 의미

flag : CV_CALIB_ZERO_DISPARITY플래그를 기본으로 가지며 플래그를 설정하지 않으면 두 카메라가 마주보고있ㅎ는것으로 간주



조정지도

스트레오 보정 정보를 구하였다면, 왼쪽과 오른쪽 카메라 영상을 위한 조정 룩업 지도를 계산할수 있다.

 void cvInitUndistortRectifyMap(

        const CvMat* camera_matrix,

        const CvMat* dist_coeffs,

        const CvMat *R,

        const CvMat* new_camera_matrix,

        CvArr* mapx, 

        CvArr* mapy

);

camera_matrix 3×3 카메라행렬

dis_coeffs 5×1 왜곡 파라미터

R : 3×3 회전행렬

new_camera_matrix : 조정된 3×3 카메라 행렬

mapx, mapz : 매핑정보를 담은 아웃파라미터

※ cvStereoRectify()함수를 이용하여 스테레오 카메라를 보정하였다면, 인자를 쉽게 얻을 수 있다.

    cvStereoRectifyUncalibrated()함수를 사용하였다면, 호모그래피에 몇가지 작업을 해줘야 한다.



스테레오 대응

두 대의 카메라 입력영상에서 3D점을 찾아 매칭하는것을 의미한다. 

스테레오 대응은 두 카메라에서 겹치는 장면에서만 계산이 가능


OpenCV에서 블록-매칭 스테레오 알고리즘을 위해 cvFindStereoCorrespondenceBM() 함수를 제공

스테레오 조정된 왼쪽과 오른쪽 영상에서 대응점을 찾기 위해 윈도우 내부의 SAD를 계산한다

두 영상 사이에서 질감이 두드러진 점들을 매칭하는데 유용하게 사용

※ SAD : Sum of Absolute Difference, 주어진 윈도우 내부에서 두영상의 픽셀값들의 차의 절대값을 모두 합한


블록-매칭 스테레오 대응 알고리즘 단계

1. 영상의 밝기를 정규화하고 질감을 향상시키는 전처리 과정

2. 수평 에피폴라 직선을 따라 SAD윈도우를 이동시키며 대응점 찾기

3. 잘못된 대응점들을 제거하는 후처리 과정


CvStereoBMState 구조체 : 블록-매칭 파라미터들과 내부적으로 사용되는 임시 버퍼들이 정의되어있다.

 typedef struct CvStereoBMState

{

        // 전처리과정 (입력영상 Normalization)

        int preFilterType; // =CV_STEREO_BM_NORMALIZED_RESPONSE now

        int preFilterSize; // averaging window size: (5x5) ~ (21x21)

        int preFilterCap; // the output of pre-filtering is clipped by [-preFilterCap,preFilterCap]

 

        // SAD 이용한 대응점 찾기

        int SADWindowSize; // (5x5), (7x7), (21x21)

        int minDisparity;  // minimum disparity (can be negative)

        int numberOfDisparities; // maximum disparity - minimum disparity (> 0)

 

        // 후처리 (나쁜 매칭결과를 제거함)

        int textureThreshold;  //유효한 SAD 응답의 최소값

        int uniquenessRatio;   // accept the computed disparity d* only if

        // SAD(d) >= SAD(d*)*(1 + uniquenessRatio/100.)

        // for any d != d*+/-1 within the search range.

        int speckleWindowSize; // 스펙클 윈도우 크기

        int speckleRange;             // 스펙클 윈도우 내에서 유효한 시차 변동 범위

 

        int trySmallerWindows; // if 1, the results may be more accurate,

        // at the expense of slower processing

        CvRect roi1, roi2;

        int disp12MaxDiff;

 

        // temporary buffers

        CvMat* preFilteredImg0;

        CvMat* preFilteredImg1;

        CvMat* slidingSumBuf;

        CvMat* cost;

        CvMat* disp;

} CvStereoBMState;


cvCreateStereoBMState()CvStereoBMState구조체를 생성한다.

 CvStereoBMState* cvCreateStereoBMState(

        int preset=CV_STEREO_BM_BASIC,

        int numberOfDisparities=0

);

presetFlag

- CV_STEREO_BM_BASIC : 모든 파라미터들을 기본값들로 설정한다

- CV_STEREO_BM_FISH_EYE : 광각 렌즈를 다루기 위한 형태로 파라미터를 설정한다

- CV_STEREO_BM_NARROW

numberOfDisparities


cvReleaseStereoBMState()CvStereoBMState구조체를 해제

 void cvReleaseStereoBMState(CvStereoBMState** state);


cvFindStereoCorrespondenceBM() : 시차지도를 생성

 void cvFindStereoCorrespondenceBM(

        const CvArr* left,

        const CvArr* right,

        CvArr* disparity,

        CvStereoBMState* state

);


















'Developer > OpenCV' 카테고리의 다른 글

매핑  (0) 2013.02.04
기본행렬, 필수행렬  (0) 2013.02.03
어파인변환, 투시변환  (0) 2013.01.31
보정함수  (0) 2013.01.30
보정객체(체스판) 찾기  (0) 2013.01.30
Posted by No names
,