版权声明:本文为u012678352原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.youkuaiyun.com/u012678352/article/details/80899931
代码记录
import glob
from typing import Tuple
import cv2 as cv
import numpy as np
def generate_pattern(checkerboard_size, num_of_row, num_of_col):
"""
自定义生成棋盘格图片
:param checkerboard_size: 棋盘格大小,此处100即可
:param num_of_row: 棋盘格横向内角数
:param num_of_col: 棋盘格纵向内角数
:return:
"""
black = np.zeros((checkerboard_size, checkerboard_size, 3), np.uint8)
white = np.zeros((checkerboard_size, checkerboard_size, 3), np.uint8)
black[:] = [0, 0, 0] # 纯黑色
white[:] = [255, 255, 255] # 纯白色
black_white = np.concatenate([black, white], axis=1)
black_white2 = black_white
white_black = np.concatenate([white, black], axis=1)
white_black2 = white_black
# 横向连接
if num_of_row % 2 == 1:
for i in range(1, (num_of_row + 1) // 2):
black_white2 = np.concatenate([black_white2, black_white], axis=1)
white_black2 = np.concatenate([white_black2, white_black], axis=1)
else:
for i in range(1, num_of_row // 2):
black_white2 = np.concatenate([black_white2, black_white], axis=1)
white_black2 = np.concatenate([white_black2, white_black], axis=1)
black_white2 = np.concatenate([black_white2, black], axis=1)
white_black2 = np.concatenate([white_black2, white], axis=1)
jj = 0
black_white3 = black_white2
for i in range(0, num_of_col):
jj += 1
# 纵向连接
if jj % 2 == 1:
black_white3 = np.concatenate((black_white3, white_black2)) # =np.vstack((img1, img2))
else:
black_white3 = np.concatenate((black_white3, black_white2)) # =np.vstack((img1, img2))
# 添加边缘
black_white4 = cv.copyMakeBorder(black_white3, 30, 30, 30, 30, cv.BORDER_CONSTANT, value=[255, 255, 255])
cv.imshow('', black_white4)
cv.imwrite('./pattern.jpg', black_white4)
cv.waitKey(0)
cv.destroyAllWindows()
def get_K_and_D(checkerboard: Tuple[int, int], imgs_path, save_file=True):
"""
获取矫正参数并保存
:param save_file: 默认保存参数
:param checkerboard: 棋盘行列元组
:param imgs_path: 棋盘图片路径
:return: DIM, K, D
"""
CHECKERBOARD = checkerboard
subpixel_criteria = (cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 0.1)
calibration_flags = cv.fisheye.CALIB_RECOMPUTE_EXTRINSIC + cv.fisheye.CALIB_CHECK_COND + cv.fisheye.CALIB_FIX_SKEW
obj_p = np.zeros((1, CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32)
obj_p[0, :, :2] = np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2)
_img_shape = None
obj_points = []
img_points = []
images = glob.glob(imgs_path + '/*.jpg')
gray = None
for image_filename in images:
img = cv.imread(image_filename)
if _img_shape is None:
_img_shape = img.shape[:2]
else:
assert _img_shape == img.shape[:2], "All images must share the same size."
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
ret, corners = cv.findChessboardCorners(gray, CHECKERBOARD,
cv.CALIB_CB_ADAPTIVE_THRESH + cv.CALIB_CB_FAST_CHECK +
cv.CALIB_CB_NORMALIZE_IMAGE)
if ret:
obj_points.append(obj_p)
cv.cornerSubPix(gray, corners, (3, 3), (-1, -1), subpixel_criteria)
img_points.append(corners)
N_OK = len(obj_points)
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
rms, _, _, _, _ = cv.fisheye.calibrate(
obj_points,
img_points,
gray.shape[::-1],
K,
D,
rvecs,
tvecs,
calibration_flags,
(cv.TERM_CRITERIA_EPS + cv.TERM_CRITERIA_MAX_ITER, 30, 1e-6)
)
DIM = _img_shape[::-1]
print("Found " + str(N_OK) + " valid images for calibration")
print("DIM=" + str(_img_shape[::-1]))
print("K=np.array(" + str(K.tolist()) + ")")
print("D=np.array(" + str(D.tolist()) + ")")
if save_file:
np.savez("../calibrate.npz", DIM=DIM, K=K, D=D)
return DIM, K, D
def undistorted(img_or_path, K, D, DIM, scale=0.6, imshow=False):
"""
:param img_or_path: 图片路径或cv读取的图像
:param K:
:param D:
:param DIM:
:param scale:
:param imshow: 是否显示
:return: 矫正后图像
"""
if type(img_or_path) == str:
img = cv.imread(img_or_path)
else:
img = img_or_path
dim1 = img.shape[:2][::-1] # dim1 is the dimension of input image to un-distort
assert dim1[0] / dim1[1] == DIM[0] / DIM[
1], "Image to undistorted needs to have same aspect ratio as the ones used in calibration"
if dim1[0] != DIM[0]:
img = cv.resize(img, DIM, interpolation=cv.INTER_AREA)
Knew = K.copy()
if scale: # change fov
Knew[(0, 1), (0, 1)] = scale * Knew[(0, 1), (0, 1)]
map1, map2 = cv.fisheye.initUndistortRectifyMap(K, D, np.eye(3), Knew, DIM, cv.CV_16SC2)
undistorted_img = cv.remap(img, map1, map2, interpolation=cv.INTER_LINEAR, borderMode=cv.BORDER_CONSTANT)
if imshow:
cv.imshow("undistorted", undistorted_img)
return undistorted_img
def calibrate_single():
"""
文件读取矫正参数
:return:
"""
data = np.load('./calibrate.npz')
DIM = data['DIM']
K = data['K']
D = data['D']
return DIM, K, D