Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkCameraIntrinsics.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 #include "mitkCameraIntrinsics.h"
18 #include <itkMutexLockHolder.h>
19 #include <mitkEndoMacros.h>
20 #include <mitkEndoDebug.h>
21 
23  : m_Valid(false), m_Mutex(itk::FastMutexLock::New())
24 {
25  m_CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType<double>::type);
26  m_CameraMatrix.at<double>(2,2) = 1.0;
27  m_DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType<double>::type);
28 }
29 
31  : itk::Object()
33  , m_Valid(false)
34  , m_Mutex(itk::FastMutexLock::New())
35 {
36  this->Copy(&other);
37 }
38 
40 {
41 
42 }
43 
45 {
46  return other->GetDistorsionCoeffsAsPoint4D()==
47  this->GetDistorsionCoeffsAsPoint4D() &&
48  other->GetFocalPoint()==
49  this->GetFocalPoint() &&
50  other->GetPrincipalPoint()
51  == this->GetPrincipalPoint();
52 }
53 
55 {
56  this->SetIntrinsics( other->GetCameraMatrix().clone()
57  , other->GetDistorsionCoeffs().clone() );
58  this->SetValid(other->m_Valid);
59 }
60 
62 {
64  return m_Valid;
65 }
66 
67 vnl_matrix_fixed<mitk::ScalarType, 3, 3>
69 {
70  vnl_matrix_fixed<mitk::ScalarType, 3, 3> mat;
71  mat.set_identity();
72 
73  {
75  mat(0,0) = m_CameraMatrix.at<double>(0,0);
76  mat(1,1) = m_CameraMatrix.at<double>(1,1);
77 
78  mat(0,2) = m_CameraMatrix.at<double>(0,2);
79  mat(1,2) = m_CameraMatrix.at<double>(1,2);
80  }
81 
82  return mat;
83 }
84 
86  const vnl_matrix_fixed<mitk::ScalarType, 3, 3>& _CameraMatrix )
87 {
89  m_CameraMatrix.at<double>(0,0) = _CameraMatrix(0,0);
90  m_CameraMatrix.at<double>(1,1) = _CameraMatrix(1,1);
91 
92  m_CameraMatrix.at<double>(0,2) = _CameraMatrix(0,2);
93  m_CameraMatrix.at<double>(1,2) = _CameraMatrix(1,2);
94 }
95 
96 vnl_matrix_fixed<mitk::ScalarType, 3, 4>
98 {
99  vnl_matrix_fixed<mitk::ScalarType, 3, 4> mat;
100  mat.fill(0);
101  mat.update( this->GetVnlCameraMatrix().as_matrix() );
102 
103  return mat;
104 }
105 
106 void mitk::CameraIntrinsics::SetIntrinsics( const cv::Mat& _CameraMatrix
107  , const cv::Mat& _DistorsionCoeffs)
108 {
109  {
111  if( _CameraMatrix.cols != 3 || _CameraMatrix.rows != 3)
112  throw std::invalid_argument("Wrong format of camera matrix. Should be 3x3"
113  " double.");
114 
115  endoAssertMsg( (_DistorsionCoeffs.cols == 5) &&
116  _DistorsionCoeffs.rows == 1, "Wrong format of distorsion coefficients"
117  " vector. Should be 5x1 double.");
118 
119  m_CameraMatrix = _CameraMatrix.clone();
120  m_DistorsionCoeffs = _DistorsionCoeffs.clone();
121 
122  m_Valid = true;
123  }
124  this->Modified();
125 }
126 
128  const mitk::Point3D& principalPoint,
129  const mitk::Point4D& distortionCoefficients)
130 
131 {
132  {
134  m_CameraMatrix.at<double>(0,0) = focalPoint[0];
135  m_CameraMatrix.at<double>(1,1) = focalPoint[1];
136 
137  m_CameraMatrix.at<double>(0,2) = principalPoint[0];
138  m_CameraMatrix.at<double>(1,2) = principalPoint[1];
139 
140  m_DistorsionCoeffs.at<double>(0,0) = distortionCoefficients[0];
141  m_DistorsionCoeffs.at<double>(0,1) = distortionCoefficients[1];
142  m_DistorsionCoeffs.at<double>(0,2) = distortionCoefficients[2];
143  m_DistorsionCoeffs.at<double>(0,3) = distortionCoefficients[3];
144  }
145  this->Modified();
146 }
147 
148 void mitk::CameraIntrinsics::SetFocalLength( double x, double y )
149 {
150  {
152  m_CameraMatrix.at<double>(0,0) = x;
153  m_CameraMatrix.at<double>(1,1) = y;
154  }
155  this->Modified();
156 }
157 
159 {
160  {
162  m_CameraMatrix.at<double>(0,2) = x;
163  m_CameraMatrix.at<double>(1,2) = y;
164  }
165  this->Modified();
166 }
167 
169  double p1, double p2 )
170 {
171 
172  {
174 
175  m_DistorsionCoeffs.at<double>(0,0) = k1;
176  m_DistorsionCoeffs.at<double>(0,1) = k2;
177  m_DistorsionCoeffs.at<double>(0,2) = p1;
178  m_DistorsionCoeffs.at<double>(0,3) = p2;
179  }
180  this->Modified();
181 }
182 
184 {
186  return m_CameraMatrix.clone(); // return a copy of this small matrix
187 }
188 
190 {
192  return m_DistorsionCoeffs.clone(); // return a copy of this small matrix
193 }
194 
196 {
197  const CameraIntrinsics* intrinsics = this;
198  return intrinsics->GetDistorsionCoeffs();
199 }
200 
202 {
204  std::ostringstream s; s.precision(12);
205  const cv::Mat& CameraMatrix = m_CameraMatrix;
206  const cv::Mat& DistorsionCoeffs = m_DistorsionCoeffs;
207 
208  s.str(""); s << this->GetNameOfClass() << ": ";
209  s << "fx = " << CameraMatrix.at<double>(0,0);
210  s << ", fy = " << CameraMatrix.at<double>(1,1);
211  s << ", cx = " << CameraMatrix.at<double>(0,2);
212  s << ", cy = " << CameraMatrix.at<double>(1,2);
213 
214  s << ", k1 = " << DistorsionCoeffs.at<double>(0,0);
215  s << ", k2 = " << DistorsionCoeffs.at<double>(0,1);
216  s << ", p1 = " << DistorsionCoeffs.at<double>(0,2);
217  s << ", p2 = " << DistorsionCoeffs.at<double>(0,3);
218  //s << ", k3 = " << DistorsionCoeffs.at<double>(0,4);
219 
220  return s.str();
221 }
222 
223 void mitk::CameraIntrinsics::ToXML(TiXmlElement* elem) const
224 {
226  elem->SetValue(this->GetNameOfClass());
227  std::ostringstream s; s.precision(12);
228  const cv::Mat& CameraMatrix = m_CameraMatrix;
229  s.str(""); s << CameraMatrix.at<double>(0,0);
230  elem->SetAttribute( "fx", s.str() );
231  s.str(""); s << CameraMatrix.at<double>(1,1);
232  elem->SetAttribute( "fy", s.str() );
233  s.str(""); s << CameraMatrix.at<double>(0,2);
234  elem->SetAttribute( "cx", s.str() );
235  s.str(""); s << CameraMatrix.at<double>(1,2);
236  elem->SetAttribute( "cy", s.str() );
237 
238  const cv::Mat& DistorsionCoeffs = m_DistorsionCoeffs;
239  s.str(""); s << DistorsionCoeffs.at<double>(0,0);
240  elem->SetAttribute( "k1", s.str() );
241  s.str(""); s << DistorsionCoeffs.at<double>(0,1);
242  elem->SetAttribute( "k2", s.str() );
243  s.str(""); s << DistorsionCoeffs.at<double>(0,2);
244  elem->SetAttribute( "p1", s.str() );
245  s.str(""); s << DistorsionCoeffs.at<double>(0,3);
246  elem->SetAttribute( "p2", s.str() );
247  elem->SetAttribute("Valid", m_Valid);
248  //s.str(""); s << DistorsionCoeffs.at<double>(4,0);
249  //elem->SetAttribute( "k3", s.str() );
250 }
251 
253 {
254  assert( elem );
255  assert( elem->ValueStr() == "results" );
256  cv::Mat CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType<double>::type);
257  CameraMatrix.at<double>(2,2) = 1.0;
258  cv::Mat DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType<double>::type);
259 
260  TiXmlElement* focus_lenXElem = elem->FirstChildElement("focus_lenX");
261  endoAssert( focus_lenXElem != nullptr );
262  CameraMatrix.at<double>(0,0) = atof( focus_lenXElem->GetText() );
263 
264  TiXmlElement* focus_lenYElem = elem->FirstChildElement("focus_lenY");
265  endoAssert( focus_lenYElem != nullptr );
266  CameraMatrix.at<double>(1,1) = atof( focus_lenYElem->GetText() );
267 
268  TiXmlElement* PrincipalXElem = elem->FirstChildElement("PrincipalX");
269  endoAssert( PrincipalXElem != nullptr );
270  CameraMatrix.at<double>(0,2) = atof( PrincipalXElem->GetText() );
271 
272  TiXmlElement* PrincipalYElem = elem->FirstChildElement("PrincipalY");
273  endoAssert( PrincipalYElem != nullptr );
274  CameraMatrix.at<double>(1,2) = atof( PrincipalYElem->GetText() );
275 
276  // DISTORSION COEFFS
277 
278  TiXmlElement* Dist1Elem = elem->FirstChildElement("Dist1");
279  endoAssert( Dist1Elem != nullptr );
280  DistorsionCoeffs.at<double>(0,0) = atof( Dist1Elem->GetText() );
281 
282  TiXmlElement* Dist2Elem = elem->FirstChildElement("Dist2");
283  endoAssert( Dist2Elem != nullptr );
284  DistorsionCoeffs.at<double>(0,1) = atof( Dist2Elem->GetText() );
285 
286  TiXmlElement* Dist3Elem = elem->FirstChildElement("Dist3");
287  endoAssert( Dist3Elem != nullptr );
288  DistorsionCoeffs.at<double>(0,2) = atof( Dist3Elem->GetText() );
289 
290  TiXmlElement* Dist4Elem = elem->FirstChildElement("Dist4");
291  endoAssert( Dist4Elem != nullptr );
292  DistorsionCoeffs.at<double>(0,3) = atof( Dist4Elem->GetText() );
293 
294  int valid = 0;
295  elem->QueryIntAttribute("Valid", &valid);
296 
297  {
299  m_Valid = static_cast<bool>(valid);
300  m_CameraMatrix = CameraMatrix;
301  m_DistorsionCoeffs = DistorsionCoeffs;
302  }
303 
304  this->Modified();
305 }
306 
307 void mitk::CameraIntrinsics::FromXML(TiXmlElement* elem)
308 {
309  endoAssert ( elem );
310  MITK_DEBUG << elem->Value();
311  std::string filename;
312  if(elem->QueryStringAttribute("file", &filename) == TIXML_SUCCESS)
313  {
314  this->FromXMLFile(filename);
315  return;
316  }
317  else if(strcmp(elem->Value(), "CalibrationProject") == 0)
318  {
319  this->FromGMLCalibrationXML(elem->FirstChildElement("results"));
320  return;
321  }
322 
323  assert ( elem );
324  if(strcmp(elem->Value(), this->GetNameOfClass()) != 0)
325  elem = elem->FirstChildElement(this->GetNameOfClass());
326 
327  std::ostringstream err;
328  // CAMERA MATRIX
329  cv::Mat CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType<double>::type);
330  CameraMatrix.at<double>(2,2) = 1.0;
331  double val = 0.0;
332  if(elem->QueryDoubleAttribute("fx", &val) == TIXML_SUCCESS)
333  CameraMatrix.at<double>(0,0) = val;
334  else
335  err << "fx, ";
336 
337  if(elem->QueryDoubleAttribute("fy", &val) == TIXML_SUCCESS)
338  CameraMatrix.at<double>(1,1) = val;
339  else
340  err << "fy, ";
341 
342  if(elem->QueryDoubleAttribute("cx", &val) == TIXML_SUCCESS)
343  CameraMatrix.at<double>(0,2) = val;
344  else
345  err << "cx, ";
346 
347  if(elem->QueryDoubleAttribute("cy", &val) == TIXML_SUCCESS)
348  CameraMatrix.at<double>(1,2) = val;
349  else
350  err << "cy, ";
351 
352  // DISTORSION COEFFS
353  endodebug( "creating DistorsionCoeffs from XML file")
354  cv::Mat DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType<double>::type);
355  if(elem->QueryDoubleAttribute("k1", &val) == TIXML_SUCCESS)
356  DistorsionCoeffs.at<double>(0,0) = val;
357  else
358  err << "k1, ";
359 
360  if(elem->QueryDoubleAttribute("k2", &val) == TIXML_SUCCESS)
361  DistorsionCoeffs.at<double>(0,1) = val;
362  else
363  err << "k2, ";
364 
365  if(elem->QueryDoubleAttribute("p1", &val) == TIXML_SUCCESS)
366  DistorsionCoeffs.at<double>(0,2) = val;
367  else
368  err << "p1, ";
369 
370  if(elem->QueryDoubleAttribute("p2", &val) == TIXML_SUCCESS)
371  DistorsionCoeffs.at<double>(0,3) = val;
372  else
373  err << "p2, ";
374 
375  DistorsionCoeffs.at<double>(0,4) = 0.0;
376 
377  /*if(elem->QueryDoubleAttribute("k3", &val) == TIXML_SUCCESS)
378  DistorsionCoeffs.at<double>(4,0) = val;
379  else
380  err << "k3, ";*/
381 
382  std::string errorStr = err.str();
383  int errLength = errorStr.length();
384  if(errLength > 0)
385  {
386  errorStr = errorStr.substr(0, errLength-2);
387  errorStr.append(" not found");
388  throw std::invalid_argument(err.str());
389  }
390 
391  int valid = 0;
392  elem->QueryIntAttribute("Valid", &valid);
393 
394  {
396  m_Valid = static_cast<bool>(valid);
397  m_CameraMatrix = CameraMatrix;
398  m_DistorsionCoeffs = DistorsionCoeffs;
399  }
400 
401  this->Modified();
402 }
403 
405 {
407  double FocalLengthX = m_CameraMatrix.at<double>(0,0);
408 
409  return FocalLengthX;
410 }
412 {
414  double FocalLengthY = m_CameraMatrix.at<double>(1,1);;
415  return FocalLengthY;
416 }
418 {
420  double PrincipalPointX = m_CameraMatrix.at<double>(0,2);
421  return PrincipalPointX;
422 }
424 {
426  double PrincipalPointY = m_CameraMatrix.at<double>(1,2);
427  return PrincipalPointY;
428 }
430 {
432  mitk::Point4D coeffs;
433 
434  coeffs[0] = m_DistorsionCoeffs.at<double>(0,0);
435  coeffs[1] = m_DistorsionCoeffs.at<double>(0,1);
436  coeffs[2] = m_DistorsionCoeffs.at<double>(0,2);
437  coeffs[3] = m_DistorsionCoeffs.at<double>(0,3);
438 
439  return coeffs;
440 }
441 
443 {
444  mitk::Point3D p;
445  p[0] = this->GetFocalLengthX();
446  p[1] = this->GetFocalLengthY();
447  p[2] = 0;
448  return p;
449 }
450 
452 {
453  mitk::Point3D p;
454  p[0] = this->GetPrincipalPointX();
455  p[1] = this->GetPrincipalPointY();
456  p[2] = 0;
457  return p;
458 }
459 
460 vnl_vector_fixed<mitk::ScalarType, 2>
462 {
463  vnl_vector_fixed<mitk::ScalarType, 2> vec;
464  vec[0] = this->GetFocalLengthX();
465  vec[1] = this->GetFocalLengthY();
466  return vec;
467 }
468 
469 vnl_vector_fixed<mitk::ScalarType, 2>
471 {
472  vnl_vector_fixed<mitk::ScalarType, 2> vec;
473  vec[0] = this->GetPrincipalPointX();
474  vec[1] = this->GetPrincipalPointY();
475  return vec;
476 }
477 
478 std::ostream& operator<< (std::ostream& os, mitk::CameraIntrinsics::Pointer p)
479 {
480  os << p->ToString();
481  return os;
482 }
483 
485 {
486  return this->ToString();
487 }
488 
490  const std::string& varName)
491 {
492  std::ostringstream s;
493  s << varName << " = [" << this->GetFocalLengthX() << " 0 "
494  << this->GetPrincipalPointX() << "; 0 " <<
495  this->GetFocalLengthY() << " " << this->GetPrincipalPointY() << ";"
496  << " 0 0 1 ];";
497  return s.str();
498 }
499 
501 {
503  m_Valid = valid;
504 }
505 
506 itk::LightObject::Pointer mitk::CameraIntrinsics::InternalClone() const
507 {
508  itk::LightObject::Pointer result(new Self(*this));
509  result->UnRegister();
510  return result;
511 }
itk::SmartPointer< Self > Pointer
void FromXML(TiXmlElement *elem) override
MITKCORE_EXPORT std::ostream & operator<<(std::ostream &o, DataNode::Pointer &dtn)
class representing camera intrinsics and related functions
vnl_matrix_fixed< mitk::ScalarType, 3, 3 > GetVnlCameraMatrix() const
void FromGMLCalibrationXML(TiXmlElement *elem)
std::string ToOctaveString(const std::string &varName="CameraIntrinsics")
std::string ToString() const
#define MITK_DEBUG
Definition: mitkLogMacros.h:26
#define endoAssertMsg(a, msg)
DataCollection - Class to facilitate loading/accessing structured data.
vnl_vector_fixed< mitk::ScalarType, 2 > GetPrincipalPointAsVnlVector() const
void SetFocalLength(double x, double y)
void SetIntrinsics(const cv::Mat &_CameraMatrix, const cv::Mat &_DistorsionCoeffs)
#define endodebug(msg)
mitk::Point4D GetDistorsionCoeffsAsPoint4D() const
static const std::string filename
mitk::Point3D GetPrincipalPoint() const
void SetDistorsionCoeffs(double k1, double k2, double p1, double p2)
bool Equals(const CameraIntrinsics *other) const
vnl_vector_fixed< mitk::ScalarType, 2 > GetFocalPointAsVnlVector() const
void SetPrincipalPoint(double x, double y)
#define endoAssert(a)
interface for all classes able to write themselves to XML files
void Copy(const CameraIntrinsics *other)
void ToXML(TiXmlElement *elem) const override
vnl_matrix_fixed< mitk::ScalarType, 3, 4 > GetVnlCameraMatrix3x4() const
mitk::Point3D GetFocalPoint() const
void SetCameraMatrix(const vnl_matrix_fixed< mitk::ScalarType, 3, 3 > &_CameraMatrix)
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.