Skip to content

Commit 4f6f419

Browse files
committed
add all code
1 parent 598d813 commit 4f6f419

26 files changed

+665
-369
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
项目正在进行一次比较大的更新,预计本月内全部完成,请耐心等候几天
1+
全部代码已上传完成,文档正在写作中

get_projection_maps.py

Lines changed: 0 additions & 65 deletions
This file was deleted.

get_weight_matrices.py

Lines changed: 0 additions & 31 deletions
This file was deleted.

images/res.png

115 KB
Loading

run_calibrate_camera.py

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
"""
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Fisheye Camera calibration
4+
~~~~~~~~~~~~~~~~~~~~~~~~~~
5+
6+
Usage:
7+
python calibrate_camera.py \
8+
-i 0 \
9+
-grid 9x6 \
10+
-out fisheye.yaml \
11+
-framestep 20 \
12+
-resolution 640x480
13+
--fisheye
14+
"""
15+
import argparse
16+
import os
17+
import numpy as np
18+
import cv2
19+
from surround_view import CaptureThread, MultiBufferManager
20+
import surround_view.utils as utils
21+
22+
23+
# we will save the camera param file to this directory
24+
TARGET_DIR = os.path.join(os.getcwd(), "yaml")
25+
26+
# default param file
27+
DEFAULT_PARAM_FILE = os.path.join(TARGET_DIR, "camera_params.yaml")
28+
29+
30+
def main():
31+
parser = argparse.ArgumentParser()
32+
33+
# input video stream
34+
parser.add_argument("-i", "--input", type=int, default=0,
35+
help="input camera device")
36+
37+
# chessboard pattern size
38+
parser.add_argument("-grid", "--grid", default="9x6",
39+
help="size of the calibrate grid pattern")
40+
41+
parser.add_argument("-framestep", type=int, default=20,
42+
help="use every nth frame in the video")
43+
44+
parser.add_argument("-o", "--output", default=DEFAULT_PARAM_FILE,
45+
help="path to output yaml file")
46+
47+
parser.add_argument("-fisheye", "--fisheye", action="store_true",
48+
help="set ture if this is a fisheye camera")
49+
50+
parser.add_argument("-flip", "--flip", default=0, type=int,
51+
help="flip method of the camera")
52+
53+
args = parser.parse_args()
54+
55+
if not os.path.exists(TARGET_DIR):
56+
os.mkdir(TARGET_DIR)
57+
58+
text1 = "press c to calibrate"
59+
text2 = "press q to quit"
60+
text3 = "device: {}".format(args.input)
61+
font = cv2.FONT_HERSHEY_SIMPLEX
62+
fontscale = 0.6
63+
64+
grid_size = tuple(int(x) for x in args.grid.split("x"))
65+
grid_points = np.zeros((1, np.prod(grid_size), 3), np.float32)
66+
grid_points[0, :, :2] = np.indices(grid_size).T.reshape(-1, 2)
67+
68+
objpoints = [] # 3d point in real world space
69+
imgpoints = [] # 2d points in image plane
70+
71+
device = args.input
72+
cap_thread = CaptureThread(device_id=device,
73+
flip_method=args.flip)
74+
buffer_manager = MultiBufferManager()
75+
buffer_manager.bind_thread(cap_thread, buffer_size=8)
76+
if cap_thread.connect_camera():
77+
cap_thread.start()
78+
else:
79+
print("cannot open device")
80+
return
81+
82+
quit = False
83+
do_calib = False
84+
i = -1
85+
while True:
86+
i += 1
87+
img = buffer_manager.get_device(device).get().image
88+
if i % args.framestep != 0:
89+
continue
90+
91+
print("searching for chessboard corners in frame " + str(i) + "...")
92+
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
93+
found, corners = cv2.findChessboardCorners(
94+
gray,
95+
grid_size,
96+
cv2.CALIB_CB_ADAPTIVE_THRESH +
97+
cv2.CALIB_CB_NORMALIZE_IMAGE +
98+
cv2.CALIB_CB_FILTER_QUADS
99+
)
100+
if found:
101+
term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.01)
102+
cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), term)
103+
print("OK")
104+
imgpoints.append(corners)
105+
objpoints.append(grid_points)
106+
cv2.drawChessboardCorners(img, grid_size, corners, found)
107+
108+
cv2.putText(img, text1, (20, 70), font, fontscale, (255, 200, 0), 2)
109+
cv2.putText(img, text2, (20, 110), font, fontscale, (255, 200, 0), 2)
110+
cv2.putText(img, text3, (20, 30), font, fontscale, (255, 200, 0), 2)
111+
cv2.imshow("corners", img)
112+
key = cv2.waitKey(1) & 0xFF
113+
if key == ord("c"):
114+
do_calib = True
115+
break
116+
117+
elif key == ord("q"):
118+
quit = True
119+
break
120+
121+
if quit:
122+
cap_thread.stop()
123+
cap_thread.disconnect_camera()
124+
cv2.destroyAllWindows()
125+
126+
if do_calib:
127+
print("\nPerforming calibration...\n")
128+
N_OK = len(objpoints)
129+
if N_OK < 12:
130+
print("Less than 12 corners detected, calibration failed")
131+
return
132+
133+
K = np.zeros((3, 3))
134+
D = np.zeros((4, 1))
135+
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
136+
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
137+
calibration_flags = (cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC +
138+
cv2.fisheye.CALIB_CHECK_COND +
139+
cv2.fisheye.CALIB_FIX_SKEW)
140+
141+
if args.fisheye:
142+
ret, mtx, dist, rvecs, tvecs = cv2.fisheye.calibrate(
143+
objpoints,
144+
imgpoints,
145+
(W, H),
146+
K,
147+
D,
148+
rvecs,
149+
tvecs,
150+
calibration_flags,
151+
(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6)
152+
)
153+
else:
154+
ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera(
155+
objpoints,
156+
imgpoints,
157+
(W, H),
158+
None,
159+
None)
160+
161+
if ret:
162+
fs = cv2.FileStorage(args.output, cv2.FILE_STORAGE_WRITE)
163+
fs.write("resolution", np.int32([W, H]))
164+
fs.write("camera_matrix", K)
165+
fs.write("dist_coeffs", D)
166+
fs.release()
167+
print("succesfully saved camera data")
168+
cv2.putText(img, "Success!", (220, 240), font, 2, (0, 0, 255), 2)
169+
170+
else:
171+
cv2.putText(img, "Failed!", (220, 240), font, 2, (0, 0, 255), 2)
172+
173+
cv2.imshow("corners", img)
174+
cv2.waitKey(0)
175+
176+
177+
if __name__ == "__main__":
178+
main()

run_get_projection_maps.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
"""
2+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3+
Manually select points to get the projection map
4+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5+
"""
6+
import argparse
7+
import os
8+
import numpy as np
9+
import cv2
10+
from surround_view import FisheyeCameraModel, PointSelector, display_image
11+
import surround_view.param_settings as settings
12+
13+
14+
def get_projection_map(camera_model, image):
15+
und_image = camera_model.undistort(image)
16+
name = camera_model.camera_name
17+
gui = PointSelector(und_image, title=name)
18+
dst_points = settings.project_keypoints[name]
19+
choice = gui.loop()
20+
if choice > 0:
21+
src = np.float32(gui.keypoints)
22+
dst = np.float32(dst_points)
23+
camera_model.project_matrix = cv2.getPerspectiveTransform(src, dst)
24+
proj_image = camera_model.project(image)
25+
26+
ret = display_image("Bird's View", proj_image)
27+
if ret > 0:
28+
return True
29+
if ret < 0:
30+
cv2.destroyAllWindows()
31+
32+
return False
33+
34+
35+
def main():
36+
parser = argparse.ArgumentParser()
37+
parser.add_argument("-camera", required=True,
38+
choices=["front", "back", "left", "right"],
39+
help="The camera view to be projected")
40+
parser.add_argument("-scale", nargs="+", default=None,
41+
help="scale the undistorted image")
42+
parser.add_argument("-shift", nargs="+", default=None,
43+
help="shift the undistorted image")
44+
args = parser.parse_args()
45+
46+
if args.scale is not None:
47+
scale = [float(x) for x in args.scale]
48+
else:
49+
scale = (1.0, 1.0)
50+
51+
if args.shift is not None:
52+
shift = [float(x) for x in args.shift]
53+
else:
54+
shift = (0, 0)
55+
56+
camera_name = args.camera
57+
camera_file = os.path.join(os.getcwd(), "yaml", camera_name + ".yaml")
58+
image_file = os.path.join(os.getcwd(), "images", camera_name + ".png")
59+
image = cv2.imread(image_file)
60+
camera = FisheyeCameraModel(camera_file, camera_name)
61+
camera.set_scale_and_shift(scale, shift)
62+
success = get_projection_map(camera, image)
63+
if success:
64+
print("saving projection matrix to yaml")
65+
camera.save_data()
66+
else:
67+
print("failed to compute the projection map")
68+
69+
70+
if __name__ == "__main__":
71+
main()

run_get_weight_matrices.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import os
2+
import numpy as np
3+
import cv2
4+
from PIL import Image
5+
from surround_view import FisheyeCameraModel, display_image, BirdView
6+
import surround_view.param_settings as settings
7+
8+
9+
def main():
10+
names = settings.camera_names
11+
images = [os.path.join(os.getcwd(), "images", name + ".png") for name in names]
12+
yamls = [os.path.join(os.getcwd(), "yaml", name + ".yaml") for name in names]
13+
camera_models = [FisheyeCameraModel(camera_file, camera_name) for camera_file, camera_name in zip (yamls, names)]
14+
15+
projected = []
16+
for image_file, camera in zip(images, camera_models):
17+
img = cv2.imread(image_file)
18+
img = camera.undistort(img)
19+
img = camera.project(img)
20+
img = camera.flip(img)
21+
projected.append(img)
22+
23+
birdview = BirdView()
24+
Gmat, Mmat = birdview.get_weights_and_masks(projected)
25+
birdview.update_frames(projected)
26+
birdview.make_luminance_balance().stitch_all_parts()
27+
birdview.make_white_balance()
28+
birdview.copy_car_image()
29+
ret = display_image("BirdView Result", birdview.image)
30+
if ret > 0:
31+
Image.fromarray((Gmat * 255).astype(np.uint8)).save("weights.png")
32+
Image.fromarray(Mmat.astype(np.uint8)).save("masks.png")
33+
34+
35+
if __name__ == "__main__":
36+
main()

0 commit comments

Comments
 (0)