diff --git a/Modules/CMakeLists.txt b/Modules/CMakeLists.txt index 001a20e23f..04747cd7e9 100644 --- a/Modules/CMakeLists.txt +++ b/Modules/CMakeLists.txt @@ -1,33 +1,34 @@ SET(LIBPOSTFIX "Ext") SET(module_dirs SceneSerializationBase PlanarFigure MitkExt SceneSerialization QmitkExt DiffusionImaging GPGPU IGT + CameraCalibration IGTUI RigidRegistration RigidRegistrationUI DeformableRegistration DeformableRegistrationUI OpenCVVideoSupport Overlays InputDevices ToFHardware ToFProcessing ToFUI ) SET(MITK_DEFAULT_SUBPROJECTS MITK-Modules) FOREACH(module_dir ${module_dirs}) ADD_SUBDIRECTORY(${module_dir}) ENDFOREACH() IF(MITK_USE_BLUEBERRY) ADD_SUBDIRECTORY(Bundles) ENDIF() diff --git a/Modules/CameraCalibration/CMakeLists.txt b/Modules/CameraCalibration/CMakeLists.txt new file mode 100644 index 0000000000..825c7cbcc7 --- /dev/null +++ b/Modules/CameraCalibration/CMakeLists.txt @@ -0,0 +1,5 @@ +MITK_CREATE_MODULE(mitkCameraCalibration + DEPENDS MitkIGT + PACKAGE_DEPENDS OpenCV + PROVIDES mitkCameraCalibration +) diff --git a/Modules/CameraCalibration/files.cmake b/Modules/CameraCalibration/files.cmake new file mode 100644 index 0000000000..e87d7ca979 --- /dev/null +++ b/Modules/CameraCalibration/files.cmake @@ -0,0 +1,7 @@ +SET(CPP_FILES + mitkEndoDebug.cpp + mitkTransform.cpp + mitkCameraIntrinsics.cpp + mitkXMLSerializable.cpp +) + diff --git a/Modules/CameraCalibration/mitkAlgorithm.h b/Modules/CameraCalibration/mitkAlgorithm.h new file mode 100644 index 0000000000..3724c1cfbf --- /dev/null +++ b/Modules/CameraCalibration/mitkAlgorithm.h @@ -0,0 +1,22 @@ +#ifndef mitkAlgorithm_h +#define mitkAlgorithm_h + +namespace mitk +{ + /// + /// filter "Algorithm" interface = a class which does + /// its work when calling this function + /// this is a general polling mechansim + /// + class Algorithm + { + public: + /// + /// do update steps here + /// + virtual void Update() = 0; + }; + +} // namespace mitk + +#endif // mitkAlgorithm_h diff --git a/Modules/CameraCalibration/mitkCameraIntrinsics.cpp b/Modules/CameraCalibration/mitkCameraIntrinsics.cpp new file mode 100644 index 0000000000..2698f0a6fe --- /dev/null +++ b/Modules/CameraCalibration/mitkCameraIntrinsics.cpp @@ -0,0 +1,482 @@ +#include "mitkCameraIntrinsics.h" +#include +#include +#include + +mitk::CameraIntrinsics::CameraIntrinsics() + : m_Valid(false), m_Mutex(itk::FastMutexLock::New()) +{ + m_CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType::type); + m_CameraMatrix.at(2,2) = 1.0; + m_DistorsionCoeffs = cv::Mat::zeros(1, 5, cv::DataType::type); +} + +mitk::CameraIntrinsics::~CameraIntrinsics() +{ + +} + +bool mitk::CameraIntrinsics::Equals( const CameraIntrinsics* other ) const +{ + return other->GetDistorsionCoeffsAsPoint4D()== + this->GetDistorsionCoeffsAsPoint4D() && + other->GetFocalPoint()== + this->GetFocalPoint() && + other->GetPrincipalPoint() + == this->GetPrincipalPoint(); +} + +void mitk::CameraIntrinsics::Copy(const CameraIntrinsics* other) +{ + this->SetIntrinsics( other->GetCameraMatrix().clone() + , other->GetDistorsionCoeffs().clone() ); +} + +bool mitk::CameraIntrinsics::IsValid() const +{ + itk::MutexLockHolder lock(*m_Mutex); + return m_Valid; +} + +mitk::CameraIntrinsics::Pointer mitk::CameraIntrinsics::Clone() const +{ + mitk::CameraIntrinsics::Pointer copy = mitk::CameraIntrinsics::New(); + copy->SetIntrinsics( this->GetCameraMatrix(), this->GetDistorsionCoeffs() ); + return copy; +} + +vnl_matrix_fixed + mitk::CameraIntrinsics::GetVnlCameraMatrix() const +{ + vnl_matrix_fixed mat; + mat.set_identity(); + + { + itk::MutexLockHolder lock(*m_Mutex); + mat(0,0) = m_CameraMatrix.at(0,0); + mat(1,1) = m_CameraMatrix.at(1,1); + + mat(0,2) = m_CameraMatrix.at(0,2); + mat(1,2) = m_CameraMatrix.at(1,2); + } + + return mat; +} + +void mitk::CameraIntrinsics::SetCameraMatrix( + const vnl_matrix_fixed& _CameraMatrix ) +{ + itk::MutexLockHolder lock(*m_Mutex); + m_CameraMatrix.at(0,0) = _CameraMatrix(0,0); + m_CameraMatrix.at(1,1) = _CameraMatrix(1,1); + + m_CameraMatrix.at(0,2) = _CameraMatrix(0,2); + m_CameraMatrix.at(1,2) = _CameraMatrix(1,2); +} + +vnl_matrix_fixed + mitk::CameraIntrinsics::GetVnlCameraMatrix3x4() const +{ + vnl_matrix_fixed mat; + mat.fill(0); + mat.update( this->GetVnlCameraMatrix().as_matrix() ); + + return mat; +} + +void mitk::CameraIntrinsics::SetIntrinsics( const cv::Mat& _CameraMatrix + , const cv::Mat& _DistorsionCoeffs) +{ + { + itk::MutexLockHolder lock(*m_Mutex); + if( _CameraMatrix.cols != 3 || _CameraMatrix.rows != 3) + throw std::invalid_argument("Wrong format of camera matrix. Should be 3x3" + " double."); + + endoAssertMsg( (_DistorsionCoeffs.cols == 5) && + _DistorsionCoeffs.rows == 1, "Wrong format of distorsion coefficients" + " vector. Should be 5x1 double."); + + m_CameraMatrix = _CameraMatrix; + m_DistorsionCoeffs = _DistorsionCoeffs; + + m_Valid = true; + } + this->Modified(); +} + +void mitk::CameraIntrinsics::SetIntrinsics( const mitk::Point3D& focalPoint, + const mitk::Point3D& principalPoint, + const mitk::Point4D& distortionCoefficients) + +{ + { + itk::MutexLockHolder lock(*m_Mutex); + m_CameraMatrix.at(0,0) = focalPoint[0]; + m_CameraMatrix.at(1,1) = focalPoint[1]; + + m_CameraMatrix.at(0,2) = principalPoint[0]; + m_CameraMatrix.at(1,2) = principalPoint[1]; + + m_DistorsionCoeffs.at(0,0) = distortionCoefficients[0]; + m_DistorsionCoeffs.at(0,1) = distortionCoefficients[1]; + m_DistorsionCoeffs.at(0,2) = distortionCoefficients[2]; + m_DistorsionCoeffs.at(0,3) = distortionCoefficients[3]; + } + this->Modified(); +} + +void mitk::CameraIntrinsics::SetFocalLength( double x, double y ) +{ + { + itk::MutexLockHolder lock(*m_Mutex); + m_CameraMatrix.at(0,0) = x; + m_CameraMatrix.at(1,1) = y; + } + this->Modified(); +} + +void mitk::CameraIntrinsics::SetPrincipalPoint( double x, double y ) +{ + { + itk::MutexLockHolder lock(*m_Mutex); + m_CameraMatrix.at(0,2) = x; + m_CameraMatrix.at(1,2) = y; + } + this->Modified(); +} + +void mitk::CameraIntrinsics::SetDistorsionCoeffs( double k1, double k2, + double p1, double p2 ) +{ + + { + itk::MutexLockHolder lock(*m_Mutex); + + m_DistorsionCoeffs.at(0,0) = k1; + m_DistorsionCoeffs.at(0,1) = k2; + m_DistorsionCoeffs.at(0,2) = p1; + m_DistorsionCoeffs.at(0,3) = p2; + } + this->Modified(); +} + +cv::Mat mitk::CameraIntrinsics::GetCameraMatrix() const +{ + itk::MutexLockHolder lock(*m_Mutex); + return m_CameraMatrix.clone(); // return a copy of this small matrix +} + +cv::Mat mitk::CameraIntrinsics::GetDistorsionCoeffs() const +{ + itk::MutexLockHolder lock(*m_Mutex); + return m_DistorsionCoeffs.clone(); // return a copy of this small matrix +} + +cv::Mat mitk::CameraIntrinsics::GetDistorsionCoeffs() +{ + const CameraIntrinsics* intrinsics = this; + return intrinsics->GetDistorsionCoeffs(); +} + +std::string mitk::CameraIntrinsics::ToString() const +{ + itk::MutexLockHolder lock(*m_Mutex); + std::ostringstream s; s.precision(12); + const cv::Mat& CameraMatrix = m_CameraMatrix; + const cv::Mat& DistorsionCoeffs = m_DistorsionCoeffs; + + s.str(""); s << this->GetNameOfClass() << ": "; + s << "fx = " << CameraMatrix.at(0,0); + s << ", fy = " << CameraMatrix.at(1,1); + s << ", cx = " << CameraMatrix.at(0,2); + s << ", cy = " << CameraMatrix.at(1,2); + + s << ", k1 = " << DistorsionCoeffs.at(0,0); + s << ", k2 = " << DistorsionCoeffs.at(0,1); + s << ", p1 = " << DistorsionCoeffs.at(0,2); + s << ", p2 = " << DistorsionCoeffs.at(0,3); + //s << ", k3 = " << DistorsionCoeffs.at(0,4); + + return s.str(); +} + +void mitk::CameraIntrinsics::ToXML(TiXmlElement* elem) const +{ + itk::MutexLockHolder lock(*m_Mutex); + elem->SetValue(this->GetNameOfClass()); + std::ostringstream s; s.precision(12); + const cv::Mat& CameraMatrix = m_CameraMatrix; + s.str(""); s << CameraMatrix.at(0,0); + elem->SetAttribute( "fx", s.str() ); + s.str(""); s << CameraMatrix.at(1,1); + elem->SetAttribute( "fy", s.str() ); + s.str(""); s << CameraMatrix.at(0,2); + elem->SetAttribute( "cx", s.str() ); + s.str(""); s << CameraMatrix.at(1,2); + elem->SetAttribute( "cy", s.str() ); + + const cv::Mat& DistorsionCoeffs = m_DistorsionCoeffs; + s.str(""); s << DistorsionCoeffs.at(0,0); + elem->SetAttribute( "k1", s.str() ); + s.str(""); s << DistorsionCoeffs.at(0,1); + elem->SetAttribute( "k2", s.str() ); + s.str(""); s << DistorsionCoeffs.at(0,2); + elem->SetAttribute( "p1", s.str() ); + s.str(""); s << DistorsionCoeffs.at(0,3); + elem->SetAttribute( "p2", s.str() ); + elem->SetAttribute("Valid", m_Valid); + //s.str(""); s << DistorsionCoeffs.at(4,0); + //elem->SetAttribute( "k3", s.str() ); +} + +void mitk::CameraIntrinsics::FromGMLCalibrationXML(TiXmlElement* elem) +{ + assert( elem ); + assert( elem->ValueStr() == "results" ); + cv::Mat CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType::type); + CameraMatrix.at(2,2) = 1.0; + cv::Mat DistorsionCoeffs = cv::Mat::zeros(1, 4, cv::DataType::type); + + TiXmlElement* focus_lenXElem = elem->FirstChildElement("focus_lenX"); + endoAssert( focus_lenXElem != 0 ); + CameraMatrix.at(0,0) = atof( focus_lenXElem->GetText() ); + + TiXmlElement* focus_lenYElem = elem->FirstChildElement("focus_lenY"); + endoAssert( focus_lenYElem != 0 ); + CameraMatrix.at(1,1) = atof( focus_lenYElem->GetText() ); + + TiXmlElement* PrincipalXElem = elem->FirstChildElement("PrincipalX"); + endoAssert( PrincipalXElem != 0 ); + CameraMatrix.at(0,2) = atof( PrincipalXElem->GetText() ); + + TiXmlElement* PrincipalYElem = elem->FirstChildElement("PrincipalY"); + endoAssert( PrincipalYElem != 0 ); + CameraMatrix.at(1,2) = atof( PrincipalYElem->GetText() ); + + // DISTORSION COEFFS + + TiXmlElement* Dist1Elem = elem->FirstChildElement("Dist1"); + endoAssert( Dist1Elem != 0 ); + DistorsionCoeffs.at(0,0) = atof( Dist1Elem->GetText() ); + + TiXmlElement* Dist2Elem = elem->FirstChildElement("Dist2"); + endoAssert( Dist2Elem != 0 ); + DistorsionCoeffs.at(0,1) = atof( Dist2Elem->GetText() ); + + TiXmlElement* Dist3Elem = elem->FirstChildElement("Dist3"); + endoAssert( Dist3Elem != 0 ); + DistorsionCoeffs.at(0,2) = atof( Dist3Elem->GetText() ); + + TiXmlElement* Dist4Elem = elem->FirstChildElement("Dist4"); + endoAssert( Dist4Elem != 0 ); + DistorsionCoeffs.at(0,3) = atof( Dist4Elem->GetText() ); + + int valid = 0; + elem->QueryIntAttribute("Valid", &valid); + + { + itk::MutexLockHolder lock(*m_Mutex); + m_Valid = static_cast(valid); + m_CameraMatrix = CameraMatrix; + m_DistorsionCoeffs = DistorsionCoeffs; + } + + this->Modified(); +} + +void mitk::CameraIntrinsics::FromXML(TiXmlElement* elem) +{ + endoAssert ( elem ); + MITK_DEBUG << elem->Value(); + std::string filename; + if(elem->QueryStringAttribute("file", &filename) == TIXML_SUCCESS) + { + this->FromXMLFile(filename); + return; + } + else if(strcmp(elem->Value(), "CalibrationProject") == 0) + { + this->FromGMLCalibrationXML(elem->FirstChildElement("results")); + return; + } + + assert ( elem ); + if(strcmp(elem->Value(), this->GetNameOfClass()) != 0) + elem = elem->FirstChildElement(this->GetNameOfClass()); + + std::ostringstream err; + // CAMERA MATRIX + cv::Mat CameraMatrix = cv::Mat::zeros(3, 3, cv::DataType::type); + CameraMatrix.at(2,2) = 1.0; + float val = 0.0f; + if(elem->QueryFloatAttribute("fx", &val) == TIXML_SUCCESS) + CameraMatrix.at(0,0) = val; + else + err << "fx, "; + + if(elem->QueryFloatAttribute("fy", &val) == TIXML_SUCCESS) + CameraMatrix.at(1,1) = val; + else + err << "fy, "; + + if(elem->QueryFloatAttribute("cx", &val) == TIXML_SUCCESS) + CameraMatrix.at(0,2) = val; + else + err << "cx, "; + + if(elem->QueryFloatAttribute("cy", &val) == TIXML_SUCCESS) + CameraMatrix.at(1,2) = val; + else + err << "cy, "; + + // DISTORSION COEFFS + cv::Mat DistorsionCoeffs = cv::Mat::zeros(1, 4, cv::DataType::type); + if(elem->QueryFloatAttribute("k1", &val) == TIXML_SUCCESS) + DistorsionCoeffs.at(0,0) = val; + else + err << "k1, "; + + if(elem->QueryFloatAttribute("k2", &val) == TIXML_SUCCESS) + DistorsionCoeffs.at(0,1) = val; + else + err << "k2, "; + + if(elem->QueryFloatAttribute("p1", &val) == TIXML_SUCCESS) + DistorsionCoeffs.at(0,2) = val; + else + err << "p1, "; + + if(elem->QueryFloatAttribute("p2", &val) == TIXML_SUCCESS) + DistorsionCoeffs.at(0,3) = val; + else + err << "p2, "; + + /*if(elem->QueryFloatAttribute("k3", &val) == TIXML_SUCCESS) + DistorsionCoeffs.at(4,0) = val; + else + err << "k3, ";*/ + + std::string errorStr = err.str(); + int errLength = errorStr.length(); + if(errLength > 0) + { + errorStr = errorStr.substr(0, errLength-2); + errorStr.append(" not found"); + throw std::invalid_argument(err.str()); + } + + int valid = 0; + elem->QueryIntAttribute("Valid", &valid); + + { + itk::MutexLockHolder lock(*m_Mutex); + m_Valid = static_cast(valid); + m_CameraMatrix = CameraMatrix; + m_DistorsionCoeffs = DistorsionCoeffs; + } + + this->Modified(); +} + +double mitk::CameraIntrinsics::GetFocalLengthX() const +{ + itk::MutexLockHolder lock(*m_Mutex); + double FocalLengthX = m_CameraMatrix.at(0,0); + + return FocalLengthX; +} +double mitk::CameraIntrinsics::GetFocalLengthY() const +{ + itk::MutexLockHolder lock(*m_Mutex); + double FocalLengthY = m_CameraMatrix.at(1,1);; + return FocalLengthY; +} +double mitk::CameraIntrinsics::GetPrincipalPointX() const +{ + itk::MutexLockHolder lock(*m_Mutex); + double PrincipalPointX = m_CameraMatrix.at(0,2); + return PrincipalPointX; +} +double mitk::CameraIntrinsics::GetPrincipalPointY() const +{ + itk::MutexLockHolder lock(*m_Mutex); + double PrincipalPointY = m_CameraMatrix.at(1,2); + return PrincipalPointY; +} +mitk::Point4D mitk::CameraIntrinsics::GetDistorsionCoeffsAsPoint4D() const +{ + itk::MutexLockHolder lock(*m_Mutex); + mitk::Point4D coeffs; + + coeffs[0] = m_DistorsionCoeffs.at(0,0); + coeffs[1] = m_DistorsionCoeffs.at(0,1); + coeffs[2] = m_DistorsionCoeffs.at(0,2); + coeffs[3] = m_DistorsionCoeffs.at(0,3); + + return coeffs; +} + +mitk::Point3D mitk::CameraIntrinsics::GetFocalPoint() const +{ + mitk::Point3D p; + p[0] = this->GetFocalLengthX(); + p[1] = this->GetFocalLengthY(); + p[2] = 0; + return p; +} + +mitk::Point3D mitk::CameraIntrinsics::GetPrincipalPoint() const +{ + mitk::Point3D p; + p[0] = this->GetPrincipalPointX(); + p[1] = this->GetPrincipalPointY(); + p[2] = 0; + return p; +} + +vnl_vector_fixed + mitk::CameraIntrinsics::GetFocalPointAsVnlVector() const +{ + vnl_vector_fixed vec; + vec[0] = this->GetFocalLengthX(); + vec[1] = this->GetFocalLengthY(); + return vec; +} + +vnl_vector_fixed + mitk::CameraIntrinsics::GetPrincipalPointAsVnlVector() const +{ + vnl_vector_fixed vec; + vec[0] = this->GetPrincipalPointX(); + vec[1] = this->GetPrincipalPointY(); + return vec; +} + +std::ostream& operator<< (std::ostream& os, mitk::CameraIntrinsics::Pointer p) +{ + os << p->ToString(); + return os; +} + +std::string mitk::CameraIntrinsics::GetString() +{ + return this->ToString(); +} + +std::string mitk::CameraIntrinsics::ToOctaveString( + const std::string& varName) +{ + std::ostringstream s; + s << varName << " = [" << this->GetFocalLengthX() << " 0 " + << this->GetPrincipalPointX() << "; 0 " << + this->GetFocalLengthY() << " " << this->GetPrincipalPointY() << ";" + << " 0 0 1 ];"; + return s.str(); +} + +void mitk::CameraIntrinsics::SetValid( bool valid ) +{ + itk::MutexLockHolder lock(*m_Mutex); + m_Valid = valid; +} diff --git a/Modules/CameraCalibration/mitkCameraIntrinsics.h b/Modules/CameraCalibration/mitkCameraIntrinsics.h new file mode 100644 index 0000000000..bb5c3fe803 --- /dev/null +++ b/Modules/CameraCalibration/mitkCameraIntrinsics.h @@ -0,0 +1,140 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Module: $RCSfile$ +Language: C++ +Date: $Date: 2010-03-15 11:12:36 +0100 (Mo, 15 Mrz 2010) $ +Version: $Revision: 21745 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#ifndef mitkCameraIntrinsics_h +#define mitkCameraIntrinsics_h + +#include +#include +#include +#include +#include +#include +#include "mitkXMLSerializable.h" +#include + +int mitkCameraIntrinsicsTest(int argc, char* argv[]); + +namespace mitk +{ + /// + /// \brief class representing camera intrinsics and related functions + /// + class mitkCameraCalibration_EXPORT CameraIntrinsics: virtual public itk::Object, + virtual public mitk::XMLSerializable + { + public: + /// + /// for testing purposes + /// + friend int mitkCameraIntrinsicsTest(int argc, char* argv[]); + /// + /// smartpointer typedefs + /// + mitkClassMacro(CameraIntrinsics, itk::Object); + /// + /// the static new function + /// + itkFactorylessNewMacro(Self); + + /// + /// make a clone of this intrinsics + /// + Pointer Clone() const; + + /// + /// copy information from other to this + /// + void Copy(const CameraIntrinsics* other); + + /// + /// checks two intrinsics for equality + /// + bool Equals( const CameraIntrinsics* other ) const; + + /// + /// \return the intrinsic parameter matrix as a 3x3 vnl matrix + /// + vnl_matrix_fixed GetVnlCameraMatrix() const; + + /// + /// \return the intrinsic parameter matrix as a 3x4 vnl matrix + /// (the last column only containing zeros) + /// + vnl_matrix_fixed GetVnlCameraMatrix3x4() const; + + /// + /// \return true if the intrinsics are set (some plausibility checks + /// may be done here) + /// + bool IsValid() const; + void SetValid(bool valid); + cv::Mat GetCameraMatrix() const; + cv::Mat GetDistorsionCoeffs(); + cv::Mat GetDistorsionCoeffs() const; + void ToXML(TiXmlElement* elem) const; + std::string ToString() const; + std::string GetString(); + double GetFocalLengthX() const; + double GetFocalLengthY() const; + double GetPrincipalPointX() const; + double GetPrincipalPointY() const; + mitk::Point4D GetDistorsionCoeffsAsPoint4D() const; + mitk::Point3D GetFocalPoint() const; + mitk::Point3D GetPrincipalPoint() const; + vnl_vector_fixed GetFocalPointAsVnlVector() const; + vnl_vector_fixed GetPrincipalPointAsVnlVector() const; + + /// + /// set a new camera matrix utilizing a vnl matrix + /// + void SetCameraMatrix( const vnl_matrix_fixed& + _CameraMatrix ); + + void SetIntrinsics( const cv::Mat& _CameraMatrix + , const cv::Mat& _DistorsionCoeffs); + + void SetFocalLength( double x, double y ); + void SetPrincipalPoint( double x, double y ); + void SetDistorsionCoeffs( double k1, double k2, double p1, double p2 ); + + void SetIntrinsics( const mitk::Point3D& focalPoint, + const mitk::Point3D& principalPoint, + const mitk::Point4D& distortionCoefficients); + + void FromXML(TiXmlElement* elem); + void FromGMLCalibrationXML(TiXmlElement* elem); + std::string ToOctaveString(const std::string& varName="CameraIntrinsics"); + + virtual ~CameraIntrinsics(); + + protected: + CameraIntrinsics(); + cv::Mat m_CameraMatrix; + cv::Mat m_DistorsionCoeffs; + bool m_Valid; + itk::FastMutexLock::Pointer m_Mutex; + }; + +} // namespace mitk + +mitkCameraCalibration_EXPORT std::ostream& operator<< + (std::ostream& os, mitk::CameraIntrinsics::Pointer p); + +#endif // mitkCameraIntrinsics_h diff --git a/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h b/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h new file mode 100644 index 0000000000..c918a142e8 --- /dev/null +++ b/Modules/CameraCalibration/mitkCvMatFromVnlMatrix.h @@ -0,0 +1,73 @@ +#ifndef mitkCvMatFromVnlMatrix_h +#define mitkCvMatFromVnlMatrix_h + +#include +#include +#include +#include +#include + +namespace mitk +{ + /// + /// casts a random cv::Mat to a vnl Matrix + /// if the columns of the first row are > 1 + /// then the Matrix is filled with the values from this row + /// otherwise the first elements of each row are used + /// to fill the Matrix + /// + template + class CvMatFromVnlMatrix: + virtual public Algorithm + { + public: + /// + /// init default values and save references + /// + CvMatFromVnlMatrix( + const vnl_matrix* _VnlMatrix, + cv::Mat* _CvMat): + m_VnlMatrix(_VnlMatrix), + m_CvMat(_CvMat) + { + } + + /// + /// templated function for multiplexed cv::Mat + /// + template + static void Cast( const vnl_matrix& vnlMat, cv::Mat& cvMat ) + { + endodebugvar( vnlMat ) + cvMat = cv::Mat(vnlMat.rows(), vnlMat.cols(), cv::DataType::type); + for(unsigned int i=0; i(i,j) = static_cast( vnlMat(i,j) ); +// endodebugvar( vnlMat(i,j) ) +// endodebugvar( cvMat.at(i,j) ) + } + } + } + + /// + /// executes the Algorithm + /// + void Update() + { + Cast( *m_VnlMatrix, *m_CvMat ); + } + private: + /// + /// CvMatFromVnlMatrix input member variable + /// + const vnl_matrix* m_VnlMatrix; + /// + /// CvMatFromVnlMatrix output member variable + /// + cv::Mat* m_CvMat; + }; +} // namespace mitk + +#endif // mitkCvMatFromVnlMatrix_h diff --git a/Modules/CameraCalibration/mitkCvMatFromVnlVector.h b/Modules/CameraCalibration/mitkCvMatFromVnlVector.h new file mode 100644 index 0000000000..cca34d1739 --- /dev/null +++ b/Modules/CameraCalibration/mitkCvMatFromVnlVector.h @@ -0,0 +1,58 @@ +#ifndef mitkCvMatFromVnlVector_h +#define mitkCvMatFromVnlVector_h + +#include +#include +#include + +namespace mitk +{ + /// + /// casts a random cv::Mat to a vnl vector + /// if the columns of the first row are > 1 + /// then the vector is filled with the values from this row + /// otherwise the first elements of each row are used + /// to fill the vector + /// + template + class CvMatFromVnlVector: + virtual public Algorithm + { + public: + /// + /// init default values and save references + /// + CvMatFromVnlVector( + const vnl_vector* _VnlVector, + cv::Mat* _CvMat): + m_CvMatFromVnlMatrix(&m_VnlMatrix, _CvMat), + m_VnlVector(_VnlVector) + { + } + + /// + /// executes the Algorithm + /// + void Update() + { + m_VnlMatrix.set_size( m_VnlVector->size(), 1 ); + m_VnlMatrix.set_column(0, *m_VnlVector); + m_CvMatFromVnlMatrix.Update(); + } + private: + /// + /// CvMatFromVnlVector input member variable + /// + vnl_matrix m_VnlMatrix; + /// + /// internal algorithm to create a vnl matrix from a random cv mat + /// + mitk::CvMatFromVnlMatrix m_CvMatFromVnlMatrix; + /// + /// CvMatFromVnlVector input member variable + /// + const vnl_vector* m_VnlVector; + }; +} // namespace mitk + +#endif // mitkCvMatFromVnlVector_h diff --git a/Modules/CameraCalibration/mitkEndoDebug.cpp b/Modules/CameraCalibration/mitkEndoDebug.cpp new file mode 100644 index 0000000000..2b5654ced5 --- /dev/null +++ b/Modules/CameraCalibration/mitkEndoDebug.cpp @@ -0,0 +1,173 @@ +#include "mitkEndoDebug.h" +#include +#include +#include + +namespace mitk +{ + struct EndoDebugData + { + EndoDebugData() + : m_DebugEnabled(false) + , m_ShowImagesInDebug(false) + , m_ShowImagesTimeOut(false) + , m_Mutex(itk::FastMutexLock::New()) + { + + } + + std::set m_FilesToDebug; + std::set m_SymbolsToDebug; + bool m_DebugEnabled; + bool m_ShowImagesInDebug; + size_t m_ShowImagesTimeOut; + itk::FastMutexLock::Pointer m_Mutex; + }; + + EndoDebug::EndoDebug() + : d ( new EndoDebugData ) + { + + } + + EndoDebug::~EndoDebug() + { + delete d; + } + + EndoDebug& EndoDebug::GetInstance() + { + static EndoDebug instance; + return instance; + } + + std::string EndoDebug::GetFilenameWithoutExtension(const std::string& s) + { + return itksys::SystemTools::GetFilenameWithoutExtension( s ); + } + + void EndoDebug::AddFileToDebug(const std::string& s) + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + d->m_FilesToDebug.insert( s ); + } + } + + void EndoDebug::AddSymbolToDebug(const std::string& symbolToDebug) + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + d->m_SymbolsToDebug.insert( symbolToDebug ); + } + } + + bool EndoDebug::DebugSymbol(const std::string& s) + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + return d->m_SymbolsToDebug.find(s) + != d->m_SymbolsToDebug.end(); + } + } + + bool EndoDebug::DebugFile(const std::string& s) + { + std::string filename = GetFilenameWithoutExtension(s); + + { + itk::MutexLockHolder lock(*d->m_Mutex); + return d->m_FilesToDebug.find(filename) + != d->m_FilesToDebug.end(); + } + } + + bool EndoDebug::Debug( const std::string& fileToDebug, const std::string& symbol ) + { + bool debug = false; + + { + bool debugEnabled = false; + size_t filesSize = 0; + size_t symbolsSize = 0; + bool symbolFound = false; + { + itk::MutexLockHolder lock(*d->m_Mutex); + debugEnabled = d->m_DebugEnabled; + filesSize = d->m_FilesToDebug.size(); + symbolsSize = d->m_SymbolsToDebug.size(); + symbolFound = d->m_SymbolsToDebug.find(symbol) != d->m_SymbolsToDebug.end(); + } + + if( debugEnabled ) + { + if( filesSize == 0 ) + debug = true; + else + debug = DebugFile(fileToDebug); + + // ok debug is determined so far, now check if symbol set + if( symbolsSize > 0 ) + { + debug = symbolFound; + } + else + { + // do not show symbol debug output if no symbols are set at all + if( !symbol.empty() ) + debug = false; + } + } + } + + return debug; + } + + void EndoDebug::SetDebugEnabled(bool _DebugEnabled) + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + d->m_DebugEnabled = _DebugEnabled; + } + } + + bool EndoDebug::GetDebugEnabled() + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + return d->m_DebugEnabled; + } + } + + void EndoDebug::SetShowImagesInDebug(bool _ShowImagesInDebug) + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + d->m_ShowImagesInDebug = _ShowImagesInDebug; + } + } + + bool EndoDebug::GetShowImagesInDebug() + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + return d->m_ShowImagesInDebug; + } + } + + void EndoDebug::SetShowImagesTimeOut(size_t _ShowImagesTimeOut) + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + d->m_ShowImagesTimeOut = _ShowImagesTimeOut; + } + } + + bool EndoDebug::GetShowImagesTimeOut() + { + { + itk::MutexLockHolder lock(*d->m_Mutex); + return d->m_ShowImagesTimeOut; + } + } +} diff --git a/Modules/CameraCalibration/mitkEndoDebug.h b/Modules/CameraCalibration/mitkEndoDebug.h new file mode 100644 index 0000000000..14572f5973 --- /dev/null +++ b/Modules/CameraCalibration/mitkEndoDebug.h @@ -0,0 +1,166 @@ +#ifndef mitkEndoDebug_h +#define mitkEndoDebug_h + +#include +#include +#include +#include + +namespace mitk +{ + /// + /// again d pointer impl + /// + struct EndoDebugData; + + /// + /// class responsible for handling debug matters + /// in endotracking + /// + struct mitkEndoTracking_EXPORT EndoDebug + { + /// + /// singleton class + /// + static EndoDebug& GetInstance(); + + /// + /// set if debug is enabled at all + /// + void SetDebugEnabled(bool _DebugEnabled); + + /// + /// \return true if debug should be enabled + /// + bool GetDebugEnabled(); + + /// + /// set if debug is enabled at all + /// + void SetShowImagesInDebug(bool _ShowImagesInDebug); + + /// + /// \return true if debug should be enabled + /// + bool GetShowImagesInDebug(); + + /// + /// set if debug is enabled at all + /// + void SetShowImagesTimeOut(size_t _ShowImagesTimeOut); + + /// + /// \return true if debug should be enabled + /// + bool GetShowImagesTimeOut(); + + /// + /// \return the basename of a file without path + /// + std::string GetFilenameWithoutExtension(const std::string& s); + + /// + /// add a file to debug ( if one or more files are set ) + /// only those files will be debugged when using the macros + /// below. e.g. call AddFileToDebug("MyClass.cpp"), then + /// statements like endodebug(...) will be evaluated in + /// MyClass.cpp and nowhere else + /// + void AddFileToDebug(const std::string& fileToDebug); + + /// + /// same as files to debug, but the user can provide + /// any symbol string. if one or more symbols + /// are set only for these symbols Debug() will return true + /// + void AddSymbolToDebug(const std::string& symbolToDebug); + + /// + /// \return true if file should be debugged + /// + bool DebugFile( const std::string& fileToDebug ); + + /// + /// \return true if symbol should be debugged + /// + bool DebugSymbol( const std::string& symbolToDebug ); + + /// + /// \return the all in all status if debug output + /// should be generated + /// + bool Debug( const std::string& fileToDebug, const std::string& symbol="" ); + /// + /// init defaults + /// + EndoDebug(); + /// + /// delete d pointer + /// + virtual ~EndoDebug(); + + private: + /// + /// d pointer + /// + EndoDebugData* d; + }; +} + +/// +/// macro for debugging purposes +/// +#define endodebugmarker\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ + { \ + std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": " << __FUNCTION__ << std::endl;\ + } + +/// +/// macro for debugging purposes +/// +#define endodebug(msg)\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ + { \ + std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": " << msg << std::endl;\ + } + +/// +/// macro for debugging variables +/// +#define endodebugvar(var)\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) ) \ + { \ + std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": " #var " = " << var << std::endl;\ + } + +/// +/// macro for debugging a variable as symbol +/// +#define endodebugsymbol(var, mSymbol)\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__, mSymbol) ) \ + { \ + std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": " #var " = " << var << std::endl;\ + } + +/// +/// macro for showing cv image if in debug mode +/// highgui.h must be included before +/// +#define endodebugimg(imgVariableName)\ + if( mitk::EndoDebug::GetInstance().Debug(__FILE__) \ + && mitk::EndoDebug::GetInstance().GetShowImagesInDebug()) \ + { \ + std::cout << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " << __LINE__\ + << ": Showing " #imgVariableName << std::endl; \ + cv::imshow( "Debug", imgVariableName ); \ + cv::waitKey( mitk::EndoDebug::GetInstance().GetShowImagesTimeOut() ); \ + } + +#endif // mitkEndoDebug_h + + diff --git a/Modules/CameraCalibration/mitkEndoMacros.h b/Modules/CameraCalibration/mitkEndoMacros.h new file mode 100644 index 0000000000..ea450aec64 --- /dev/null +++ b/Modules/CameraCalibration/mitkEndoMacros.h @@ -0,0 +1,81 @@ +#ifndef mitkEndoMacros_h +#define mitkEndoMacros_h + +/// +/// COLLECTION OF MACROS FOR THE ENDOTRACKING MODULE +/// + +/// +/// multiplexing for cv mats +/// +#define endoAccessCvMat(function, T, arg1, arg2) \ +if( arg2.type() == cv::DataType::type ) \ + function( arg1, arg2 ); \ +else if( arg2.type() == cv::DataType::type ) \ + function( arg1, arg2 ); \ +else if( arg2.type() == cv::DataType::type ) \ + function( arg1, arg2 ); \ +else if( arg2.type() == cv::DataType::type ) \ + function( arg1, arg2 ); \ +else if( arg2.type() == cv::DataType::type ) \ + function( arg1, arg2 ); \ +else if( arg2.type() == cv::DataType::type ) \ + function( arg1, arg2 ); \ +else if( arg2.type() == cv::DataType::type ) \ + function( arg1, arg2 ); \ +else if( arg2.type() == cv::DataType::type ) \ + function( arg1, arg2 ); \ +else \ + throw std::invalid_argument("Unknown type for cv::Mat"); + +/// +/// exec an algorithm with 1 output argument +/// +#define endoExec(macroAlgName, macroOutputType, macroOutputVarName, ...)\ + macroOutputType macroOutputVarName;\ + { \ + macroAlgName _macroAlgName(__VA_ARGS__, ¯oOutputVarName);\ + _macroAlgName.Update();\ + } + +/// +/// exec an algorithm with 2 output argument +/// +#define endoExec2(macroAlgName, macroOutputType1, macroOutputVarName1, macroOutputType2, macroOutputVarName2, ...)\ + macroOutputType1 macroOutputVarName1;\ + macroOutputType1 macroOutputVarName1;\ + { \ + macroAlgName _macroAlgName(__VA_ARGS__, ¯oOutputVarName1, ¯oOutputVarName2);\ + _macroAlgName.Update();\ + } + +/// +/// an assert macro for throwing exceptions from an assert +/// +#define endoAssert(a) if(!(a)) { \ +std::ostringstream s; \ +s << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " \ + << __LINE__ << ", failed: " << #a; \ +throw std::invalid_argument(s.str()); } + +/// +/// same as above but with an output error stream +/// use it like this: endoAssertMsg( file.read() == true, file << "could not be read" ); +/// +#define endoAssertMsg(a, msg) if(!(a)) { \ + std::ostringstream s; \ + s << mitk::EndoDebug::GetInstance().GetFilenameWithoutExtension(__FILE__) << ", " \ + << __LINE__ << ": " << msg; \ + throw std::invalid_argument(s.str()); \ + } + +/// +/// definition of the corresponding directory separator +/// +#ifdef WIN32 + static const std::string DIR_SEPARATOR = "\\"; +#else + static const std::string DIR_SEPARATOR = "/"; +#endif + +#endif // mitkEndoMacros_h diff --git a/Modules/CameraCalibration/mitkObservable.h b/Modules/CameraCalibration/mitkObservable.h new file mode 100644 index 0000000000..f1722f0486 --- /dev/null +++ b/Modules/CameraCalibration/mitkObservable.h @@ -0,0 +1,25 @@ +#ifndef mitkObservable_h +#define mitkObservable_h + +#include + +namespace mitk +{ + /// + /// filter "Observable" interface + /// + class Observable + { + public: + /// + /// this class garantuees to call Update() on + /// all observer if it changes + /// if you need more then one observer bundle + /// the algorithms in a BatchAlgorithm + /// + virtual void SetObserver( Algorithm* _Algorithm ) = 0; + }; + +} // namespace mitk + +#endif // mitkObservable_h diff --git a/Modules/CameraCalibration/mitkTransform.cpp b/Modules/CameraCalibration/mitkTransform.cpp new file mode 100644 index 0000000000..e3a8e9ffad --- /dev/null +++ b/Modules/CameraCalibration/mitkTransform.cpp @@ -0,0 +1,688 @@ +#include "mitkTransform.h" +#include +#include +#include +#include +#include +#include +namespace mitk +{ + + Transform::Transform() + : m_NavData(mitk::NavigationData::New()) + { + vnl_matrix_fixed rot; + rot.set_identity(); + this->SetRotation( rot ); + } + + Transform::Transform(const mitk::NavigationData* nd) + : m_NavData(mitk::NavigationData::New()) + { + m_NavData->Graft(nd); + } + + void Transform::Copy(const mitk::NavigationData* nd) + { + (const_cast(m_NavData.GetPointer()))->Graft(nd); + } + + void Transform::Concatenate( mitk::Transform* transform ) + { + vnl_matrix_fixed mat = transform->GetMatrix(); + mat = mat * this->GetMatrix(); // + this->SetMatrix( mat ); + } + + void Transform::Concatenate( const vnl_matrix_fixed& + transform ) + { + Transform::Pointer t = Transform::New(); + t->SetMatrix( transform ); + this->Concatenate( t ); + } + + void Transform::Concatenate( const vtkMatrix4x4* transform ) + { + Transform::Pointer t = Transform::New(); + t->SetMatrix( transform ); + this->Concatenate( t ); + } + + void Transform::SetOrientation( + const vnl_quaternion& orientation) + { + m_NavData->SetOrientation(orientation); + this->Modified(); + } + + void Transform::SetTranslation( const vnl_vector_fixed& + transl) + { + mitk::Point3D p; + for(unsigned int i=0; i<3; ++i) + p[i] = transl[i]; + + m_NavData->SetPosition(p); + this->Modified(); + } + + void Transform::SetTranslation( float* array ) + { + vnl_vector_fixed vec; + for(unsigned int i=0; iSetTranslation( vec ); + } + + void Transform::SetRotation( float* array ) + { + vnl_matrix_fixed mat; + + unsigned int row = 0; + unsigned int col = 0; + for(unsigned int i=0; i 0 && i % 3 == 0 ) + { + ++row; + col = 0; + } + + mat(row,col) = array[i]; + ++col; + } + + this->SetRotation( mat ); + } + + void Transform::SetOrientation( const vnl_quaternion& orientation) + { + vnl_vector_fixed qvec; + VnlVectorCaster caster( &orientation, &qvec ); + caster.Update(); + + mitk::Quaternion p( qvec ); + + this->SetOrientation( p ); + } + + vnl_vector_fixed Transform::GetVnlDoubleTranslation() const + { + vnl_vector_fixed vecFloat = this->GetVnlTranslation(); + vnl_vector_fixed vecDouble; + VnlVectorCaster caster( &vecFloat, &vecDouble ); + caster.Update(); + + return vecDouble; + } + + void Transform::SetTranslation( const vnl_vector& transl) + { + vnl_vector_fixed dTransl(transl); + vnl_vector_fixed fTransl; + VnlVectorCaster caster( &dTransl, &fTransl ); + caster.Update(); + + this->SetTranslation( fTransl ); + } + + vnl_quaternion Transform::GetVnlDoubleQuaternion() const + { + mitk::Quaternion fOrientation = this->GetOrientation(); + vnl_quaternion dOrientation; + VnlVectorCaster caster( &fOrientation, &dOrientation ); + caster.Update(); + + return dOrientation; + } + + void Transform::FromCSVFile(const std::string& file) + { + std::ifstream csvFile (file.c_str()); + endoAssert ( csvFile.fail() == false ); + + mitk::Transform::Pointer transform = mitk::Transform::New(); + vnl_matrix_fixed mat; + std::string line; + mitk::ScalarType d = 0.0f; + int row=0,column = 0; + + while (std::getline (csvFile, line)) + { + std::istringstream linestream(line); + std::string item; + column = 0; + while (std::getline (linestream, item, ',')) + { + std::istringstream number; + number.str(item); + number >> d; + mat(row, column) = d; + ++column; + } + ++row; + } + endoAssert( row == 4 && column == 4 ); + transform->SetMatrix( mat ); + + this->SetNavigationData( transform->GetNavigationData() ); + // modified is called in SetNavigationData + } + + std::string Transform::ToCSVString() const + { + std::ostringstream s; s.precision(12); + + vnl_matrix_fixed mat + = this->GetMatrix(); + + for( unsigned int j=0; j mat + = this->GetMatrix(); + + s << varname << " = ["; + for( unsigned int j=0; jGraft(transform->GetNavigationData()); + } + + mitk::Transform::Pointer Transform::Clone() const + { + Transform::Pointer copy = Transform::New(); + copy->Copy( this ); + return copy; + } + + void Transform::SetMatrix( const vtkMatrix4x4* mat) + { + vnl_matrix_fixed vnlMat; + for(unsigned int i=0; i<4; ++i) + for(unsigned int j=0; j<4; ++j) + vnlMat(i,j) = mat->GetElement(i, j); + + this->SetMatrix( vnlMat ); + } + + void Transform::ToCSVFile(const std::string& file) const + { + std::ofstream csvFile; + csvFile.open(file.c_str()); + endoAssert ( csvFile.fail() == false ); + csvFile << this->ToCSVString(); + csvFile.close(); + } + + void Transform::ToMatlabFile(const std::string& file + , const std::string& varname) const + { + std::ofstream csvFile; + csvFile.open(file.c_str()); + endoAssert ( csvFile.fail() == false ); + csvFile << this->ToMatlabString(varname); + csvFile.close(); + } + + void Transform::SetNavigationData( const mitk::NavigationData* naviData ) + { + endoAssert( naviData != 0 ); + m_NavData->Graft( naviData ); + this->Modified(); + } + + void Transform::SetRotation( vnl_matrix_fixed& mat) + { + this->m_NavData->SetOrientation( mitk::Quaternion(mat) ); + this->Modified(); + } + + void Transform::SetRotation( vnl_matrix& mat) + { + vnl_matrix_fixed tmp(mat); + this->SetRotation( tmp ); + } + + void Transform::SetPosition( const mitk::Point3D& transl) + { + this->SetTranslation( transl.GetVnlVector() ); + } + + void Transform::SetTranslation( double array[3] ) + { + mitk::Point3D p; + for(unsigned int i = 0; i < 3; ++i) + p.SetElement(i, array[i]); + this->SetTranslation( p.GetVnlVector() ); + } + + + void Transform::SetRotation( double array[3][3] ) + { + vnl_matrix_fixed mat; + + for(unsigned int i = 0; i < 3; ++i) + for(unsigned int j = 0; j < 3; ++j) + mat(i, j) = array[i][j]; + this->SetRotation( mat ); + } + + void Transform::Invert() + { + vnl_matrix_fixed tmp(this->GetMatrix()); + this->SetMatrix( vnl_inverse( tmp ) ); + } + + void Transform::SetMatrix( + const vnl_matrix_fixed& mat) + { + // set translation first + vnl_vector transl = mat.get_column(3); + mitk::Point3D p; + for(unsigned int i=0; i<3; ++i) + p[i] = transl[i]; + + m_NavData->SetPosition(p); + + // set rotation + vnl_matrix_fixed rotMatFixed( + mat.extract(3,3)); + this->SetRotation(rotMatFixed); + } + + bool Transform::IsValid() const + { + return m_NavData->IsDataValid(); + } + + void Transform::SetTranslation( const cv::Mat& transl) + { + vnl_vector vec(3); + VnlVectorFromCvMat _VnlVectorFromCvMat( &transl, &vec ); + _VnlVectorFromCvMat.Update(); + this->SetTranslation( vnl_vector_fixed( vec ) ); + } + + void Transform::SetRotation( const cv::Mat& mat ) + { + vnl_matrix vnlMat(3, 3); + VnlMatrixFromCvMat _VnlMatrixFromCvMat( &mat, &vnlMat ); + _VnlMatrixFromCvMat.Update(); + vnl_matrix_fixed vnlMatFixed(vnlMat); + + this->SetRotation(vnlMatFixed); + } + + void Transform::SetRotationVector( const cv::Mat& rotVec ) + { + cv::Mat rotMat; + cv::Rodrigues( rotVec, rotMat ); + + vnl_matrix vnlMat(3, 3); + VnlMatrixFromCvMat _VnlMatrixFromCvMat( &rotMat, &vnlMat ); + _VnlMatrixFromCvMat.Update(); + + + vnl_matrix_fixed vnlMatFixed(vnlMat); + + this->SetRotation( vnlMatFixed ); + } + + //# getter + mitk::NavigationData::Pointer Transform::GetNavigationData() const + { + return m_NavData; + } + + mitk::Point3D Transform::GetTranslation() const + { + return m_NavData->GetPosition(); + } + + mitk::Point3D Transform::GetPosition() const + { + return m_NavData->GetPosition(); + } + + mitk::Quaternion Transform::GetOrientation() const + { + return m_NavData->GetOrientation(); + } + + void Transform::GetMatrix(vtkMatrix4x4* matrix) const + { + vnl_matrix_fixed vnlMat = this->GetMatrix(); + for(unsigned int i=0; iSetElement(i,j, vnlMat(i,j)); + } + + void Transform::GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const + { + vnl_matrix vnlRotation + = this->GetVnlRotationMatrix().as_matrix(); + + // normalize rows of rotation matrix + vnlRotation.normalize_rows(); + + vnl_matrix vnlInverseRotation(3,3); + // invert rotation + vnlInverseRotation = vnl_matrix_inverse(vnlRotation); + + vnl_vector vnlTranslation + = this->GetPosition().GetVnlVector(); + // rotate translation vector by inverse rotation P = P' + vnlTranslation = vnlInverseRotation * vnlTranslation; + vnlTranslation *= -1; // save -P' + + // set position + mitk::Transform::Pointer tmp = mitk::Transform::New(); + + tmp->SetTranslation( vnlTranslation ); + tmp->SetRotation( vnlRotation ); + tmp->GetMatrix(matrix); + } + + //# cv getter + cv::Mat Transform::GetCvTranslation() const + { + cv::Mat mat; + vnl_vector vec = this->GetVnlTranslation().as_vector(); + endodebugvar( vec ) + CvMatFromVnlVector _CvMatFromVnlVector(&vec, &mat); + _CvMatFromVnlVector.Update(); + return mat; + } + + cv::Mat Transform::GetCvRotationMatrix() const + { + cv::Mat mat; + vnl_matrix vec = this->GetVnlRotationMatrix().as_matrix(); + endodebugvar( vec ) + CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); + _CvMatFromVnlMatrix.Update(); + return mat; + } + + cv::Mat Transform::GetCvMatrix() const + { + cv::Mat mat; + vnl_matrix vec = this->GetVnlRotationMatrix().as_matrix(); + CvMatFromVnlMatrix _CvMatFromVnlMatrix(&vec, &mat); + _CvMatFromVnlMatrix.Update(); + return mat; + } + + cv::Mat Transform::GetCvRotationVector() const + { + cv::Mat rotVec(3,1,cv::DataType::type); + cv::Rodrigues( this->GetCvRotationMatrix(), rotVec ); + return rotVec; + } + + //# vnl getter + vnl_vector_fixed Transform::GetVnlTranslation() const + { + vnl_vector_fixed vec(m_NavData->GetPosition() + .GetVnlVector()); + return vec; + } + + vnl_matrix_fixed Transform::GetVnlRotationMatrix() const + { + return m_NavData->GetOrientation().rotation_matrix_transpose(); + } + + vnl_matrix_fixed Transform::GetVnlDoubleMatrix() const + { + vnl_matrix_fixed mat = this->GetMatrix(); + + vnl_matrix_fixed doubleMat; + + for(unsigned int i=0; i( mat(i,j) ); + + return doubleMat; + } + + vnl_matrix_fixed Transform::GetMatrix() + const + { + vnl_vector_fixed transl = this->GetVnlTranslation(); + vnl_matrix_fixed rot = this->GetVnlRotationMatrix(); + + vnl_matrix_fixed homMat; + homMat.set_identity(); + //std::cout << homMat << std::endl; + for(unsigned int i=0; i rotMat = this->GetVnlRotationMatrix().transpose(); + this->SetRotation( rotMat ); + } + + void Transform::SetValid( bool valid ) + { + if( m_NavData->IsDataValid() == valid ) + return; + + m_NavData->SetDataValid( valid ); + this->Modified(); + } + + std::string mitk::Transform::ToString() const + { + std::ostringstream s; s.precision(12); + + mitk::NavigationData::PositionType position; + position.Fill(0.0); + position = m_NavData->GetPosition(); + + mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); + orientation = m_NavData->GetOrientation(); + + s << "Translation: [" << position[0] << ", " << position[1] << ", " + << position[2] << "]"; + s << ", orientation: [" << orientation[0] << ", " << orientation[1] << ", " + << orientation[2] << ", " << orientation[3] << "]"; + s << ", valid: [" << (this->IsValid()? "true": "false") << "]"; + + return s.str(); + } + + void mitk::Transform::ToXML(TiXmlElement* elem) const + { + std::string value = elem->ValueStr(); + if(value.empty()) + elem->SetValue(this->GetNameOfClass()); + + mitk::NavigationData::PositionType position; + position.Fill(0.0); + position = m_NavData->GetPosition(); + + mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); + orientation = m_NavData->GetOrientation(); + + mitk::NavigationData::CovarianceMatrixType matrix; + matrix.SetIdentity(); + matrix = m_NavData->GetCovErrorMatrix(); + + bool hasPosition = true; + hasPosition = m_NavData->GetHasPosition(); + bool hasOrientation = true; + hasOrientation = m_NavData->GetHasOrientation(); + bool dataValid = false; + dataValid = m_NavData->IsDataValid(); + mitk::NavigationData::TimeStampType timestamp=0.0; + + elem->SetDoubleAttribute("Time", timestamp); + elem->SetDoubleAttribute("X", position[0]); + elem->SetDoubleAttribute("Y", position[1]); + elem->SetDoubleAttribute("Z", position[2]); + + elem->SetDoubleAttribute("QX", orientation[0]); + elem->SetDoubleAttribute("QY", orientation[1]); + elem->SetDoubleAttribute("QZ", orientation[2]); + elem->SetDoubleAttribute("QR", orientation[3]); + + elem->SetDoubleAttribute("C00", matrix[0][0]); + elem->SetDoubleAttribute("C01", matrix[0][1]); + elem->SetDoubleAttribute("C02", matrix[0][2]); + elem->SetDoubleAttribute("C03", matrix[0][3]); + elem->SetDoubleAttribute("C04", matrix[0][4]); + elem->SetDoubleAttribute("C05", matrix[0][5]); + elem->SetDoubleAttribute("C10", matrix[1][0]); + elem->SetDoubleAttribute("C11", matrix[1][1]); + elem->SetDoubleAttribute("C12", matrix[1][2]); + elem->SetDoubleAttribute("C13", matrix[1][3]); + elem->SetDoubleAttribute("C14", matrix[1][4]); + elem->SetDoubleAttribute("C15", matrix[1][5]); + + if (dataValid) + elem->SetAttribute("Valid",1); + else + elem->SetAttribute("Valid",0); + + if (hasOrientation) + elem->SetAttribute("hO",1); + else + elem->SetAttribute("hO",0); + + if (hasPosition) + elem->SetAttribute("hP",1); + else + elem->SetAttribute("hP",0); + } + + void mitk::Transform::FromXML(TiXmlElement* elem) + { + assert(elem); + + mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); + mitk::NavigationData::PositionType position; + mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); + mitk::NavigationData::TimeStampType timestamp = -1; + mitk::NavigationData::CovarianceMatrixType matrix; + + bool hasPosition = true; + bool hasOrientation = true; + bool dataValid = false; + + position.Fill(0.0); + matrix.SetIdentity(); + + elem->QueryDoubleAttribute("Time",×tamp); + + // position and orientation is mandatory! + if(elem->QueryFloatAttribute("X", &position[0]) != TIXML_SUCCESS) + throw std::invalid_argument("No X position found in xml"); + if(elem->QueryFloatAttribute("Y", &position[1]) != TIXML_SUCCESS) + throw std::invalid_argument("No Y position found in xml"); + if(elem->QueryFloatAttribute("Z", &position[2]) != TIXML_SUCCESS) + throw std::invalid_argument("No Z position found in xml"); + + if(elem->QueryFloatAttribute("QX", &orientation[0]) != TIXML_SUCCESS) + throw std::invalid_argument("No QX orientation found in xml"); + if(elem->QueryFloatAttribute("QY", &orientation[1]) != TIXML_SUCCESS) + throw std::invalid_argument("No QY orientation found in xml"); + if(elem->QueryFloatAttribute("QZ", &orientation[2]) != TIXML_SUCCESS) + throw std::invalid_argument("No QZ orientation found in xml"); + if(elem->QueryFloatAttribute("QR", &orientation[3]) != TIXML_SUCCESS) + throw std::invalid_argument("No QR orientation found in xml"); + + elem->QueryFloatAttribute("C00", &matrix[0][0]); + elem->QueryFloatAttribute("C01", &matrix[0][1]); + elem->QueryFloatAttribute("C02", &matrix[0][2]); + elem->QueryFloatAttribute("C03", &matrix[0][3]); + elem->QueryFloatAttribute("C04", &matrix[0][4]); + elem->QueryFloatAttribute("C05", &matrix[0][5]); + elem->QueryFloatAttribute("C10", &matrix[1][0]); + elem->QueryFloatAttribute("C11", &matrix[1][1]); + elem->QueryFloatAttribute("C12", &matrix[1][2]); + elem->QueryFloatAttribute("C13", &matrix[1][3]); + elem->QueryFloatAttribute("C14", &matrix[1][4]); + elem->QueryFloatAttribute("C15", &matrix[1][5]); + + int tmpval = 0; + elem->QueryIntAttribute("Valid", &tmpval); + if (tmpval == 0) + dataValid = false; + else + dataValid = true; + + tmpval = 0; + elem->QueryIntAttribute("hO", &tmpval); + if (tmpval == 0) + hasOrientation = false; + else + hasOrientation = true; + + tmpval = 0; + elem->QueryIntAttribute("hP", &tmpval); + if (tmpval == 0) + hasPosition = false; + else + hasPosition = true; + + nd->SetTimeStamp(timestamp); + nd->SetPosition(position); + nd->SetOrientation(orientation); + nd->SetCovErrorMatrix(matrix); + nd->SetDataValid(dataValid); + nd->SetHasOrientation(hasOrientation); + nd->SetHasPosition(hasPosition); + + m_NavData = nd; + this->Modified(); + } + +} // namespace mitk + +std::ostream& operator<< (std::ostream& os, mitk::Transform::Pointer p) +{ + os << p->ToString(); + return os; +} diff --git a/Modules/CameraCalibration/mitkTransform.h b/Modules/CameraCalibration/mitkTransform.h new file mode 100644 index 0000000000..798d53ebc7 --- /dev/null +++ b/Modules/CameraCalibration/mitkTransform.h @@ -0,0 +1,257 @@ +#ifndef MITKTRANSFORM_H +#define MITKTRANSFORM_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mitk { + + /// + /// \brief class representing a transfrom in 3D + /// + /// internally it stores a mitk navigation data. this is more + /// or less a wrapper for navigation data for easy casting + /// between opencv/vnl/mitk/xml representations of transform + /// data + /// + class mitkCameraCalibration_EXPORT Transform: public itk::Object, + public XMLSerializable + { + public: + mitkClassMacro(Transform, itk::Object); + itkFactorylessNewMacro(Transform); + mitkNewMacro1Param(Transform, const mitk::NavigationData*); + + /// + /// Copies the content of transform to this + /// instance + /// + void Copy( const mitk::Transform* transform ); + + /// + /// Copies the content of transform to this + /// instance + /// + void Copy( const mitk::NavigationData* transform ); + + /// + /// Inverts the rotation of this transform + /// (Polaris navigation Data have inverted rotation + /// so you may want to call this function when using + /// polaris data) + /// + void TransposeRotation(); + + /// + /// get a copy of this transform + /// + mitk::Transform::Pointer Clone() const; + + /// + /// concatenate this transform with the given one, + /// i.e. this transform is done first, then transform + /// ( if x is this transform, y is transform, then this will be y*x) + /// post multiply semantics! + /// \see vtkTransform + /// + void Concatenate( mitk::Transform* transform ); + /// + /// same as above with vnl mat argument + /// + void Concatenate( const vnl_matrix_fixed& transform ); + + /// + /// same as above with vtk mat argument + /// + void Concatenate( const vtkMatrix4x4* transform ); + + /// + /// invert this transform + /// + void Invert(); + + /// + /// read from xml + /// + void FromXML(TiXmlElement* elem); + /// + /// read csv file + /// + void FromCSVFile(const std::string& file); + /// + /// grafts the data from naviData to this transform + /// + void SetNavigationData( const mitk::NavigationData* naviData ); + /// + /// method to set orientation quat + /// + void SetOrientation( const vnl_quaternion& orientation); + /// + /// method to set double valued orientation quat + /// + void SetOrientation( const vnl_quaternion& orientation); + /// + /// method to set translation + /// + void SetTranslation( const vnl_vector_fixed& transl); + /// + /// method to set a vector of doubles as translation + /// + void SetTranslation( const vnl_vector& transl); + /// + /// method to set a mitk::Point3D as position + /// + void SetPosition( const mitk::Point3D& transl); + /// + /// sets rotation with a rotation matrix + /// + void SetRotation( vnl_matrix_fixed& mat); + /// + /// sets rotation with a non fixed rotation matrix + /// + void SetRotation( vnl_matrix& mat); + /// + /// sets rotation and translation with a transformation matrix + /// + void SetMatrix( const vnl_matrix_fixed& mat); + /// + /// sets rotation and translation with a vtk transformation matrix + /// + void SetMatrix( const vtkMatrix4x4* mat); + /// + /// sets translation from a POD vector + /// + void SetTranslation( float* array ); + /// + /// sets translation from a POD vector. this must be a + /// 3x3=9 sized vector in row major format (first row = first + /// three elements) + /// + void SetRotation( float* array ); + /// + /// sets translation from a POD vector + /// + void SetTranslation( double array[3] ); + /// + /// sets translation from a POD vector + /// + void SetRotation( double array[3][3] ); + + /// + /// method to set translation by cv vector + /// + void SetTranslation( const cv::Mat& transl); + /// + /// sets rotation with a rotation matrix + /// + void SetRotation( const cv::Mat& mat ); + /// + /// sets rotation with a rodrigues rotation vector + /// + void SetRotationVector( const cv::Mat& rotVec); + + /// + /// \return the navigation data that stores all information + /// + mitk::NavigationData::Pointer GetNavigationData() const; + /// + /// calls navigationdata::GetPosition() + /// + mitk::Point3D GetPosition() const; + /// + /// same as GetPosition + /// + mitk::Point3D GetTranslation() const; + /// + /// calls navigationdata::IsValid() + /// + bool IsValid() const; + /// + /// calls navigationdata::SetValid() + /// + void SetValid(bool valid); + + /// + /// calls navigationdata::GetOrientation() + /// + mitk::Quaternion GetOrientation() const; + + /// + /// \return the homogeneous matrix representing this transform + /// + vnl_matrix_fixed GetMatrix() const; + /// + /// \return the homogeneous vtk matrix representing this transform + /// + void GetMatrix(vtkMatrix4x4* matrix) const; + /// + /// \return the homogeneous vtk matrix representing this transform + /// in !OpenGL! left handed coordinate system + /// + void GetVtkOpenGlMatrix(vtkMatrix4x4* matrix) const; + + /// + /// create xml representation + /// + void ToXML(TiXmlElement* elem) const; + /// + /// create string representation + /// + std::string ToString() const; + /// + /// create string csv representation (only the transformation values!!!!) + /// + std::string ToCSVString() const; + /// + /// create matlab representation + /// + std::string ToMatlabString(const std::string& varname="transform", + bool printLastRow=true) const; + /// + /// write csv representation to file (only the transformation values!!!!) + /// + void ToCSVFile(const std::string& file) const; + /// + /// write matlab representation to file + /// + void ToMatlabFile(const std::string& file + , const std::string& varname="transform") const; + /// + /// conversion to cv types + /// + cv::Mat GetCvTranslation() const; + cv::Mat GetCvRotationVector() const; + cv::Mat GetCvRotationMatrix() const; + cv::Mat GetCvMatrix() const; + + /// + /// conversion to vnl types + /// + vnl_vector_fixed GetVnlTranslation() const; + vnl_vector_fixed GetVnlDoubleTranslation() const; + vnl_quaternion GetVnlDoubleQuaternion() const; + vnl_matrix_fixed GetVnlRotationMatrix() const; + vnl_matrix_fixed GetVnlDoubleMatrix() const; + + protected: + Transform(); + Transform(const mitk::NavigationData* nd); + + // everything is stored here + mitk::NavigationData::Pointer m_NavData; +}; + +} // namespace mitk + +mitkCameraCalibration_EXPORT std::ostream& operator<< + (std::ostream& os, mitk::Transform::Pointer p); + +#endif // MITKTRANSFORM_H diff --git a/Modules/CameraCalibration/mitkVnlMatrixFromCvMat.h b/Modules/CameraCalibration/mitkVnlMatrixFromCvMat.h new file mode 100644 index 0000000000..c21d33422a --- /dev/null +++ b/Modules/CameraCalibration/mitkVnlMatrixFromCvMat.h @@ -0,0 +1,64 @@ +#ifndef mitkVnlMatrixFromCvMat_h +#define mitkVnlMatrixFromCvMat_h + +#include +#include +#include +#include +#include +#include + +namespace mitk +{ + /// + /// create a vnl_matrix from a cv mat + /// + template + class VnlMatrixFromCvMat: + virtual public Algorithm + { + public: + /// + /// init default values and save references + /// + VnlMatrixFromCvMat( + const cv::Mat* _CvMat, + vnl_matrix* _VnlMatrix): + m_CvMat(_CvMat), + m_VnlMatrix(_VnlMatrix) + { + } + + + /// + /// cv mat to vnl matrix with known cv type + /// + template + void ToVnlMatrix( vnl_matrix& vnlMat, const cv::Mat& mat ) + { + vnlMat.set_size( mat.rows, mat.cols ); + for(int i=0; i( mat.at(i,j) ); + } + + /// + /// executes the Algorithm + /// + void Update() + { + endoAccessCvMat( ToVnlMatrix, T, (*m_VnlMatrix), (*m_CvMat) ); + } + private: + /// + /// VnlMatrixFromCvMat input member variable + /// + const cv::Mat* m_CvMat; + /// + /// VnlMatrixFromCvMat output member variable + /// + vnl_matrix* m_VnlMatrix; + }; +} // namespace mitk + +#endif // mitkVnlMatrixFromCvMat_h diff --git a/Modules/CameraCalibration/mitkVnlVectorCaster.h b/Modules/CameraCalibration/mitkVnlVectorCaster.h new file mode 100644 index 0000000000..85f946c919 --- /dev/null +++ b/Modules/CameraCalibration/mitkVnlVectorCaster.h @@ -0,0 +1,51 @@ +#ifndef mitkVnlVectorCaster_h +#define mitkVnlVectorCaster_h + +#include +#include +#include +#include + +namespace mitk +{ + /// + /// class for casting vnl vectors to another basic type + /// by means of static cast + /// + template + class VnlVectorCaster: + virtual public Algorithm + { + public: + /// + /// init default values and save references + /// + VnlVectorCaster( + const vnl_vector_fixed* _InputVector, + vnl_vector_fixed* _OutputVector): + m_InputVector(_InputVector), + m_OutputVector(_OutputVector) + { + } + /// + /// executes the Algorithm + /// + void Update() + { + for( size_t i=0; isize(); ++i ) + (*m_OutputVector)[i] = static_cast( (*m_InputVector)[i] ); + + } + private: + /// + /// VnlVectorCaster input member variable + /// + const vnl_vector_fixed* m_InputVector; + /// + /// VnlVectorCaster output member variable + /// + vnl_vector_fixed* m_OutputVector; + }; +} // namespace mitk + +#endif // mitkVnlVectorCaster_h diff --git a/Modules/CameraCalibration/mitkVnlVectorFromCvMat.h b/Modules/CameraCalibration/mitkVnlVectorFromCvMat.h new file mode 100644 index 0000000000..f556b9782f --- /dev/null +++ b/Modules/CameraCalibration/mitkVnlVectorFromCvMat.h @@ -0,0 +1,57 @@ +#ifndef mitkVnlVectorFromCvMat_h +#define mitkVnlVectorFromCvMat_h + +#include +#include + +namespace mitk +{ + /// + /// create a vnl_vector from a cv mat + /// + template + class VnlVectorFromCvMat: + virtual public Algorithm + { + public: + /// + /// init default values and save references + /// + VnlVectorFromCvMat( + const cv::Mat* _CvMat, + vnl_vector* _VnlVector): + m_VnlMatrixFromCvMat( _CvMat, &m_VnlMatrix ), + m_VnlVector(_VnlVector) + { + } + + /// + /// executes the Algorithm + /// + void Update() + { + m_VnlMatrixFromCvMat.Update(); + + if( m_VnlMatrix.rows() == 1 ) + *m_VnlVector = m_VnlMatrix.get_row(0); + else if( m_VnlMatrix.cols() == 1 ) + *m_VnlVector = m_VnlMatrix.get_column(0); + + } + private: + /// + /// VnlVectorFromCvMat input member variable + /// + vnl_matrix m_VnlMatrix; + /// + /// internal algorithm to get a vnl matrix from a cv mat + /// + VnlMatrixFromCvMat m_VnlMatrixFromCvMat; + /// + /// VnlVectorFromCvMat output member variable + /// + vnl_vector* m_VnlVector; + }; +} // namespace mitk + +#endif // mitkVnlVectorFromCvMat_h diff --git a/Modules/CameraCalibration/mitkXMLSerializable.cpp b/Modules/CameraCalibration/mitkXMLSerializable.cpp new file mode 100644 index 0000000000..85b7dd5513 --- /dev/null +++ b/Modules/CameraCalibration/mitkXMLSerializable.cpp @@ -0,0 +1,126 @@ +#include +#include "mitkEndoDebug.h" +#include "mitkEndoMacros.h" +#include + +namespace mitk +{ + const std::string XMLSerializable::FILE_REFERENCE_ATTRIBUTE_NAME = "fileRef"; + const std::string XMLSerializable::ROOT_NAME = "data"; + + void mitk::XMLSerializable::ToXMLFile(const std::string& file + , const std::string& elemName) + { + TiXmlElement * rootElem=0; + TiXmlElement * element=0; + + // determine element to write to + std::string elementName = elemName; + if(elementName.empty()) + elementName = this->GetNameOfClass(); + + TiXmlDocument doc( file.c_str() ); + bool loadOkay = doc.LoadFile(); + // if the document already exists ... + if(loadOkay) + { + // try to identify the XML element of this class as the root + // or as the child of the root + rootElem = doc.RootElement(); + endoAssertMsg( rootElem, "No root element found in " << file ); + + // if root element represents this element remove the root + if( rootElem->ValueStr() == elementName ) + { + doc.RemoveChild(rootElem); + rootElem = 0; + } + else + { + // if it is a child of the root remove it too + element = rootElem->FirstChildElement(elementName); + if(element) + rootElem->RemoveChild(element); + } + } + else + { + // document did not exist, create new one with declration + TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" ); + doc.LinkEndChild( decl ); + } + + m_XMLFileName = file; + + // create element (if the document already exists this element was removed) + element = new TiXmlElement( elementName ); + this->ToXML( element ); + + // if we do not have a root element create a new one + if(!rootElem) + rootElem = new TiXmlElement( ROOT_NAME ); + // add the element node as child + rootElem->LinkEndChild(element); + + // if no root element exists, add it now + if(doc.RootElement() == 0) + doc.LinkEndChild( rootElem ); + + if(!doc.SaveFile( file )) + { + std::ostringstream s; s << "File " << file + << " could not be written. Please check permissions."; + throw std::logic_error(s.str()); + } + } + + std::string mitk::XMLSerializable::GetXMLFileName() const + { + return m_XMLFileName; + } + + void mitk::XMLSerializable::FromXMLFile(const std::string& file + , const std::string& elemName) + { + endodebug( "Trying to read from " << file ) + + TiXmlDocument doc( file.c_str() ); + bool loadOkay = doc.LoadFile(); + if(!loadOkay) + { + std::ostringstream s; s << "File " << file + << " could not be loaded!"; + throw std::logic_error(s.str().c_str()); + } + + m_XMLFileName = file; + + TiXmlElement* elem = doc.FirstChildElement(); + endoAssertMsg( elem, "No root element found" ); + + // determine element to read from + std::string elementName = elemName; + if(elementName.empty()) + elementName = this->GetNameOfClass(); + // try again with the first element + if(strcmp(elem->Value(), elementName.c_str()) != 0) + elem = elem->FirstChildElement(elementName.c_str()); + + endoAssertMsg( elem, "No child element \"" << elementName << + "\" found in " << file ); + + // if theres an attribute as file reference try to load the class + // from that file + std::string filename; + if(elem->QueryStringAttribute(FILE_REFERENCE_ATTRIBUTE_NAME.c_str(), &filename) + == TIXML_SUCCESS) + { + if( !itksys::SystemTools::FileIsFullPath(filename.c_str()) ) + filename = itksys::SystemTools::GetFilenamePath(file) + "/" + filename; + this->FromXMLFile(filename); + return; // exit! + } + + this->FromXML( elem ); + } +} diff --git a/Modules/CameraCalibration/mitkXMLSerializable.h b/Modules/CameraCalibration/mitkXMLSerializable.h new file mode 100644 index 0000000000..9f5ad5b356 --- /dev/null +++ b/Modules/CameraCalibration/mitkXMLSerializable.h @@ -0,0 +1,77 @@ +#ifndef MITKXMLSerializable_H +#define MITKXMLSerializable_H + +#include +#include +#include +#include +#include + +namespace mitk +{ + /// + /// \brief interface for all classes able to write themselves to XML files + /// + class mitkCameraCalibration_EXPORT XMLSerializable + { + public: + /// + /// value of the special tag for file references + /// if this is attribute is found the class + /// will be loaded from the file in the attributes value + /// + static const std::string FILE_REFERENCE_ATTRIBUTE_NAME; + /// + /// the name of the root node that is created when the element is saved + /// + static const std::string ROOT_NAME; + /// + /// the tag value will be equals to the class name (function + /// implemented by the itkTypeMacro) + /// + virtual const char* GetNameOfClass() const = 0; + + /// + /// write your values here to elem + /// + virtual void ToXML(TiXmlElement* elem) const = 0; + /// + /// read your values here from elem + /// + virtual void FromXML(TiXmlElement* elem) = 0; + + /// + /// tries to write the xml data obtained in ToXML() to file + /// + virtual void ToXMLFile(const std::string& file + , const std::string& elemName=""); + + /// + /// loads the XML file and calls FromXML() + /// takes the first child of the document + /// if this root node value is not equal to GetNameOfClass() + /// the method will try to find the first children of the root + /// node with the value of GetNameOfClass() + /// if elemName is not empty then this value will be used instead + /// of GetNameOfClass() + /// if this node is found it will check if an attribute named + /// FILE_REFERENCE_ATTRIBUTE_NAME is found: in this case + /// the method calls itself with this attributes value as parameter + /// + virtual void FromXMLFile(const std::string& file + , const std::string& elemName=""); + + /// + /// \see m_XMLFileName + /// + std::string GetXMLFileName() const; + + private: + /// + /// saves the xmlfile name set for this serializable ( in FromXMLFile() ) + /// + std::string m_XMLFileName; + }; +} + +#endif