Commit bb6924d0 authored by Matt Clarkson's avatar Matt Clarkson

Issue #5353: Fixes to save regardless of calibration.

parent f2289b3c
...@@ -1632,13 +1632,16 @@ double NiftyCalVideoCalibrationManager::GetStereoRMSReconstructionError(const cv ...@@ -1632,13 +1632,16 @@ double NiftyCalVideoCalibrationManager::GetStereoRMSReconstructionError(const cv
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
std::string NiftyCalVideoCalibrationManager::Calibrate() bool NiftyCalVideoCalibrationManager::Calibrate()
{ {
bool isSuccessful = false;
std::ostringstream message; std::ostringstream message;
message << "Calibrating with " << m_NumberOfSnapshotsForCalibrating message << "Calibrating with " << m_NumberOfSnapshotsForCalibrating
<< " sample" << (m_NumberOfSnapshotsForCalibrating > 1 ? "s" : "") << " sample" << (m_NumberOfSnapshotsForCalibrating > 1 ? "s" : "")
<< std::endl; << std::endl;
m_CalibrationResult = message.str(); m_CalibrationResult = message.str();
m_CalibrationErrorMessage = "";
try try
{ {
...@@ -1953,22 +1956,38 @@ std::string NiftyCalVideoCalibrationManager::Calibrate() ...@@ -1953,22 +1956,38 @@ std::string NiftyCalVideoCalibrationManager::Calibrate()
this->UpdateDisplayNodes(); this->UpdateDisplayNodes();
// Save successful calibrations. // Save successful calibrations.
this->Save(); isSuccessful = true;
this->Save(isSuccessful);
}
catch (niftk::NiftyCalException& e)
{
m_CalibrationErrorMessage = e.GetDescription();
MITK_ERROR << "ERROR: Calibration failed:" << e.GetDescription();
}
catch (mitk::Exception& e)
{
m_CalibrationErrorMessage = e.GetDescription();
MITK_ERROR << "ERROR: Calibration failed:" << e.GetDescription();
} }
catch (std::exception& e) catch (std::exception& e)
{
m_CalibrationErrorMessage = e.what();
MITK_ERROR << "ERROR: Calibration failed:" << e.what();
}
if (!isSuccessful)
{ {
std::ostringstream message; std::ostringstream message;
message << "ERROR: Calibration failed: " << e.what() << std::endl; message << "CalibrationFailed: " << m_CalibrationErrorMessage << std::endl;
m_CalibrationResult += message.str(); m_CalibrationResult += message.str();
if (this->GetSaveOutputRegardlessOfCalibration()) if (this->GetSaveOutputRegardlessOfCalibration())
{ {
this->Save(); this->Save(isSuccessful);
} }
} }
MITK_INFO << m_CalibrationResult; MITK_INFO << m_CalibrationResult;
return m_CalibrationResult; return isSuccessful;
} }
...@@ -2135,7 +2154,7 @@ void NiftyCalVideoCalibrationManager::LoadCalibrationFromDirectory(const std::st ...@@ -2135,7 +2154,7 @@ void NiftyCalVideoCalibrationManager::LoadCalibrationFromDirectory(const std::st
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void NiftyCalVideoCalibrationManager::Save() void NiftyCalVideoCalibrationManager::Save(bool isSuccessful)
{ {
if (m_ImageNode[0].IsNull()) if (m_ImageNode[0].IsNull())
{ {
...@@ -2163,148 +2182,158 @@ void NiftyCalVideoCalibrationManager::Save() ...@@ -2163,148 +2182,158 @@ void NiftyCalVideoCalibrationManager::Save()
mitkThrow() << "Failed to create directory:" << m_OutputDirName; mitkThrow() << "Failed to create directory:" << m_OutputDirName;
} }
niftk::SaveNifTKIntrinsics(m_Intrinsic[0], m_Distortion[0], m_OutputDirName + "calib.left.intrinsic.txt");
this->SaveImages("calib.left.images.", m_OriginalImages[0]); this->SaveImages("calib.left.images.", m_OriginalImages[0]);
this->SavePoints("calib.left.points.", m_Points[0]); this->SavePoints("calib.left.points.", m_Points[0]);
if (m_ImageNode[1].IsNotNull()) if (m_ImageNode[1].IsNotNull())
{ {
niftk::SaveNifTKIntrinsics(
m_Intrinsic[1], m_Distortion[1], m_OutputDirName + "calib.right.intrinsic.txt");
niftk::SaveNifTKStereoExtrinsics(
m_LeftToRightRotationMatrix, m_LeftToRightTranslationVector, m_OutputDirName + "calib.r2l.txt");
this->SaveImages("calib.right.images.", m_OriginalImages[1]); this->SaveImages("calib.right.images.", m_OriginalImages[1]);
this->SavePoints("calib.right.points.", m_Points[1]); this->SavePoints("calib.right.points.", m_Points[1]);
} }
if (m_ImageNode[0].IsNotNull()) if (m_TrackingTransformNode.IsNotNull())
{ {
int counter = 0; int counter = 0;
std::list<cv::Matx44d> leftCams = this->ExtractCameraMatrices(0);
std::list<cv::Matx44d >::const_iterator iter; std::list<cv::Matx44d >::const_iterator iter;
for (iter = leftCams.begin(); for (iter = m_TrackingMatrices.begin();
iter != leftCams.end(); iter != m_TrackingMatrices.end();
++iter ++iter
) )
{ {
std::ostringstream fileName; std::ostringstream fileName;
fileName << m_OutputDirName << "calib.left.camera." << counter++ << ".4x4"; fileName << m_OutputDirName << "calib.tracking." << counter++ << ".4x4";
niftk::Save4x4Matrix(*iter, fileName.str()); niftk::Save4x4Matrix(*iter, fileName.str());
} }
} }
if (m_ImageNode[1].IsNotNull()) if (m_ModelTransformNode.IsNotNull())
{ {
int counter = 0; int counter = 0;
std::list<cv::Matx44d> rightCams = this->ExtractCameraMatrices(1);
std::list<cv::Matx44d >::const_iterator iter; std::list<cv::Matx44d >::const_iterator iter;
for (iter = rightCams.begin(); for (iter = m_ModelTrackingMatrices.begin();
iter != rightCams.end(); iter != m_ModelTrackingMatrices.end();
++iter ++iter
) )
{ {
std::ostringstream fileName; std::ostringstream fileName;
fileName << m_OutputDirName << "calib.right.camera." << counter++ << ".4x4"; fileName << m_OutputDirName << "calib.tracking.model." << counter++ << ".4x4";
niftk::Save4x4Matrix(*iter, fileName.str()); niftk::Save4x4Matrix(*iter, fileName.str());
} }
} }
if (m_TrackingTransformNode.IsNotNull()) // Write main results to file.
std::string outputMessageFileName = m_OutputDirName + "calib.result.log";
std::ofstream outputMessageFile;
outputMessageFile.open(outputMessageFileName, std::ofstream::out);
if (!outputMessageFile.is_open())
{ {
int counter = 0; mitkThrow() << "Failed to open file:" << outputMessageFileName << " for writing.";
std::list<cv::Matx44d >::const_iterator iter; }
for (iter = m_TrackingMatrices.begin(); outputMessageFile << m_CalibrationResult << std::endl;
iter != m_TrackingMatrices.end(); outputMessageFile.close();
++iter
) MITK_INFO << "Saving calibration to:" << m_OutputDirName << ": - DONE.";
if (isSuccessful)
{
niftk::SaveNifTKIntrinsics(m_Intrinsic[0], m_Distortion[0], m_OutputDirName + "calib.left.intrinsic.txt");
if (m_ImageNode[1].IsNotNull())
{ {
std::ostringstream fileName; niftk::SaveNifTKIntrinsics(
fileName << m_OutputDirName << "calib.tracking." << counter++ << ".4x4"; m_Intrinsic[1], m_Distortion[1], m_OutputDirName + "calib.right.intrinsic.txt");
niftk::Save4x4Matrix(*iter, fileName.str());
niftk::SaveNifTKStereoExtrinsics(
m_LeftToRightRotationMatrix, m_LeftToRightTranslationVector, m_OutputDirName + "calib.r2l.txt");
}
if (m_ImageNode[0].IsNotNull())
{
int counter = 0;
std::list<cv::Matx44d> leftCams = this->ExtractCameraMatrices(0);
std::list<cv::Matx44d >::const_iterator iter;
for (iter = leftCams.begin();
iter != leftCams.end();
++iter
)
{
std::ostringstream fileName;
fileName << m_OutputDirName << "calib.left.camera." << counter++ << ".4x4";
niftk::Save4x4Matrix(*iter, fileName.str());
}
}
if (m_ImageNode[1].IsNotNull())
{
int counter = 0;
std::list<cv::Matx44d> rightCams = this->ExtractCameraMatrices(1);
std::list<cv::Matx44d >::const_iterator iter;
for (iter = rightCams.begin();
iter != rightCams.end();
++iter
)
{
std::ostringstream fileName;
fileName << m_OutputDirName << "calib.right.camera." << counter++ << ".4x4";
niftk::Save4x4Matrix(*iter, fileName.str());
}
} }
// We deliberately output all hand-eye matrices, and additionally, whichever one was preferred method. if (m_TrackingTransformNode.IsNotNull())
niftk::Save4x4Matrix(m_HandEyeMatrices[0][0].inv(), m_OutputDirName {
// We deliberately output all hand-eye matrices, and additionally, whichever one was preferred method.
niftk::Save4x4Matrix(m_HandEyeMatrices[0][0].inv(), m_OutputDirName
+ "calib.left.eyehand.tsai.txt"); + "calib.left.eyehand.tsai.txt");
niftk::Save4x4Matrix(m_HandEyeMatrices[0][1].inv(), m_OutputDirName niftk::Save4x4Matrix(m_HandEyeMatrices[0][1].inv(), m_OutputDirName
+ "calib.left.eyehand.shahidi.txt"); + "calib.left.eyehand.shahidi.txt");
niftk::Save4x4Matrix(m_HandEyeMatrices[0][2].inv(), m_OutputDirName niftk::Save4x4Matrix(m_HandEyeMatrices[0][2].inv(), m_OutputDirName
+ "calib.left.eyehand.malti.txt"); + "calib.left.eyehand.malti.txt");
niftk::Save4x4Matrix(m_HandEyeMatrices[0][3].inv(), m_OutputDirName niftk::Save4x4Matrix(m_HandEyeMatrices[0][3].inv(), m_OutputDirName
+ "calib.left.eyehand.allextrinsic.txt"); + "calib.left.eyehand.allextrinsic.txt");
niftk::Save4x4Matrix(m_HandEyeMatrices[0][m_HandeyeMethod].inv(), m_OutputDirName niftk::Save4x4Matrix(m_HandEyeMatrices[0][m_HandeyeMethod].inv(), m_OutputDirName
+ "calib.left.eyehand.current.txt"); + "calib.left.eyehand.current.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[0][0].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[0][0].inv(), m_OutputDirName
+ "calib.left.eyehand.tsai.params.txt"); + "calib.left.eyehand.tsai.params.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[0][1].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[0][1].inv(), m_OutputDirName
+ "calib.left.eyehand.shahidi.params.txt"); + "calib.left.eyehand.shahidi.params.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[0][2].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[0][2].inv(), m_OutputDirName
+ "calib.left.eyehand.malti.params.txt"); + "calib.left.eyehand.malti.params.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[0][3].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[0][3].inv(), m_OutputDirName
+ "calib.left.eyehand.allextrinsic.params.txt"); + "calib.left.eyehand.allextrinsic.params.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[0][m_HandeyeMethod].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[0][m_HandeyeMethod].inv(), m_OutputDirName
+ "calib.left.eyehand.current.params.txt"); + "calib.left.eyehand.current.params.txt");
if (m_ImageNode[1].IsNotNull()) if (m_ImageNode[1].IsNotNull())
{ {
// We deliberately output all hand-eye matrices, and additionally, whichever one was preferred method. // We deliberately output all hand-eye matrices, and additionally, whichever one was preferred method.
niftk::Save4x4Matrix(m_HandEyeMatrices[1][0].inv(), m_OutputDirName niftk::Save4x4Matrix(m_HandEyeMatrices[1][0].inv(), m_OutputDirName
+ "calib.right.eyehand.tsai.txt"); + "calib.right.eyehand.tsai.txt");
niftk::Save4x4Matrix(m_HandEyeMatrices[1][1].inv(), m_OutputDirName niftk::Save4x4Matrix(m_HandEyeMatrices[1][1].inv(), m_OutputDirName
+ "calib.right.eyehand.shahidi.txt"); + "calib.right.eyehand.shahidi.txt");
niftk::Save4x4Matrix(m_HandEyeMatrices[1][2].inv(), m_OutputDirName niftk::Save4x4Matrix(m_HandEyeMatrices[1][2].inv(), m_OutputDirName
+ "calib.right.eyehand.malti.txt"); + "calib.right.eyehand.malti.txt");
niftk::Save4x4Matrix(m_HandEyeMatrices[1][3].inv(), m_OutputDirName niftk::Save4x4Matrix(m_HandEyeMatrices[1][3].inv(), m_OutputDirName
+ "calib.right.eyehand.allextrinsic.txt"); + "calib.right.eyehand.allextrinsic.txt");
niftk::Save4x4Matrix(m_HandEyeMatrices[1][m_HandeyeMethod].inv(), m_OutputDirName niftk::Save4x4Matrix(m_HandEyeMatrices[1][m_HandeyeMethod].inv(), m_OutputDirName
+ "calib.right.eyehand.current.txt"); + "calib.right.eyehand.current.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[1][0].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[1][0].inv(), m_OutputDirName
+ "calib.right.eyehand.tsai.params.txt"); + "calib.right.eyehand.tsai.params.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[1][1].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[1][1].inv(), m_OutputDirName
+ "calib.right.eyehand.shahidi.params.txt"); + "calib.right.eyehand.shahidi.params.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[1][2].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[1][2].inv(), m_OutputDirName
+ "calib.right.eyehand.malti.params.txt"); + "calib.right.eyehand.malti.params.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[1][3].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[1][3].inv(), m_OutputDirName
+ "calib.right.eyehand.allextrinsic.params.txt"); + "calib.right.eyehand.allextrinsic.params.txt");
niftk::SaveRigidParams(m_HandEyeMatrices[1][m_HandeyeMethod].inv(), m_OutputDirName niftk::SaveRigidParams(m_HandEyeMatrices[1][m_HandeyeMethod].inv(), m_OutputDirName
+ "calib.right.eyehand.current.params.txt"); + "calib.right.eyehand.current.params.txt");
}
if (m_ModelTransformNode.IsNotNull())
{
int counter = 0;
std::list<cv::Matx44d >::const_iterator iter;
for (iter = m_ModelTrackingMatrices.begin();
iter != m_ModelTrackingMatrices.end();
++iter
)
{
std::ostringstream fileName;
fileName << m_OutputDirName << "calib.tracking.model." << counter++ << ".4x4";
niftk::Save4x4Matrix(*iter, fileName.str());
} }
} // end if we have a reference transform
niftk::Save4x4Matrix(m_ModelToWorld, m_OutputDirName + "calib.model2world.txt");
} // end if we have tracking info niftk::Save4x4Matrix(m_ModelToWorld, m_OutputDirName + "calib.model2world.txt");
// Write main results to file. } // end if we have tracking info
std::string outputMessageFileName = m_OutputDirName + "calib.result.log"; } // end ifSuccessful
std::ofstream outputMessageFile;
outputMessageFile.open (outputMessageFileName, std::ofstream::out);
if (!outputMessageFile.is_open())
{
mitkThrow() << "Failed to open file:" << outputMessageFileName << " for writing.";
}
outputMessageFile << m_CalibrationResult << std::endl;
outputMessageFile.close();
MITK_INFO << "Saving calibration to:" << m_OutputDirName << ": - DONE.";
} }
......
...@@ -168,6 +168,9 @@ public: ...@@ -168,6 +168,9 @@ public:
void SetModelTransformFileName(const std::string& fileName); void SetModelTransformFileName(const std::string& fileName);
itkGetMacro(ModelTransformFileName, std::string); itkGetMacro(ModelTransformFileName, std::string);
itkGetMacro(CalibrationResult, std::string);
itkGetMacro(CalibrationErrorMessage, std::string);
bool isStereo() const; bool isStereo() const;
unsigned int GetNumberOfSnapshots() const; unsigned int GetNumberOfSnapshots() const;
...@@ -195,15 +198,17 @@ public: ...@@ -195,15 +198,17 @@ public:
* This can be mono, stereo, iterative and include hand-eye, * This can be mono, stereo, iterative and include hand-eye,
* depending on the configuration parameters stored in this class. * depending on the configuration parameters stored in this class.
* *
* \return calibration message with all results in. * \return bool true if it ran to completion, false otherwise.
*
* Note that even if calibration ran to completion, it doesn't mean its a good calibration.
*/ */
std::string Calibrate(); bool Calibrate();
/** /**
* \brief Saves a bunch of standard (from a NifTK perspective) * \brief Saves a bunch of standard (from a NifTK perspective)
* calibration files to the output dir, overwriting existing files. * calibration files to the output dir, overwriting existing files.
*/ */
void Save(); void Save(bool isSuccessful);
/** /**
* \brief To update the camera to world in mitk::DataStorage so * \brief To update the camera to world in mitk::DataStorage so
...@@ -413,6 +418,7 @@ private: ...@@ -413,6 +418,7 @@ private:
std::vector<cv::Matx44d> m_HandEyeMatrices[2]; std::vector<cv::Matx44d> m_HandEyeMatrices[2];
cv::Matx44d m_ModelToWorld; cv::Matx44d m_ModelToWorld;
std::string m_CalibrationResult; std::string m_CalibrationResult;
std::string m_CalibrationErrorMessage;
}; // end class }; // end class
......
...@@ -422,8 +422,8 @@ void CameraCalView::OnGrabButtonPressed() ...@@ -422,8 +422,8 @@ void CameraCalView::OnGrabButtonPressed()
// If there is no model file, calibration will ultimately fail. // If there is no model file, calibration will ultimately fail.
// However, if the user just wants to grab data, and hence // However, if the user just wants to grab data, and hence
// m_Manager->GetSaveOutputBeforeCalibration() is true, then we do NOT need this check. // m_Manager->GetSaveOutputRegardlessOfCalibration() is true, then we do NOT need this check.
// So, only do this check if m_Manager->GetSaveOutputBeforeCalibration() is false. // So, only do this check if m_Manager->GetSaveOutputRegardlessOfCalibration() is false.
if (m_Manager->GetModelFileName().empty() && !m_Manager->GetSaveOutputRegardlessOfCalibration()) if (m_Manager->GetModelFileName().empty() && !m_Manager->GetSaveOutputRegardlessOfCalibration())
{ {
QMessageBox msgBox; QMessageBox msgBox;
...@@ -452,9 +452,7 @@ void CameraCalView::OnGrabButtonPressed() ...@@ -452,9 +452,7 @@ void CameraCalView::OnGrabButtonPressed()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool CameraCalView::RunGrab() bool CameraCalView::RunGrab()
{ {
bool isSuccessful = false; bool isSuccessful = false;
std::string errorMessage = "";
// This happens in a separate thread, so try to catch everything. // This happens in a separate thread, so try to catch everything.
// Even if we understand where NiftyCal exceptions come from, // Even if we understand where NiftyCal exceptions come from,
...@@ -467,30 +465,20 @@ bool CameraCalView::RunGrab() ...@@ -467,30 +465,20 @@ bool CameraCalView::RunGrab()
} }
catch (niftk::NiftyCalException& e) catch (niftk::NiftyCalException& e)
{ {
errorMessage = e.GetDescription(); std::string errorMessage = e.GetDescription();
MITK_ERROR << "CameraCalView::RunGrab() failed:" << e.GetDescription(); MITK_ERROR << "CameraCalView::RunGrab() failed:" << e.GetDescription();
} }
catch (mitk::Exception& e) catch (mitk::Exception& e)
{ {
errorMessage = e.GetDescription(); std::string errorMessage = e.GetDescription();
MITK_ERROR << "CameraCalView::RunGrab() failed:" << e.GetDescription(); MITK_ERROR << "CameraCalView::RunGrab() failed:" << e.GetDescription();
} }
catch (std::exception& e) catch (std::exception& e)
{ {
errorMessage = e.what(); std::string errorMessage = e.what();
MITK_ERROR << "CameraCalView::RunGrab() failed:" << e.what(); MITK_ERROR << "CameraCalView::RunGrab() failed:" << e.what();
} }
if (!errorMessage.empty())
{
QMessageBox msgBox;
msgBox.setText("An Error Occurred.");
msgBox.setInformativeText(QString::fromStdString(errorMessage));
msgBox.setStandardButtons(QMessageBox::Ok);
msgBox.setDefaultButton(QMessageBox::Ok);
msgBox.exec();
}
return isSuccessful; return isSuccessful;
} }
...@@ -553,10 +541,9 @@ void CameraCalView::Calibrate() ...@@ -553,10 +541,9 @@ void CameraCalView::Calibrate()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
std::string CameraCalView::RunCalibration() bool CameraCalView::RunCalibration()
{ {
std::string outputMessage = ""; bool isSuccessful = false;
std::string errorMessage = "";
// This happens in a separate thread, so try to catch everything. // This happens in a separate thread, so try to catch everything.
// Even if we understand where NiftyCal exceptions come from, // Even if we understand where NiftyCal exceptions come from,
...@@ -565,56 +552,47 @@ std::string CameraCalView::RunCalibration() ...@@ -565,56 +552,47 @@ std::string CameraCalView::RunCalibration()
try try
{ {
outputMessage = m_Manager->Calibrate(); isSuccessful = m_Manager->Calibrate();
} }
catch (niftk::NiftyCalException& e) catch (niftk::NiftyCalException& e)
{ {
errorMessage = e.GetDescription(); std::string errorMessage = e.GetDescription();
MITK_ERROR << "CameraCalView::RunCalibration() failed:" << e.GetDescription(); MITK_ERROR << "CameraCalView::RunCalibration() failed:" << e.GetDescription();
throw e;
} }
catch (mitk::Exception& e) catch (mitk::Exception& e)
{ {
errorMessage = e.GetDescription(); std::string errorMessage = e.GetDescription();
MITK_ERROR << "CameraCalView::RunCalibration() failed:" << e.GetDescription(); MITK_ERROR << "CameraCalView::RunCalibration() failed:" << e.GetDescription();
throw e;
} }
catch (std::exception& e) catch (std::exception& e)
{ {
errorMessage = e.what(); std::string errorMessage = e.what();
MITK_ERROR << "CameraCalView::RunCalibration() failed:" << e.what(); MITK_ERROR << "CameraCalView::RunCalibration() failed:" << e.what();
throw e;
} }
return outputMessage; return isSuccessful;
} }