aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThéo de la Hogue2023-03-29 11:23:01 +0200
committerThéo de la Hogue2023-03-29 11:23:01 +0200
commit356863e1192805b74831c4424854784d29099ca2 (patch)
tree430e0d4b9d1b7d9008d102cbc113fee70814ea34 /src
parent3065391fd0defe0e0f70a1d4ab12630a81a85e25 (diff)
downloadargaze-356863e1192805b74831c4424854784d29099ca2.zip
argaze-356863e1192805b74831c4424854784d29099ca2.tar.gz
argaze-356863e1192805b74831c4424854784d29099ca2.tar.bz2
argaze-356863e1192805b74831c4424854784d29099ca2.tar.xz
Adding calibrate_camera.py script example.
Diffstat (limited to 'src')
-rw-r--r--src/argaze/ArUcoMarkers/utils/A3_DICT_APRILTAG_16h5_3cm_35cmx25cm.pdfbin0 -> 97542 bytes
-rw-r--r--src/argaze/ArUcoMarkers/utils/A3_DICT_ARUCO_ORIGINAL_3cm_35cmx25cm.pdfbin53854 -> 0 bytes
-rw-r--r--src/argaze/ArUcoMarkers/utils/A4_DICT_APRILTAG_16h5_5cm_0-7.pdfbin0 -> 37670 bytes
-rw-r--r--src/argaze/ArUcoMarkers/utils/A4_DICT_ARUCO_ORIGINAL_3cm_0-9.pdfbin26485 -> 0 bytes
-rw-r--r--src/argaze/utils/README.md15
-rw-r--r--src/argaze/utils/camera_calibrate.py116
6 files changed, 125 insertions, 6 deletions
diff --git a/src/argaze/ArUcoMarkers/utils/A3_DICT_APRILTAG_16h5_3cm_35cmx25cm.pdf b/src/argaze/ArUcoMarkers/utils/A3_DICT_APRILTAG_16h5_3cm_35cmx25cm.pdf
new file mode 100644
index 0000000..2adcee1
--- /dev/null
+++ b/src/argaze/ArUcoMarkers/utils/A3_DICT_APRILTAG_16h5_3cm_35cmx25cm.pdf
Binary files differ
diff --git a/src/argaze/ArUcoMarkers/utils/A3_DICT_ARUCO_ORIGINAL_3cm_35cmx25cm.pdf b/src/argaze/ArUcoMarkers/utils/A3_DICT_ARUCO_ORIGINAL_3cm_35cmx25cm.pdf
deleted file mode 100644
index 455fd4f..0000000
--- a/src/argaze/ArUcoMarkers/utils/A3_DICT_ARUCO_ORIGINAL_3cm_35cmx25cm.pdf
+++ /dev/null
Binary files differ
diff --git a/src/argaze/ArUcoMarkers/utils/A4_DICT_APRILTAG_16h5_5cm_0-7.pdf b/src/argaze/ArUcoMarkers/utils/A4_DICT_APRILTAG_16h5_5cm_0-7.pdf
new file mode 100644
index 0000000..fcf850d
--- /dev/null
+++ b/src/argaze/ArUcoMarkers/utils/A4_DICT_APRILTAG_16h5_5cm_0-7.pdf
Binary files differ
diff --git a/src/argaze/ArUcoMarkers/utils/A4_DICT_ARUCO_ORIGINAL_3cm_0-9.pdf b/src/argaze/ArUcoMarkers/utils/A4_DICT_ARUCO_ORIGINAL_3cm_0-9.pdf
deleted file mode 100644
index 03085f2..0000000
--- a/src/argaze/ArUcoMarkers/utils/A4_DICT_ARUCO_ORIGINAL_3cm_0-9.pdf
+++ /dev/null
Binary files differ
diff --git a/src/argaze/utils/README.md b/src/argaze/utils/README.md
index f91438f..719218d 100644
--- a/src/argaze/utils/README.md
+++ b/src/argaze/utils/README.md
@@ -8,22 +8,25 @@ Collection of ready-to-use commands based on ArGaze toolkit.
# ArUco Markers factory
-Export all markers from DICT_APRILTAG_16h5 dictionary as 5 cm pictures with 300 dpi resolution into an \_export/markers folder:
+Export all markers from *DICT_APRILTAG_16h5* dictionary as 5 cm pictures with 300 dpi resolution into an *\_export/markers* folder:
```
python ./src/argaze/utils/aruco_markers_dictionary_export.py DICT_APRILTAG_16h5 -s 5 -r 300 -o _export/markers
```
-Export a 7 columns and 5 rows calibration board made of 5cm squares with 3cm markers from DICT_APRILTAG_16h5 dictionary at 300 dpi into an \_export folder:
+Export a 7 columns and 5 rows calibration board made of 5cm squares with 3cm markers from *DICT_APRILTAG_16h5* dictionary at 300 dpi into an *\_export* folder:
```
python ./src/argaze/utils/aruco_calibration_board_export.py 7 5 5 3 DICT_APRILTAG_16h5 -r 300 -o _export
```
-# TODO: Camera calibration
+# Camera calibration
-Calibrate a network camera (-t IP_ADDRESS) using a 7 columns and 5 rows calibration board made of 5cm squares with 3cm markers from DICT_APRILTAG_16h5 dictionary. Then, export its optical parameters into an camera.json file:
+Calibrate a camera device (-d DEVICE) using a 7 columns and 5 rows calibration board made of 5cm squares with 3cm markers from *DICT_APRILTAG_16h5* dictionary. Then, export its optical parameters into an *camera.json* file:
```
-python ./src/argaze/utils/camera_calibrate.py 7 5 5 3 -t IP_ADDRESS -d DICT_APRILTAG_16h5 -o _export/camera.json
-``` \ No newline at end of file
+python ./src/argaze/utils/camera_calibrate.py 7 5 5 3 DICT_APRILTAG_16h5 -d DEVICE -o _export
+```
+
+.. note::
+ Use **A3_DICT_APRILTAG_16h5_3cm_35cmx25cm.pdf** file located in ./src/argaze/ArUcoMarkers/utils/ folder ready to be printed on A3 paper sheet. \ No newline at end of file
diff --git a/src/argaze/utils/camera_calibrate.py b/src/argaze/utils/camera_calibrate.py
new file mode 100644
index 0000000..f55f0ce
--- /dev/null
+++ b/src/argaze/utils/camera_calibrate.py
@@ -0,0 +1,116 @@
+#!/usr/bin/env python
+
+import argparse
+import os
+import time
+
+from argaze.ArUcoMarkers import ArUcoMarkersDictionary, ArUcoBoard, ArUcoDetector, ArUcoCamera
+
+import cv2
+
+def main():
+ """
+ Captures board pictures and finally outputs camera calibration data into a calibration.json file.
+
+ - Export and print a calibration board using aruco_calibration_board_export.py script.
+ - Place the calibration board face to the camera.
+ - Move the calibration board in a manner to view it entirely on screen in various configurations (orientation and distance):
+ The script will automatically take pictures. Do this step with a good lighting and a clear background.
+ - Once enough pictures have been captured (~20), press Esc key then, wait for the camera calibration processing.
+ - Finally, check rms parameter: it should be between 0. and 1. if the calibration succeeded (lower is better).
+
+ ### Reference:
+ - [Camera calibration using ArUco marker tutorial](https://automaticaddison.com/how-to-perform-camera-calibration-using-opencv/)
+ """
+
+ # Manage arguments
+ parser = argparse.ArgumentParser(description=main.__doc__.split('-')[0])
+ parser.add_argument('columns', metavar='COLS_NUMBER', type=int, default=7, help='expected board columns number')
+ parser.add_argument('rows', metavar='ROWS_NUMBER', type=int, default=5, help='expected board rows number')
+ parser.add_argument('square_size', metavar='SQUARE_SIZE', type=float, default=5, help='expected square size in cm')
+ parser.add_argument('marker_size', metavar='MARKER_SIZE', type=float, default=3, help='expected marker size in cm')
+ parser.add_argument('dictionary', metavar='DICTIONARY', type=ArUcoMarkersDictionary.ArUcoMarkersDictionary, default='DICT_ARUCO_ORIGINAL', help='expected dictionary name: DICT_4X4_50, DICT_4X4_100, DICT_4X4_250, DICT_4X4_1000, DICT_5X5_50, DICT_5X5_100, DICT_5X5_250, DICT_5X5_1000, DICT_6X6_50, DICT_6X6_100, DICT_6X6_250, DICT_6X6_1000, DICT_7X7_50, DICT_7X7_100, DICT_7X7_250, DICT_7X7_1000, DICT_ARUCO_ORIGINAL, DICT_APRILTAG_16h5, DICT_APRILTAG_25h9, DICT_APRILTAG_36h10, DICT_APRILTAG_36h11')
+
+ parser.add_argument('-d', '--device', metavar='DEVICE', type=int, default=0, help='video capture device id')
+ parser.add_argument('-o', '--output', metavar='OUT', type=str, default='.', help='destination folder filepath')
+ args = parser.parse_args()
+
+ # Enable camera video capture
+ video_capture = cv2.VideoCapture(args.device)
+
+ frame_width = int(video_capture.get(cv2.CAP_PROP_FRAME_WIDTH))
+ frame_height = int(video_capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
+
+ # Create aruco camera
+ aruco_camera = ArUcoCamera.ArUcoCamera(dimensions=(frame_width, frame_height))
+
+ # Create aruco board
+ aruco_board = ArUcoBoard.ArUcoBoard(args.columns, args.rows, args.square_size, args.marker_size, args.dictionary)
+
+ # Create aruco detector
+ aruco_detector = ArUcoDetector.ArUcoDetector(dictionary=args.dictionary, marker_size=args.marker_size)
+
+ print(f'{aruco_camera.dimensions[0]}x{aruco_camera.dimensions[1]} pixels camera calibration starts')
+ print("Waiting for calibration board...")
+
+ expected_markers_number = aruco_board.markers_number
+ expected_corners_number = aruco_board.corners_number
+
+ # Capture loop
+ try:
+
+ # Capture frames with a full displayed board inside
+ while video_capture.isOpened():
+
+ success, video_frame = video_capture.read()
+
+ if success:
+
+ # Detect calibration board
+ aruco_detector.detect_board(video_frame, aruco_board, expected_markers_number)
+
+ # Draw detected markers
+ aruco_detector.draw_detected_markers(video_frame)
+
+ # Draw current calibration data count
+ cv2.putText(video_frame, f'Capture: {aruco_camera.calibration_data_count}', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv2.LINE_AA)
+ cv2.imshow('Camera Calibration', video_frame)
+
+ # If all board corners are detected
+ if aruco_detector.board_corners_number == expected_corners_number:
+
+ # Draw board corners to notify a capture is done
+ aruco_detector.draw_board(video_frame)
+
+ # Append calibration data
+ aruco_camera.store_calibration_data(aruco_detector.board_corners, aruco_detector.board_corners_identifier)
+
+ cv2.imshow('Camera Calibration', video_frame)
+
+ # Stop calibration by pressing 'Esc' key
+ if cv2.waitKey(1) == 27:
+ break
+
+ # Stop calibration on 'ctrl+C' interruption
+ except KeyboardInterrupt:
+ pass
+
+ # Stop frame display
+ cv2.destroyAllWindows()
+
+ print('\nCalibrating camera...')
+ aruco_camera.calibrate(aruco_board)
+
+ print('\nCalibration succeeded!')
+ print(f'\nRMS:\n{aruco_camera.rms}')
+ print(f'\nDimensions:\n{frame_width}x{frame_height}')
+ print(f'\nCamera matrix:\n{aruco_camera.K}')
+ print(f'\nDistortion coefficients:\n{aruco_camera.D}')
+
+ aruco_camera.to_json(f'{args.output}/calibration.json')
+
+ print(f'\ncalibration.json file exported into {args.output} folder')
+
+if __name__ == '__main__':
+
+ main()