728x90

모든 카메라에는

 

이미지 센서와 렌즈사이는 정확하게 나란하지 않아 약간의 이미지 왜곡이 발생한다.

 

이 왜곡에 대한 행렬을 camera matrix라 한다.

 

camera matrix는 카매라 내부 (왜곡 정도에 대한) 행렬과

 

카메라 이미지 평면 ~ 외부 물체에 대한 회전, 평행이동에 대한 백터로 이루어진다.

 

 

카메라 캘리브레이션 카메라 왜곡 행렬 camera matrix를 찾아주는 작업이다.

 

스테레오 비전 같은 3차원 복원을 한다면 이 카메라 왜곡을 잡아주어야 한다.

 

자세한 설명은 다음 링크에서

 

ref : https://darkpgmr.tistory.com/32

 

 

 

 

https://kr.mathworks.com/help/vision/ug/camera-calibration.html

 

 

 

 

 

카매라 캘리브레이션은 체스판이 있으면 할수 있는데,

 

테블릿에다 채스보드를 띄워서 검출했다.

 

ref : https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html#calibration

 

 

 

 

 

 

카메라 매트릭스와 왜곡 계수를 구하였으면

 

이 값으로 왜곡된 카메라 영상을 보정시킬수가 있다.

 

 

import numpy as np
import cv2
import glob
import pickle
import time

#https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_calib3d/py_calibration/py_calibration.html
#https://stackoverflow.com/questions/6568007/how-do-i-save-and-restore-multiple-variables-in-python

#This should be as close to zero as possible
def reprojection_error(imgpoints, objpoints, mtx, dist, rvecs, tvecs):
    mean_error = 0
    for i in range(len(objpoints)):
        imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], mtx, dist)
        error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
        mean_error = mean_error + error

    print("total error: " + str(mean_error/len(objpoints)))
    return mean_error



# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((4*6,3), np.float32)
objp[:,:2] = np.mgrid[0:6,0:4].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.








cap = cv2.VideoCapture(0)
while(len(objpoints) < 20):
    ret, frame = cap.read()
    frame = cv2.flip(frame, -1)
    rsz = cv2.resize(frame, dsize=(320,240))
    gray = cv2.cvtColor(rsz, cv2.COLOR_BGR2GRAY)


    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, (6,4),None)

    # If found, add object points, image points (after refining them)
    if ret == True:
        objpoints.append(objp)

        corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        imgpoints.append(corners2)

        # Draw and display the corners
        gray = cv2.drawChessboardCorners(gray, (6,4), corners2,ret)
        print("chessobard corner detected. curr num objpoints : " + str(len(objpoints)) +  ", curr num imgpoints : " + str(len(imgpoints)))

        time.sleep(0.2)

    cv2.imshow('res',gray)
    if cv2.waitKey(20) & 0xFF == ord('q'):
        break


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


reprojection_error(imgpoints, objpoints, mtx, dist, rvecs, tvecs)


cap.release()
cv2.destroyAllWindows()


print("camera matrix")
print(mtx)
print("distortion coeff")
print(dist)


# Saving the objects:
with open('cam_calib.pkl', 'wb') as f:
    pickle.dump([mtx, dist, rvecs, tvecs], f)

 

 

 

 

지금 사용하는 파이 카메라는 내부 왜곡이 크지 않아서인지 보정 전과 후에도 큰 차이가 없다.

 

실제 이미지 왜곡은 다음 링크를 참조하는게 좋을것같다.

 

ref : https://medium.com/analytics-vidhya/camera-calibration-with-opencv-f324679c6eb7

 

 

 

import numpy as np
import cv2
import glob
import pickle

def get_cameramat_dist(filename):

    f = open(filename, 'rb')
    mat, dist, rvecs, tvecs = pickle.load(f)
    f.close()

    print("camera matrix")
    print(mat)
    print("distortion coeff")
    print(dist)
    return mat,dist





def main():

    mat, dist = get_cameramat_dist("cam_calib.pkl")

    cap = cv2.VideoCapture(0)

    ret, frame = cap.read()
    frame = cv2.flip(frame, -1)
    rsz = cv2.resize(frame, dsize=(320,240))
    gray = cv2.cvtColor(rsz, cv2.COLOR_BGR2GRAY)


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



    while(True):
        ret, frame = cap.read()
        frame = cv2.flip(frame,-1)
        rsz = cv2.resize(frame, dsize=(320,240))
        gray = cv2.cvtColor(rsz, cv2.COLOR_BGR2GRAY)

        # undistort
        mapx,mapy = cv2.initUndistortRectifyMap(mat,dist,None,newcameramtx,(w,h),5)
        res = cv2.remap(gray,mapx,mapy,cv2.INTER_LINEAR)

        # crop the image
        x,y,w,h = roi
        res = res[y:y+h, x:x+w]

        cv2.imshow('res',res)
        if cv2.waitKey(20) & 0xFF == ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows()



if __name__ == "__main__":
    main()

 

 

300x250

+ Recent posts