PlusLib  2.9.0
Software library for tracked ultrasound image acquisition, calibration, and processing.
CreateSliceModels.cxx
Go to the documentation of this file.
1 /*=Plus=header=begin======================================================
2  Program: Plus
3  Copyright (c) Laboratory for Percutaneous Surgery. All rights reserved.
4  See License.txt for details.
5 =========================================================Plus=header=end*/
6 
13 #include "PlusConfigure.h"
14 
15 // STL includes
16 #include <iostream>
17 #include <algorithm>
18 #include <cctype>
19 #include <string>
20 
21 // VTK includes
22 #include <vtkAppendPolyData.h>
23 #include <vtkCubeSource.h>
24 #include <vtkMatrix4x4.h>
25 #include <vtkPolyData.h>
26 #include <vtkPolyDataWriter.h>
27 #include <vtkSTLWriter.h>
28 #include <vtkSmartPointer.h>
29 #include <vtkTransform.h>
30 #include <vtkTransformPolyDataFilter.h>
31 #include <vtkXMLUtilities.h>
32 #include <vtksys/CommandLineArguments.hxx>
33 
34 // IGSIO includes
35 #include <igsioTrackedFrame.h>
36 #include <vtkIGSIOSequenceIO.h>
37 #include <vtkIGSIOTrackedFrameList.h>
38 #include <vtkIGSIOTransformRepository.h>
39 
40 // Plus includes
42 
43 int main( int argc, char** argv )
44 {
45  bool printHelp( false );
46  std::string inputMetaFilename;
47  std::string inputConfigFileName;
48  std::string outputModelFilename;
49  std::string imageToReferenceTransformNameStr;
50 
51  int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED;
52 
53  vtksys::CommandLineArguments args;
54  args.Initialize( argc, argv );
55 
56  args.AddArgument( "--image-to-reference-transform", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &imageToReferenceTransformNameStr, "Image to reference transform name used for creating slice models" );
57  args.AddArgument( "--source-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputMetaFilename, "Tracked ultrasound recorded by Plus (e.g., by the TrackedUltrasoundCapturing application) in a sequence file (.mha/.nrrd)" );
58  args.AddArgument( "--config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputConfigFileName, "Config file used for volume reconstruction. It contains the probe calibration matrix, the ImageToTool transform (.xml) " );
59  args.AddArgument( "--output-model-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputModelFilename, "A 3D model file that contains rectangles corresponding to each US image slice (.vtk)" );
60  args.AddArgument( "--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel, "Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)" );
61  args.AddArgument( "--help", vtksys::CommandLineArguments::NO_ARGUMENT, &printHelp, "Print this help." );
62 
63  if ( !args.Parse() )
64  {
65  std::cerr << "Problem parsing arguments" << std::endl;
66  std::cout << "Help: " << args.GetHelp() << std::endl;
67  exit( EXIT_FAILURE );
68  }
69 
70  if ( printHelp )
71  {
72  std::cout << args.GetHelp() << std::endl;
73  exit( EXIT_SUCCESS );
74  }
75 
76  vtkPlusLogger::Instance()->SetLogLevel( verboseLevel );
77 
78  if ( inputMetaFilename.empty() )
79  {
80  std::cerr << "--source-seq-file argument required!" << std::endl;
81  exit( EXIT_FAILURE );
82  }
83  if ( outputModelFilename.empty() )
84  {
85  std::cerr << "--output-model-file argument required!" << std::endl;
86  std::cout << "Help: " << args.GetHelp() << std::endl;
87  exit( EXIT_FAILURE );
88  }
89 
90  // Read input tracked ultrasound data.
91  LOG_DEBUG( "Reading input... " );
92  vtkSmartPointer< vtkIGSIOTrackedFrameList > trackedFrameList = vtkSmartPointer< vtkIGSIOTrackedFrameList >::New();
93  if( vtkIGSIOSequenceIO::Read( inputMetaFilename, trackedFrameList ) != PLUS_SUCCESS )
94  {
95  LOG_ERROR( "Unable to load input sequences file." );
96  exit( EXIT_FAILURE );
97  }
98  LOG_DEBUG( "Reading input done." );
99  LOG_DEBUG( "Number of frames: " << trackedFrameList->GetNumberOfTrackedFrames() );
100 
101  // Get the image size
102  FrameSizeType clipRectangleOrigin = { 0, 0, 0 };
103  FrameSizeType clipRectangleSize = trackedFrameList->GetTrackedFrame(0)->GetFrameSize();
104  if (clipRectangleSize[0] <= 0 || clipRectangleSize[1] <= 0 )
105  {
106  LOG_ERROR( "Invalid frame size: " << clipRectangleSize[0] << "x" << clipRectangleSize[1] );
107  clipRectangleSize[0] = 0;
108  clipRectangleSize[1] = 0;
109  }
110 
111  // Read calibration matrices from the config file
112  vtkSmartPointer<vtkIGSIOTransformRepository> transformRepository = vtkSmartPointer<vtkIGSIOTransformRepository>::New();
113  if ( !inputConfigFileName.empty() )
114  {
115  LOG_DEBUG( "Reading config file..." );
116  vtkSmartPointer<vtkXMLDataElement> configRootElement = vtkSmartPointer<vtkXMLDataElement>::New();
117  if ( PlusXmlUtils::ReadDeviceSetConfigurationFromFile( configRootElement, inputConfigFileName.c_str() ) == PLUS_FAIL )
118  {
119  LOG_ERROR( "Unable to read configuration from file " << inputConfigFileName.c_str() );
120  return EXIT_FAILURE;
121  }
122 
123  vtkSmartPointer<vtkPlusVolumeReconstructor> reconstructor = vtkSmartPointer<vtkPlusVolumeReconstructor>::New();
124  reconstructor->ReadConfiguration( configRootElement );
125  LOG_DEBUG( "Reading config file done." );
126  if ( transformRepository->ReadConfiguration( configRootElement ) != PLUS_SUCCESS )
127  {
128  LOG_ERROR( "Failed to read transforms for transform repository!" );
129  return EXIT_FAILURE;
130  }
131  int* clipRectangleOriginInConfig = reconstructor->GetClipRectangleOrigin();
132  if ( clipRectangleOriginInConfig != NULL && clipRectangleOriginInConfig[0] >= 0 && clipRectangleOriginInConfig[1] >= 0 )
133  {
134  clipRectangleOrigin[0] = static_cast<unsigned int>(clipRectangleOriginInConfig[0]);
135  clipRectangleOrigin[1] = static_cast<unsigned int>(clipRectangleOriginInConfig[1]);
136  }
137  int* clipRectangleSizeInConfig = reconstructor->GetClipRectangleSize();
138  if ( clipRectangleSizeInConfig != NULL && clipRectangleSizeInConfig[0] > 0 && clipRectangleSizeInConfig[1] > 0 )
139  {
140  clipRectangleSize[0] = static_cast<unsigned int>(clipRectangleSizeInConfig[0]);
141  clipRectangleSize[1] = static_cast<unsigned int>(clipRectangleSizeInConfig[1]);
142  }
143  }
144  else
145  {
146  LOG_INFO( "Configuration file is not specified. Only those transforms are available that are defined in the sequence metafile" );
147  }
148 
149  // Prepare the output polydata.
150  vtkSmartPointer<vtkAppendPolyData> appender = vtkSmartPointer<vtkAppendPolyData>::New();
151 
152  igsioTransformName imageToReferenceTransformName;
153  if ( imageToReferenceTransformName.SetTransformName( imageToReferenceTransformNameStr.c_str() ) != PLUS_SUCCESS )
154  {
155  LOG_ERROR( "Invalid image to reference transform name: " << imageToReferenceTransformNameStr );
156  return EXIT_FAILURE;
157  }
158 
159  // Loop over each tracked image slice.
160  for ( unsigned int frameIndex = 0; frameIndex < trackedFrameList->GetNumberOfTrackedFrames(); ++ frameIndex )
161  {
162  igsioTrackedFrame* frame = trackedFrameList->GetTrackedFrame( frameIndex );
163 
164  // Update transform repository
165  if ( transformRepository->SetTransforms( *frame ) != PLUS_SUCCESS )
166  {
167  LOG_ERROR( "Failed to set repository transforms from tracked frame!" );
168  continue;
169  }
170 
171  vtkSmartPointer<vtkMatrix4x4> imageToReferenceTransformMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
172  if ( transformRepository->GetTransform( imageToReferenceTransformName, imageToReferenceTransformMatrix ) != PLUS_SUCCESS )
173  {
174  std::string strTransformName;
175  imageToReferenceTransformName.GetTransformName( strTransformName );
176  LOG_ERROR( "Failed to get transform from repository: " << strTransformName );
177  continue;
178  }
179 
180  vtkSmartPointer<vtkTransform> imageToReferenceTransform = vtkSmartPointer<vtkTransform>::New();
181  imageToReferenceTransform->SetMatrix( imageToReferenceTransformMatrix );
182 
183  vtkSmartPointer<vtkTransform> tCubeToImage = vtkSmartPointer<vtkTransform>::New();
184  tCubeToImage->Translate( clipRectangleOrigin[0], clipRectangleOrigin[1], clipRectangleOrigin[2] );
185  tCubeToImage->Scale( clipRectangleSize[0], clipRectangleSize[1], clipRectangleSize[2] );
186  tCubeToImage->Translate( 0.5, 0.5, 0.5 ); // Moving the corner to the origin.
187 
188  vtkSmartPointer<vtkTransform> tCubeToTracker = vtkSmartPointer<vtkTransform>::New();
189  tCubeToTracker->Identity();
190  tCubeToTracker->Concatenate( imageToReferenceTransform );
191  tCubeToTracker->Concatenate( tCubeToImage );
192 
193  vtkSmartPointer<vtkTransformPolyDataFilter> cubeToTracker = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
194  cubeToTracker->SetTransform( tCubeToTracker );
195  vtkSmartPointer<vtkCubeSource> source = vtkSmartPointer<vtkCubeSource>::New();
196  source->Update();
197  cubeToTracker->SetInputConnection( source->GetOutputPort() );
198  cubeToTracker->Update();
199 
200  appender->AddInputConnection( cubeToTracker->GetOutputPort() );
201  }
202 
203  // Write model output.
204  LOG_DEBUG( "Writing output model file (" << outputModelFilename << ")..." );
205  std::string copy(outputModelFilename);
206  std::transform(copy.begin(), copy.end(), copy.begin(),
207  [](unsigned char c) { return std::tolower(c); });
208  if (copy.find("stl") != std::string::npos)
209  {
210  vtkSmartPointer<vtkSTLWriter> writer = vtkSmartPointer<vtkSTLWriter>::New();
211  writer->SetFileName(outputModelFilename.c_str());
212  writer->SetInputConnection(appender->GetOutputPort());
213  writer->Update();
214  }
215  else
216  {
217  vtkSmartPointer<vtkPolyDataWriter> writer = vtkSmartPointer<vtkPolyDataWriter>::New();
218  writer->SetFileName(outputModelFilename.c_str());
219  writer->SetInputConnection(appender->GetOutputPort());
220  writer->Update();
221  }
222  LOG_DEBUG( "Writing model file done." );
223 
224  LOG_INFO( "Model file created: " << outputModelFilename );
225 
226  return EXIT_SUCCESS;
227 }
const char * source
Definition: phidget22.h:2461
int main(int argc, char **argv)
#define PLUS_FAIL
Definition: PlusCommon.h:43
#define PLUS_SUCCESS
Definition: PlusCommon.h:44
static vtkIGSIOLogger * Instance()
static PlusStatus ReadDeviceSetConfigurationFromFile(vtkXMLDataElement *config, const char *filename)
Definition: PlusXmlUtils.h:23