Skip to content

Commit 49cb230

Browse files
valgurSteveMacenski
authored andcommitted
camera_calibration: Improve YAML formatting, make config dumping methods static (#438)
* Add `from __future__ import print_function` Makes sure the printed output looks as expected, rather than e.g. ('D = ', [0.8272, ...]) on Python 2. * Improve YAML formatting, make some methods static * Improves matrix formatting in YAML, for example: data: [502.99207, 0. , 250.22621, 0. , 503.22066, 245.98286, 0. , 0. , 1. ] * Reduced decimal figures for camera and projection matrix values from 8 to 5. * Making the methods static allows them to be used from elsewhere as well to dump calibration info.
1 parent f1de5b0 commit 49cb230

File tree

6 files changed

+98
-79
lines changed

6 files changed

+98
-79
lines changed

camera_calibration/nodes/cameracalibrator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@
3232
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3333
# POSSIBILITY OF SUCH DAMAGE.
3434

35+
from __future__ import print_function
3536
import cv2
3637
import functools
3738
import message_filters
38-
import os
3939
import rospy
4040
from camera_calibration.camera_calibrator import OpenCVCalibrationNode
4141
from camera_calibration.calibrator import ChessboardInfo, Patterns

camera_calibration/scripts/tarfile_calibration.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,8 @@
3232
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3333
# POSSIBILITY OF SUCH DAMAGE.
3434

35+
from __future__ import print_function
3536
import os
36-
import sys
3737
import numpy
3838

3939
import cv2

camera_calibration/src/camera_calibration/calibrator.py

Lines changed: 93 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3333
# POSSIBILITY OF SUCH DAMAGE.
3434

35+
from __future__ import print_function
3536
try:
3637
from cStringIO import StringIO
3738
except ImportError:
@@ -452,10 +453,11 @@ def downsample_and_detect(self, img):
452453
return (scrib, corners, downsampled_corners, board, (x_scale, y_scale))
453454

454455

455-
def lrmsg(self, d, k, r, p):
456+
@staticmethod
457+
def lrmsg(d, k, r, p, size):
456458
""" Used by :meth:`as_message`. Return a CameraInfo message for the given calibration matrices """
457459
msg = sensor_msgs.msg.CameraInfo()
458-
(msg.width, msg.height) = self.size
460+
msg.width, msg.height = size
459461
if d.size > 5:
460462
msg.distortion_model = "rational_polynomial"
461463
else:
@@ -466,71 +468,88 @@ def lrmsg(self, d, k, r, p):
466468
msg.P = numpy.ravel(p).copy().tolist()
467469
return msg
468470

469-
def lrreport(self, d, k, r, p):
470-
print("D = ", numpy.ravel(d).tolist())
471-
print("K = ", numpy.ravel(k).tolist())
472-
print("R = ", numpy.ravel(r).tolist())
473-
print("P = ", numpy.ravel(p).tolist())
474-
475-
def lrost(self, name, d, k, r, p):
476-
calmessage = (
477-
"# oST version 5.0 parameters\n"
478-
+ "\n"
479-
+ "\n"
480-
+ "[image]\n"
481-
+ "\n"
482-
+ "width\n"
483-
+ str(self.size[0]) + "\n"
484-
+ "\n"
485-
+ "height\n"
486-
+ str(self.size[1]) + "\n"
487-
+ "\n"
488-
+ "[%s]" % name + "\n"
489-
+ "\n"
490-
+ "camera matrix\n"
491-
+ " ".join(["%8f" % k[0,i] for i in range(3)]) + "\n"
492-
+ " ".join(["%8f" % k[1,i] for i in range(3)]) + "\n"
493-
+ " ".join(["%8f" % k[2,i] for i in range(3)]) + "\n"
494-
+ "\n"
495-
+ "distortion\n"
496-
+ " ".join("%8f" % x for x in d.flat) + "\n"
497-
+ "\n"
498-
+ "rectification\n"
499-
+ " ".join(["%8f" % r[0,i] for i in range(3)]) + "\n"
500-
+ " ".join(["%8f" % r[1,i] for i in range(3)]) + "\n"
501-
+ " ".join(["%8f" % r[2,i] for i in range(3)]) + "\n"
502-
+ "\n"
503-
+ "projection\n"
504-
+ " ".join(["%8f" % p[0,i] for i in range(4)]) + "\n"
505-
+ " ".join(["%8f" % p[1,i] for i in range(4)]) + "\n"
506-
+ " ".join(["%8f" % p[2,i] for i in range(4)]) + "\n"
507-
+ "\n")
471+
@staticmethod
472+
def lrreport(d, k, r, p):
473+
print("D =", numpy.ravel(d).tolist())
474+
print("K =", numpy.ravel(k).tolist())
475+
print("R =", numpy.ravel(r).tolist())
476+
print("P =", numpy.ravel(p).tolist())
477+
478+
@staticmethod
479+
def lrost(name, d, k, r, p, size):
480+
assert k.shape == (3, 3)
481+
assert r.shape == (3, 3)
482+
assert p.shape == (3, 4)
483+
calmessage = "\n".join([
484+
"# oST version 5.0 parameters",
485+
"",
486+
"",
487+
"[image]",
488+
"",
489+
"width",
490+
"%d" % size[0],
491+
"",
492+
"height",
493+
"%d" % size[1],
494+
"",
495+
"[%s]" % name,
496+
"",
497+
"camera matrix",
498+
" ".join("%8f" % k[0,i] for i in range(3)),
499+
" ".join("%8f" % k[1,i] for i in range(3)),
500+
" ".join("%8f" % k[2,i] for i in range(3)),
501+
"",
502+
"distortion",
503+
" ".join("%8f" % x for x in d.flat),
504+
"",
505+
"rectification",
506+
" ".join("%8f" % r[0,i] for i in range(3)),
507+
" ".join("%8f" % r[1,i] for i in range(3)),
508+
" ".join("%8f" % r[2,i] for i in range(3)),
509+
"",
510+
"projection",
511+
" ".join("%8f" % p[0,i] for i in range(4)),
512+
" ".join("%8f" % p[1,i] for i in range(4)),
513+
" ".join("%8f" % p[2,i] for i in range(4)),
514+
""
515+
])
508516
assert len(calmessage) < 525, "Calibration info must be less than 525 bytes"
509517
return calmessage
510518

511-
def lryaml(self, name, d, k, r, p):
512-
calmessage = (""
513-
+ "image_width: " + str(self.size[0]) + "\n"
514-
+ "image_height: " + str(self.size[1]) + "\n"
515-
+ "camera_name: " + name + "\n"
516-
+ "camera_matrix:\n"
517-
+ " rows: 3\n"
518-
+ " cols: 3\n"
519-
+ " data: [" + ", ".join("%8f" % x for x in k.flat) + "]\n"
520-
+ "distortion_model: " + ("rational_polynomial" if d.size > 5 else "plumb_bob") + "\n"
521-
+ "distortion_coefficients:\n"
522-
+ " rows: 1\n"
523-
+ " cols: %d\n" % d.size
524-
+ " data: [" + ", ".join("%8f" % x for x in d.flat) + "]\n"
525-
+ "rectification_matrix:\n"
526-
+ " rows: 3\n"
527-
+ " cols: 3\n"
528-
+ " data: [" + ", ".join("%8f" % x for x in r.flat) + "]\n"
529-
+ "projection_matrix:\n"
530-
+ " rows: 3\n"
531-
+ " cols: 4\n"
532-
+ " data: [" + ", ".join("%8f" % x for x in p.flat) + "]\n"
533-
+ "")
519+
@staticmethod
520+
def lryaml(name, d, k, r, p, size):
521+
def format_mat(x, precision):
522+
return ("[%s]" % (
523+
numpy.array2string(x, precision=precision, suppress_small=True, separator=", ")
524+
.replace("[", "").replace("]", "").replace("\n", "\n ")
525+
))
526+
527+
assert k.shape == (3, 3)
528+
assert r.shape == (3, 3)
529+
assert p.shape == (3, 4)
530+
calmessage = "\n".join([
531+
"image_width: %d" % size[0],
532+
"image_height: %d" % size[1],
533+
"camera_name: " + name,
534+
"camera_matrix:",
535+
" rows: 3",
536+
" cols: 3",
537+
" data: " + format_mat(k, 5),
538+
"distortion_model: " + ("rational_polynomial" if d.size > 5 else "plumb_bob"),
539+
"distortion_coefficients:",
540+
" rows: 1",
541+
" cols: %d" % d.size,
542+
" data: [%s]" % ", ".join("%8f" % x for x in d.flat),
543+
"rectification_matrix:",
544+
" rows: 3",
545+
" cols: 3",
546+
" data: " + format_mat(r, 8),
547+
"projection_matrix:",
548+
" rows: 3",
549+
" cols: 4",
550+
" data: " + format_mat(p, 5),
551+
""
552+
])
534553
return calmessage
535554

536555
def do_save(self):
@@ -685,7 +704,7 @@ def undistort_points(self, src):
685704

686705
def as_message(self):
687706
""" Return the camera calibration as a CameraInfo message """
688-
return self.lrmsg(self.distortion, self.intrinsics, self.R, self.P)
707+
return self.lrmsg(self.distortion, self.intrinsics, self.R, self.P, self.size)
689708

690709
def from_message(self, msg, alpha = 0.0):
691710
""" Initialize the camera calibration from a CameraInfo message """
@@ -702,10 +721,10 @@ def report(self):
702721
self.lrreport(self.distortion, self.intrinsics, self.R, self.P)
703722

704723
def ost(self):
705-
return self.lrost(self.name, self.distortion, self.intrinsics, self.R, self.P)
724+
return self.lrost(self.name, self.distortion, self.intrinsics, self.R, self.P, self.size)
706725

707726
def yaml(self):
708-
return self.lryaml(self.name, self.distortion, self.intrinsics, self.R, self.P)
727+
return self.lryaml(self.name, self.distortion, self.intrinsics, self.R, self.P, self.size)
709728

710729
def linear_error_from_image(self, image):
711730
"""
@@ -966,8 +985,8 @@ def as_message(self):
966985
and right cameras respectively.
967986
"""
968987

969-
return (self.lrmsg(self.l.distortion, self.l.intrinsics, self.l.R, self.l.P),
970-
self.lrmsg(self.r.distortion, self.r.intrinsics, self.r.R, self.r.P))
988+
return (self.lrmsg(self.l.distortion, self.l.intrinsics, self.l.R, self.l.P, self.size),
989+
self.lrmsg(self.r.distortion, self.r.intrinsics, self.r.R, self.r.P, self.size))
971990

972991
def from_message(self, msgs, alpha = 0.0):
973992
""" Initialize the camera calibration from a pair of CameraInfo messages. """
@@ -987,15 +1006,15 @@ def report(self):
9871006
self.lrreport(self.l.distortion, self.l.intrinsics, self.l.R, self.l.P)
9881007
print("\nRight:")
9891008
self.lrreport(self.r.distortion, self.r.intrinsics, self.r.R, self.r.P)
990-
print("self.T ", numpy.ravel(self.T).tolist())
991-
print("self.R ", numpy.ravel(self.R).tolist())
1009+
print("self.T =", numpy.ravel(self.T).tolist())
1010+
print("self.R =", numpy.ravel(self.R).tolist())
9921011

9931012
def ost(self):
994-
return (self.lrost(self.name + "/left", self.l.distortion, self.l.intrinsics, self.l.R, self.l.P) +
995-
self.lrost(self.name + "/right", self.r.distortion, self.r.intrinsics, self.r.R, self.r.P))
1013+
return (self.lrost(self.name + "/left", self.l.distortion, self.l.intrinsics, self.l.R, self.l.P, self.size) +
1014+
self.lrost(self.name + "/right", self.r.distortion, self.r.intrinsics, self.r.R, self.r.P, self.size))
9961015

9971016
def yaml(self, suffix, info):
998-
return self.lryaml(self.name + suffix, info.distortion, info.intrinsics, info.R, info.P)
1017+
return self.lryaml(self.name + suffix, info.distortion, info.intrinsics, info.R, info.P, self.size)
9991018

10001019
# TODO Get rid of "from_images" versions of these, instead have function to get undistorted corners
10011020
def epipolar_error_from_images(self, limage, rimage):

camera_calibration/src/camera_calibration/camera_calibrator.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3333
# POSSIBILITY OF SUCH DAMAGE.
3434

35+
from __future__ import print_function
3536
import cv2
3637
import message_filters
3738
import numpy

camera_calibration/src/camera_calibration/camera_checker.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3333
# POSSIBILITY OF SUCH DAMAGE.
3434

35+
from __future__ import print_function
3536
import cv2
3637
import cv_bridge
3738
import functools

camera_calibration/test/directed.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,14 @@
3232
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3333
# POSSIBILITY OF SUCH DAMAGE.
3434

35+
from __future__ import print_function
3536
import roslib
3637
import rosunit
37-
import rospy
3838
import cv2
3939

4040
import collections
4141
import copy
4242
import numpy
43-
import os
44-
import sys
4543
import tarfile
4644
import unittest
4745

0 commit comments

Comments
 (0)