-
Notifications
You must be signed in to change notification settings - Fork 19
/
undistort.py
115 lines (95 loc) · 3.75 KB
/
undistort.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python
"""
image undistortion for cameras with calibration information.
reads distorted images and their calibration matrix and distortion coefficients
and writes undistorted photos
usage:
undistort.py --matrix <matrix path> --distortion <distortion path> <image path>
Code forked from Jan Erik Solem's blog:
http://www.janeriksolem.net/2014/05/how-to-calibrate-camera-with-opencv-and.html
"""
import numpy as np
import cv2
import glob
import os
import logging
import sys
import argparse
from subprocess import call
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Remove distortion from photos with previously '
'generated parameters')
parser.add_argument('images', help='path to images')
parser.add_argument('-m', '--matrix', required=True,
help='path to the matrix.txt file')
parser.add_argument('-d', '--distortion', required=True,
help='path to distortion matrix')
args = parser.parse_args()
# get image path
if os.path.isdir(args.images):
images_path = args.images
else:
logging.error('images path is not valid')
exit()
# get images in list
extensions = ['jpg', 'JPG', 'png']
images = [fn for fn in os.listdir(images_path)
if any(fn.endswith(ext) for ext in extensions)]
out_path = os.path.join(images_path, 'out')
# load parameters to np arrays
if os.path.isfile(args.matrix):
mpath = os.path.abspath(args.matrix)
K = np.loadtxt(mpath)
else:
logging.error('matrix path is not valid')
exit()
if os.path.isfile(args.distortion):
dpath = os.path.abspath(args.distortion)
d = np.loadtxt(dpath)
# d[2:] = 0 # We only need first two values
logging.info("Matrix: \n" + str(K))
logging.info("Distortion: " + str(d))
if not os.path.isdir(out_path):
os.mkdir(out_path)
logging.debug("Starting loop")
logging.debug("writing images to {0})".format(out_path))
# Check if images are all the same w/h
img = cv2.imread(os.path.join(images_path, images[0]))
h, w = img.shape[:2]
useRectMap = True
for image in images:
path = os.path.join(images_path, image)
img = cv2.imread(path)
h1, w1 = img.shape[:2]
if not (h == h1 and w == w1):
useRectMap = False
if useRectMap:
newcamera, roi = cv2.getOptimalNewCameraMatrix(K, d, (w, h), 0)
mapx, mapy = cv2.initUndistortRectifyMap(K, d, None, newcamera, (w, h), 5)
for image in images:
# logging.debug("var %s", image)
# imgname = os.path.split(image)[1]
logging.debug("Undistorting %s . . . ", image)
# read one of your images
path = os.path.join(images_path, image)
img = cv2.imread(path)
h, w = img.shape[:2]
# un-distort
if useRectMap:
newimg = cv2.remap(img, mapx, mapy, cv2.INTER_LINEAR)
else:
newcamera, roi = cv2.getOptimalNewCameraMatrix(K, d, (w, h), 0)
newimg = cv2.undistort(img, K, d, None, newcamera)
# TODO Write exif: camera maker, camera model, focal length?, GPS to new file
# cv2.imwrite("original.jpg", img)
newimg_path = os.path.join(out_path, image)
cv2.imwrite(newimg_path, newimg)
# Only works on linux
command = "exiftool -overwrite_original -TagsFromFile {0} -all:all {1}".format(os.path.abspath(path), os.path.abspath(newimg_path)).split(' ')
try:
logging.debug(command)
call(command)
except Exception as err:
logging.error("Failed to write to exif: {0}".format(err))