Я пытаюсь откалибровать камеру объектива RaspiCam Fisheye с помощью OpenCV. Я использую пример кода Python, и номера строк и столбцов на шахматной доске также верны, но каким-то образом я не могу получить успешный результат. Я протестировал множество фотографий ниже, вы можете их увидеть. Мой исходный код: https://github.com/jagracar/OpenCV-python-tests/blob/master/OpenCV-tutorials/cameraCalibration/cameraCalibration.py
строки и столбцы моей шахматной доски: rows = 9, cols = 6
но не получает успешный результат
Изменение: мое решение
https://gist.github.com/mesutpiskin/0412c44bae399adf1f48007f22bdd22d
Начиная с opencv 3, был введен модуль " fisheye
", который довольно хорошо управляет калибровкой линз типа "рыбий глаз". (По крайней мере, для тех, кто не знаком с математикой за процессом калибровки.)
# Checkboard dimensions
CHECKERBOARD = (6,9)
subpix_criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1)
calibration_flags = cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC + cv2.fisheye.CALIB_CHECK_COND + cv2.fisheye.CALIB_FIX_SKEW
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)
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
### read images and for each image:
img = cv2.imread(fname)
img_shape = img.shape[:2]
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
# Find the chess board corners
ret, corners = cv2.findChessboardCorners(gray, CHECKERBOARD, cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)
# If found, add object points, image points (after refining them)
if ret == True:
objpoints.append(objp)
cv2.cornerSubPix(gray,corners,(3,3),(-1,-1),subpix_criteria)
imgpoints.append(corners)
###
# calculate K & D
N_imm = # number of calibration images
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_imm)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_imm)]
retval, K, D, rvecs, tvecs = cv2.fisheye.calibrate(
objpoints,
imgpoints,
gray.shape[::-1],
K,
D,
rvecs,
tvecs,
calibration_flags,
(cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6))
И теперь, когда у вас есть K и D, вы можете неуверенно:
img = # your image to undistort
map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)
undistorted_img = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
это должно сработать!
ОБНОВЛЕНИЕ
Если вы хотите увидеть скрытые части изображения (например, часть за пределами желтой рамки на изображении выше), после калибровки вам понадобится следующее:
img = cv2.imread(img_path)
img_dim = img.shape[:2][::-1]
DIM = # dimension of the images used for calibration
scaled_K = K * img_dim[0] / DIM[0]
scaled_K[2][2] = 1.0
new_K = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(scaled_K, D,
img_dim, np.eye(3), balance=balance)
map1, map2 = cv2.fisheye.initUndistortRectifyMap(scaled_K, D, np.eye(3),
new_K, img_dim, cv2.CV_16SC2)
undist_image = cv2.remap(img, map1, map2, interpolation=cv2.INTER_LINEAR,
borderMode=cv2.BORDER_CONSTANT)
Теперь, изменяя balance
значение, вы должны уменьшить или увеличить размер финального изображения (по сравнению с изображением выше, практически желтый прямоугольник).
Из OpenCV API: balance
: устанавливает новое фокусное расстояние в диапазоне между минимальным фокусным расстоянием и максимальным фокусным расстоянием. Баланс находится в диапазоне [0, 1].
Во-первых, насколько я вижу, у вашей камеры есть оптическая система рыбий глаз, но она не дает всей поверхности изображения рыбий глаз (обычно это круг внутри черной рамки). Второй. Код, который вы используете, предназначен для обычной камеры или широкоугольного (90-110 градусов). Это не для рыбий глаз (~ 180 градусов). В третьих. Вы можете использовать ссылку URL-адреса исходного кода из ЗДЕСЬ