Programming/openCV2024. 2. 20. 19:07

스테레오 카메라를 이용해서 깊이 분석을 하기 전에 렌즈 왜곡을 먼저 잡아야 한다고 한다.

[링크 : https://makepluscode.tistory.com/110]

[링크 : http://www.gisdeveloper.co.kr/?p=6955]

 

 

캘리브레이션은 체커보드 있으면 된다는데, 어찌어찌 만들어 놓았으니 해봐야지

[링크 : https://foss4g.tistory.com/1665]

 

Calibration
Now that we have our object points and image points, we are ready to go for calibration. We can use the function, cv.calibrateCamera() which returns the camera matrix, distortion coefficients, rotation and translation vectors etc.

ret, mtx, dist, rvecs, tvecs = cv.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

Undistortion
Now, we can take an image and undistort it. OpenCV comes with two methods for doing this. However first, we can refine the camera matrix based on a free scaling parameter using cv.getOptimalNewCameraMatrix(). If the scaling parameter alpha=0, it returns undistorted image with minimum unwanted pixels. So it may even remove some pixels at image corners. If alpha=1, all pixels are retained with some extra black images. This function also returns an image ROI which can be used to crop the result.

So, we take a new image (left12.jpg in this case. That is the first image in this chapter)

img = cv.imread('left12.jpg')
h,  w = img.shape[:2]
newcameramtxroi = cv.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))
1. Using cv.undistort()
This is the easiest way. Just call the function and use ROI obtained above to crop the result.

# undistort
dst = cv.undistort(img, mtx, dist, None, newcameramtx)
# crop the image
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv.imwrite('calibresult.png', dst)

2. Using remapping
This way is a little bit more difficult. First, find a mapping function from the distorted image to the undistorted image. Then use the remap function.

# undistort
mapx, mapy = cv.initUndistortRectifyMap(mtx, dist, None, newcameramtx, (w,h), 5)
dst = cv.remap(img, mapx, mapy, cv.INTER_LINEAR)
# crop the image
x, y, w, h = roi
dst = dst[y:y+h, x:x+w]
cv.imwrite('calibresult.png', dst)

[링크 : https://docs.opencv.org/4.x/dc/dbb/tutorial_py_calibration.html]

 

Parameters
rvecs Output vector of rotation vectors (Rodrigues ) estimated for each pattern view (e.g. std::vector<cv::Mat>>). That is, each i-th rotation vector together with the corresponding i-th translation vector (see the next output parameter description) brings the calibration pattern from the object coordinate space (in which object points are specified) to the camera coordinate space. In more technical terms, the tuple of the i-th rotation and translation vector performs a change of basis from object coordinate space to camera coordinate space. Due to its duality, this tuple is equivalent to the position of the calibration pattern with respect to the camera coordinate space.
tvecs Output vector of translation vectors estimated for each pattern view, see parameter describtion above.
stdDeviationsIntrinsics Output vector of standard deviations estimated for intrinsic parameters. Order of deviations values: (fx,fy,cx,cy,k1,k2,p1,p2,k3,k4,k5,k6,s1,s2,s3,s4,τx,τy) If one of parameters is not estimated, it's deviation is equals to zero.
stdDeviationsExtrinsics Output vector of standard deviations estimated for extrinsic parameters. Order of deviations values: (R0,T0,…,RM−1,TM−1) where M is the number of pattern views. Ri,Ti are concatenated 1x3 vectors.
perViewErrors Output vector of the RMS re-projection error estimated for each pattern view.

Returns
the overall RMS re-projection error.

[링크 : https://docs.opencv.org/4.x/d9/d0c/group__calib3d.html#ga3207604e4b1a1758aa66acb6ed5aa65d]

 

+

테스트 이미지를 보정해서 저장하도록 수정

$ cat calib.py 
import cv2
import numpy as np
import os
import glob
# 체커보드의 차원 정의
CHECKERBOARD = (6,9) # 체커보드 행과 열당 내부 코너 수
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)
# 각 체커보드 이미지에 대한 3D 점 벡터를 저장할 벡터 생성
objpoints = []
# 각 체커보드 이미지에 대한 2D 점 벡터를 저장할 벡터 생성
imgpoints = [] 
# 3D 점의 세계 좌표 정의
objp = np.zeros((1, CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32)
objp[0,:,:2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
prev_img_shape = None
# 주어진 디렉터리에 저장된 개별 이미지의 경로 추출
images = glob.glob('./images/*.jpg')
for fname in images:
    img = cv2.imread(fname)
    # 그레이 스케일로 변환
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # 체커보드 코너 찾기
    # 이미지에서 원하는 개수의 코너가 발견되면 ret = true
    ret, corners = cv2.findChessboardCorners(gray,
                                             CHECKERBOARD,
                                             cv2.CALIB_CB_ADAPTIVE_THRESH + cv2.CALIB_CB_FAST_CHECK + cv2.CALIB_CB_NORMALIZE_IMAGE)
    # 원하는 개수의 코너가 감지되면,
    # 픽셀 좌표 미세조정 -> 체커보드 이미지 표시
    if ret == True:
        objpoints.append(objp)
        # 주어진 2D 점에 대한 픽셀 좌표 미세조정
        corners2 = cv2.cornerSubPix(gray, corners, (11,11),(-1,-1), criteria)
        imgpoints.append(corners2)
        # 코너 그리기 및 표시
        img = cv2.drawChessboardCorners(img, CHECKERBOARD, corners2, ret)
    cv2.imshow('img',img)
    cv2.waitKey(0)
cv2.destroyAllWindows()

h,w = img.shape[:2] # 480, 640
# 알려진 3D 점(objpoints) 값과 감지된 코너의 해당 픽셀 좌표(imgpoints) 전달, 카메라 캘리브레이션 수행
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

images = glob.glob('./images/*.jpg')
for fname in images:
    img = cv2.imread(fname)

    h,  w = img.shape[:2]
    newcameramtx, roi = cv2.getOptimalNewCameraMatrix(mtx, dist, (w,h), 1, (w,h))

    dst = cv2.undistort(img, mtx, dist, None, newcameramtx)
    # crop the image
    x, y, w, h = roi
    dst = dst[y:y+h, x:x+w]
    print(fname+'.undisto')
    cv2.imwrite(fname+'.undisto.jpg', dst)

 

2760p 노트북에 달린 웹캠 720p로 해봤는데

먼가 꼼지락 대는거 보면 왜곡이 보정된 것 같기도 하고.. 아닌것 같기도 하고 모르겠다 ㅎㅎ

'Programming > openCV' 카테고리의 다른 글

opencv stereo 계산 알고리즘  (0) 2024.02.24
opencv 스테레오 카메라 깊이 처리하기  (0) 2024.02.21
opencv 카메라 캡쳐 - 최신 이미지 갱신  (0) 2024.01.25
opencv webcam 수동촛점 조절  (0) 2024.01.25
MTM + webcam  (0) 2024.01.16
Posted by 구차니