Le drone utilisé dans la recherche étant une lentille fish-eye, il est devenu nécessaire de corriger l'image acquise.
D'après la référence [1], la correction générale semble être une "correction rectiligne", et il semble que cela puisse être fait avec opencv, alors je l'ai touchée.
Le module opencv de python cv2
n'a pas de module d'étalonnage d'objectif fisheye
Par conséquent, construisez un environnement de ʻopencv c ++ `.
Mais il y avait une personne qui faisait ça avec ʻopen cv3 series`, alors je l'ai fait là-bas. Voir [4]
Copiez le motif en damier requis pour l'étalonnage avec A4.
Prenez un motif en damier sous différents angles avec une caméra fish-eye (environ 20 clichés).
calibration.py
import cv2
# assert cv2.__version__[0] == '3', 'The fisheye module requires opencv version >= 3.0.0'
import numpy as np
import os
import glob
CHECKERBOARD = (6,9)
print(CHECKERBOARD)
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)
_img_shape = None
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.
images = glob.glob('source/*.jpg')
for fname in images:
img = cv2.imread(fname)
if _img_shape == None:
_img_shape = img.shape[:2]
else:
assert _img_shape == img.shape[:2], "All images must share the same size."
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)
print('img end')
N_OK = len(objpoints)
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
rms, _, _, _, _ = \
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)
)
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()) + ")")
Lors de l'exécution, trois paramètres sont émis. DIM: Angle de vue K: coefficient de déformation radiale D: coefficient de distorsion circonférentielle
undistort.py
import numpy as np
import cv2
import sys
import os
# You should replace these 3 lines with the output in calibration step
DIM=##
K=##
D=##
def undistort(img_path):
img = cv2.imread(img_path)
h,w = img.shape[:2]
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)
# cv2.imshow("undistorted", undistorted_img)
# cv2.waitKey(0)
# cv2.destroyAllWindows()
cv2.imwrite('out_' + os.path.basename(img_path), undistorted_img)
if __name__ == '__main__':
for p in sys.argv[1:]:
undistort(p)
Exemple d'exécution