calibrate_camera_new.py 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. #!/usr/bin/python3
  2. """
  3. ~~~~~~~~~~~~~~~~~~
  4. Camera calibration
  5. ~~~~~~~~~~~~~~~~~~
  6. Usage:
  7. python calib.py \
  8. -i /dev/video0 \
  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 yaml
  19. import cv2
  20. import sys
  21. def main():
  22. parser = argparse.ArgumentParser()
  23. # parser.add_argument("-i", "--input", type=int, default=0,
  24. # help="input camera device")
  25. parser.add_argument("-grid", "--grid", default="10x7", help="size of the grid (rows x cols)")
  26. parser.add_argument("-framestep", type=int, default=20, help="use every nth frame in the video")
  27. parser.add_argument("-o", "--output", default="./yaml",
  28. help="path to output yaml file")
  29. # parser.add_argument("-resolution", "--resolution", default="640x480",
  30. # help="resolution of the camera")
  31. parser.add_argument("-fisheye", "--fisheye", default=True,action="store_true",
  32. help="set ture if this is a fisheye camera")
  33. args = parser.parse_args()
  34. cap = "v4l2src device=/dev/video0 ! video/x-raw, width=(int)1280, height=(int)720 ! videoconvert ! appsink"
  35. if not os.path.exists(args.output):
  36. os.mkdir(args.output)
  37. source = cv2.VideoCapture(cap)
  38. W=1280
  39. H=720
  40. source.set(3, W)
  41. source.set(4, H)
  42. grid_size = tuple(int(x) for x in args.grid.split("x"))
  43. grid_points = np.zeros((np.prod(grid_size), 3), np.float32)
  44. grid_points[:, :2] = np.indices(grid_size).T.reshape(-1, 2)
  45. objpoints = [] # 3d point in real world space
  46. imgpoints = [] # 2d points in image plane
  47. quit = False
  48. do_calib = False
  49. i = -1
  50. while True:
  51. i += 1
  52. retcode, img = source.read()
  53. # img= img[120:480, 240:880]
  54. # print(img.shape)
  55. W,H,_ = img.shape
  56. if not retcode:
  57. raise ValueError("cannot read frame from video")
  58. if i % args.framestep != 0:
  59. continue
  60. print("searching for chessboard corners in frame " + str(i) + "...")
  61. gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  62. found, corners = cv2.findChessboardCorners(
  63. gray,
  64. grid_size,
  65. cv2.CALIB_CB_ADAPTIVE_THRESH +
  66. cv2.CALIB_CB_NORMALIZE_IMAGE +
  67. cv2.CALIB_CB_FILTER_QUADS
  68. )
  69. if found:
  70. term = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.01)
  71. cv2.cornerSubPix(gray, corners, (5, 5), (-1, -1), term)
  72. print("OK")
  73. imgpoints.append(corners.reshape(1, -1, 2))
  74. objpoints.append(grid_points.reshape(1, -1, 3))
  75. cv2.drawChessboardCorners(img, grid_size, corners, found)
  76. text1 = "press c to calibrate"
  77. text2 = "press q to quit"
  78. text3 = "device: {}".format(cap)
  79. fontscale = 0.6
  80. cv2.putText(img, text1, (20, 70), cv2.FONT_HERSHEY_SIMPLEX, fontscale, (255, 200, 0), 2)
  81. cv2.putText(img, text2, (20, 110), cv2.FONT_HERSHEY_SIMPLEX, fontscale, (255, 200, 0), 2)
  82. cv2.putText(img, text3, (20, 30), cv2.FONT_HERSHEY_SIMPLEX, fontscale, (255, 200, 0), 2)
  83. cv2.imshow("corners", img)
  84. print("\nPerforming calibration...\n")
  85. N_OK = len(objpoints)
  86. if N_OK > 12:
  87. print("More than 12 corners detected")
  88. K = np.zeros((3, 3))
  89. D = np.zeros((4, 1))
  90. rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
  91. tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
  92. calibration_flags = (cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC +
  93. cv2.fisheye.CALIB_CHECK_COND +
  94. cv2.fisheye.CALIB_FIX_SKEW)
  95. try:
  96. ret, K, D, rvecs, tvecs = cv2.fisheye.calibrate(
  97. objpoints,
  98. imgpoints,
  99. (W, H),
  100. K,
  101. D,
  102. rvecs,
  103. tvecs,
  104. calibration_flags,
  105. (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-5)
  106. )
  107. break
  108. except:
  109. objpoints = []
  110. imgpoints = []
  111. print("Do not press C!!!!")
  112. key = cv2.waitKey(1) & 0xFF
  113. if key == ord("c"):
  114. do_calib = True
  115. break
  116. elif key == ord("q"):
  117. quit = True
  118. break
  119. if quit:
  120. source.release()
  121. cv2.destroyAllWindows()
  122. if do_calib:
  123. print("\nPerforming calibration...\n")
  124. N_OK = len(objpoints)
  125. if N_OK < 12:
  126. print("Less than 12 corners detected, calibration failed")
  127. return
  128. K = np.zeros((3, 3))
  129. D = np.zeros((4, 1))
  130. rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
  131. tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for _ in range(N_OK)]
  132. calibration_flags = (cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC +
  133. cv2.fisheye.CALIB_CHECK_COND +
  134. cv2.fisheye.CALIB_FIX_SKEW)
  135. # 求出内参矩阵和畸变系数
  136. if True:
  137. ret, K, D, rvecs, tvecs = cv2.fisheye.calibrate(
  138. objpoints,
  139. imgpoints,
  140. (W, H),
  141. K,
  142. D,
  143. rvecs,
  144. tvecs,
  145. calibration_flags,
  146. (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-5)
  147. )
  148. else:
  149. ret, K, D, rvecs, tvecs = cv2.calibrateCamera(
  150. objpoints,
  151. imgpoints,
  152. (W, H),
  153. None,
  154. None)
  155. if ret:
  156. print(ret)
  157. print(K)
  158. data = {"dim": np.array([W, H]).tolist(), "K": K.tolist(), "D": D.tolist()}
  159. fname = "./yaml/camera147.yaml"
  160. print(fname)
  161. with open(fname, "w") as f:
  162. yaml.safe_dump(data,f)
  163. print("succesfully saved camera data")
  164. cv2.putText(img, "Success!", (220 , 240), cv2.FONT_HERSHEY_COMPLEX, 2, (0, 0, 255), 2)
  165. else:
  166. cv2.putText(img, "Failed!", (220, 240), cv2.FONT_HERSHEY_COMPLEX, 2, (0, 0, 255), 2)
  167. cv2.imshow("corners", img)
  168. cv2.waitKey(0)
  169. if __name__ == "__main__":
  170. main()