8 #include "PlusConfigure.h" 10 #include "igsioTrackedFrame.h" 12 #include "vtkIGSIOTrackedFrameList.h" 13 #include "vtkIGSIOTransformRepository.h" 16 #include <vtkImageData.h> 17 #include <vtkMatrix4x4.h> 18 #include <vtkSmartPointer.h> 19 #include <vtkTransform.h> 20 #include <vtkXMLDataElement.h> 21 #include <vtkXMLUtilities.h> 22 #include <vtksys/CommandLineArguments.hxx> 23 #include <vtksys/RegularExpression.hxx> 44 class FrameFieldUpdate
49 TrackedFrameList = NULL;
51 FrameScalarIncrement = 0;
52 FrameScalarDecimalDigits = 5;
53 FrameTransformStart = NULL;
54 FrameTransformIncrement = NULL;
57 std::string FieldName;
58 std::string UpdatedFieldName;
59 std::string UpdatedFieldValue;
60 vtkIGSIOTrackedFrameList* TrackedFrameList;
61 double FrameScalarStart;
62 double FrameScalarIncrement;
63 int FrameScalarDecimalDigits;
64 vtkMatrix4x4* FrameTransformStart;
65 vtkMatrix4x4* FrameTransformIncrement;
66 std::string FrameTransformIndexFieldName;
69 PlusStatus TrimSequenceFile(vtkIGSIOTrackedFrameList* trackedFrameList,
unsigned int firstFrameIndex,
unsigned int lastFrameIndex);
74 PlusStatus AddTransform(vtkIGSIOTrackedFrameList* trackedFrameList, std::vector<std::string> transformNamesToAdd, std::string deviceSetConfigurationFileName);
75 PlusStatus FillRectangle(vtkIGSIOTrackedFrameList* trackedFrameList,
const std::vector<unsigned int>& fillRectOrigin,
const std::vector<unsigned int>& fillRectSize,
int fillGrayLevel);
76 PlusStatus CropRectangle(vtkIGSIOTrackedFrameList* trackedFrameList, igsioVideoFrame::FlipInfoType& flipInfo,
const std::vector<int>& cropRectOrigin,
const std::vector<int>& cropRectSize);
80 const std::string FIELD_VALUE_FRAME_SCALAR =
"{frame-scalar}";
81 const std::string FIELD_VALUE_FRAME_TRANSFORM =
"{frame-transform}";
88 if (inputFileNames.size() == 0)
90 LOG_ERROR(
"No --source-seq-files specified");
94 LOG_INFO(
"Read master sequence file: " << inputFileNames[0]);
97 LOG_ERROR(
"Couldn't read sequence file: " << inputFileNames[0]);
100 if (trackedFrameList->GetNumberOfTrackedFrames() == 0)
102 LOG_ERROR(
"No frames in sequence file: " << inputFileNames[0]);
106 for (
unsigned int i = 1;
i < inputFileNames.size();
i++)
108 LOG_INFO(
"Read input sequence file: " << inputFileNames[
i]);
109 vtkSmartPointer<vtkIGSIOTrackedFrameList> additionalTrackedFrameList = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
112 LOG_ERROR(
"Couldn't read sequence file: " << inputFileNames[0]);
115 if (additionalTrackedFrameList->GetNumberOfTrackedFrames() == 0)
120 unsigned int additionalFrameIndex = 0;
121 double maxTimestampValueForCurrentAdditionalFrame = additionalTrackedFrameList->GetTrackedFrame(0)->GetTimestamp();
122 if (additionalTrackedFrameList->GetNumberOfTrackedFrames() >= 2)
124 maxTimestampValueForCurrentAdditionalFrame = (additionalTrackedFrameList->GetTrackedFrame(additionalFrameIndex + 1)->GetTimestamp() + additionalTrackedFrameList->GetTrackedFrame(additionalFrameIndex)->GetTimestamp()) / 2.0;
126 for (
unsigned int f = 0; f < trackedFrameList->GetNumberOfTrackedFrames(); ++f)
128 igsioTrackedFrame* masterTrackedFrame = trackedFrameList->GetTrackedFrame(f);
131 while (masterTrackedFrame->GetTimestamp() > maxTimestampValueForCurrentAdditionalFrame
132 && additionalFrameIndex + 1 < additionalTrackedFrameList->GetNumberOfTrackedFrames())
134 if (additionalFrameIndex == additionalTrackedFrameList->GetNumberOfTrackedFrames() - 1)
139 additionalFrameIndex++;
141 maxTimestampValueForCurrentAdditionalFrame = (additionalTrackedFrameList->GetTrackedFrame(additionalFrameIndex)->GetTimestamp() +
142 additionalTrackedFrameList->GetTrackedFrame(additionalFrameIndex + 1)->GetTimestamp()) / 2.0;
146 igsioTrackedFrame* additionalFrame = additionalTrackedFrameList->GetTrackedFrame(additionalFrameIndex);
147 auto customFrameFields = additionalFrame->GetCustomFields();
148 for (
auto fieldIter = customFrameFields.begin(); fieldIter != customFrameFields.end(); ++fieldIter)
150 if (!fieldIter->first.compare(
"FrameNumber") ||
151 !fieldIter->first.compare(
"Timestamp") ||
152 !fieldIter->first.compare(
"UnfilteredTimestamp") ||
153 !fieldIter->first.compare(
"ImageStatus"))
158 masterTrackedFrame->SetFrameField(fieldIter->first, fieldIter->second.second, fieldIter->second.first);
167 PlusStatus AppendTrackedFrameLists(vtkIGSIOTrackedFrameList* trackedFrameList, std::vector<std::string> inputFileNames,
bool incrementTimestamps, std::vector<std::string> customHeaderFields)
169 double lastTimestamp = 0;
170 for (
unsigned int i = 0;
i < inputFileNames.size();
i++)
172 LOG_INFO(
"Read input sequence file: " << inputFileNames[
i]);
173 vtkSmartPointer<vtkIGSIOTrackedFrameList> timestampFrameList = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
176 LOG_ERROR(
"Couldn't read sequence file: " << inputFileNames[0]);
180 if (incrementTimestamps)
182 vtkIGSIOTrackedFrameList* tfList = timestampFrameList;
183 for (
unsigned int f = 0; f < tfList->GetNumberOfTrackedFrames(); ++f)
185 igsioTrackedFrame* tf = tfList->GetTrackedFrame(f);
186 tf->SetTimestamp(lastTimestamp + tf->GetTimestamp());
189 lastTimestamp = tfList->GetTrackedFrame(tfList->GetNumberOfTrackedFrames() - 1)->GetTimestamp();
192 if (!customHeaderFields.empty())
194 std::string fieldValue;
195 for (
unsigned int i = 0;
i < customHeaderFields.size(); ++
i)
197 fieldValue = timestampFrameList->GetCustomString(customHeaderFields[
i]);
198 trackedFrameList->SetCustomString(customHeaderFields[
i], fieldValue);
202 if (trackedFrameList->AddTrackedFrameList(timestampFrameList) !=
PLUS_SUCCESS)
204 LOG_ERROR(
"Failed to append tracked frame list!");
212 int main(
int argc,
char** argv)
215 bool printHelp =
false;
216 int verboseLevel(vtkPlusLogger::LOG_LEVEL_UNDEFINED);
217 vtksys::CommandLineArguments args;
219 std::string inputFileName;
220 std::vector<std::string> inputFileNames;
221 std::string outputFileName;
222 std::string strOperation;
224 bool useCompression =
false;
225 bool incrementTimestamps =
false;
227 int firstFrameIndex = -1;
228 int lastFrameIndex = -1;
230 std::string fieldName;
231 std::string updatedFieldName;
232 std::string updatedFieldValue;
234 std::vector<std::string> customHeaderFieldsToMaintain;
236 int frameScalarDecimalDigits = 5;
238 double frameScalarStart = 0.0;
239 double frameScalarIncrement = 1.0;
241 int decimationFactor = 2;
243 std::string strFrameTransformStart;
244 vtkSmartPointer<vtkMatrix4x4> frameTransformStart = vtkSmartPointer<vtkMatrix4x4>::New();
246 std::string strFrameTransformIncrement;
247 vtkSmartPointer<vtkMatrix4x4> frameTransformIncrement = vtkSmartPointer<vtkMatrix4x4>::New();
249 std::string strFrameTransformIndexFieldName;
251 std::string strUpdatedReferenceTransformName;
253 std::string transformNamesToAdd;
254 std::string deviceSetConfigurationFileName;
256 std::vector<int> rectOriginPix;
257 std::vector<int> rectSizePix;
258 int fillGrayLevel = 0;
264 args.Initialize(argc, argv);
265 args.AddArgument(
"--help", vtksys::CommandLineArguments::NO_ARGUMENT, &printHelp,
"Print this help.");
266 args.AddArgument(
"--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel,
"Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)");
268 args.AddArgument(
"--source-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputFileName,
"Input sequence file name with path to edit");
269 args.AddArgument(
"--source-seq-files", vtksys::CommandLineArguments::MULTI_ARGUMENT, &inputFileNames,
"Input sequence file name list with path to edit");
270 args.AddArgument(
"--output-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputFileName,
"Output sequence file name with path to save the result");
272 args.AddArgument(
"--operation", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &strOperation,
"Operation to modify sequence file. See available operations below.");
275 args.AddArgument(
"--first-frame-index", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &firstFrameIndex,
"First frame index used for trimming the sequence file. Index of the first frame of the sequence is 0.");
276 args.AddArgument(
"--last-frame-index", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &lastFrameIndex,
"Last frame index used for trimming the sequence file.");
279 args.AddArgument(
"--decimation-factor", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &decimationFactor,
"Used for DECIMATE operation, where every N-th frame is kept. This parameter specifies N (Default: 2)");
281 args.AddArgument(
"--field-name", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &fieldName,
"Field name to edit");
282 args.AddArgument(
"--updated-field-name", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &updatedFieldName,
"Updated field name after edit");
283 args.AddArgument(
"--updated-field-value", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &updatedFieldValue,
"Updated field value after edit");
285 args.AddArgument(
"--maintain-custom-headers", vtksys::CommandLineArguments::MULTI_ARGUMENT, &customHeaderFieldsToMaintain,
"List of custom header fields to pass through to output file.");
287 args.AddArgument(
"--frame-scalar-start", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &frameScalarStart,
"Frame scalar field value starting index (Default: 0.0)");
288 args.AddArgument(
"--frame-scalar-increment", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &frameScalarIncrement,
"Frame scalar field value increment (Default: 1.0)");
289 args.AddArgument(
"--frame-scalar-decimal-digits", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &frameScalarDecimalDigits,
"Number of digits saved for frame scalar field value into sequence file (Default: 5)");
291 args.AddArgument(
"--frame-transform-start", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &strFrameTransformStart,
"Frame transform field starting 4x4 transform matrix (Default: identity)");
292 args.AddArgument(
"--frame-transform-increment", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &strFrameTransformIncrement,
"Frame transform increment 4x4 transform matrix (Default: identity)");
293 args.AddArgument(
"--frame-transform-index-field-name", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &strFrameTransformIndexFieldName,
"If specified then increment is applied as many times as the value of this field");
295 args.AddArgument(
"--update-reference-transform", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &strUpdatedReferenceTransformName,
"Set the reference transform name to update old files by changing all ToolToReference transforms to ToolToTracker transform.");
297 args.AddArgument(
"--use-compression", vtksys::CommandLineArguments::NO_ARGUMENT, &useCompression,
"Compress sequence file images.");
298 args.AddArgument(
"--increment-timestamps", vtksys::CommandLineArguments::NO_ARGUMENT, &incrementTimestamps,
"Increment timestamps in the order of the input-file-names");
300 args.AddArgument(
"--add-transform", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &transformNamesToAdd,
"Name of the transform to add to each frame (e.g., StylusTipToTracker); multiple transforms can be added separated by a comma (e.g., StylusTipToReference,ProbeToReference)");
301 args.AddArgument(
"--config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &deviceSetConfigurationFileName,
"Used device set configuration file path and name");
304 args.AddArgument(
"--rect-origin", vtksys::CommandLineArguments::MULTI_ARGUMENT, &rectOriginPix,
"Fill or crop rectangle top-left corner position in MF coordinate frame, in pixels, separated by space (e.g., --rect-origin 12 34).");
305 args.AddArgument(
"--rect-size", vtksys::CommandLineArguments::MULTI_ARGUMENT, &rectSizePix,
"Fill or crop rectangle size in MF coordinate frame, in pixels, separated by space (e.g., --rect-size 56 78).");
306 args.AddArgument(
"--flipX", vtksys::CommandLineArguments::NO_ARGUMENT, &flipX,
"Flip image along X axis.");
307 args.AddArgument(
"--flipY", vtksys::CommandLineArguments::NO_ARGUMENT, &flipY,
"Flip image along Y axis.");
308 args.AddArgument(
"--flipZ", vtksys::CommandLineArguments::NO_ARGUMENT, &flipZ,
"Flip image along Z axis.");
309 args.AddArgument(
"--fill-gray-level", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &fillGrayLevel,
"Rectangle fill gray level. 0 = black, 255 = white. (Default: 0)");
313 std::cerr <<
"Problem parsing arguments" << std::endl;
314 std::cout <<
"Help: " << args.GetHelp() << std::endl;
319 if (argc == 1 || printHelp)
321 std::cout << args.GetHelp() << std::endl;
322 std::cout << std::endl <<
"Operations: " << std::endl << std::endl;
324 std::cout <<
"- UPDATE_FRAME_FIELD_NAME: update per-frame field names for each frame. If field does not exist then it is added." << std::endl;
325 std::cout <<
" Requires --field-name and --updated-field-name." << std::endl;
326 std::cout <<
"- UPDATE_FRAME_FIELD_VALUE: update per-frame field values for each frame, if not exists add it." << std::endl;
327 std::cout <<
" Uses --field-name, --updated-field-name, --updated-field-value, --frame-scalar-*, --frame-transform-*" << std::endl;
328 std::cout <<
"- DELETE_FRAME_FIELD: delete per-frame field (field values specified for each frame)." << std::endl;
329 std::cout <<
" Requires --field-name." << std::endl;
331 std::cout <<
"- UPDATE_FIELD_NAME: update field name, if not exists add it." << std::endl;
332 std::cout <<
" Requires --field-name and --updated-field-name." << std::endl;
333 std::cout <<
"- UPDATE_FIELD_VALUE: update field value, if not exists add it." << std::endl;
334 std::cout <<
" Requires --field-name and --updated-field-value." << std::endl;
335 std::cout <<
"- DELETE_FIELD: delete field with name specified." << std::endl;
336 std::cout <<
" Requires --field-name." << std::endl;
337 std::cout <<
"- ADD_TRANSFORM: add specified transform." << std::endl;
338 std::cout <<
" Requires --add-transform." << std::endl;
340 std::cout <<
"- TRIM: Trim sequence file." << std::endl;
341 std::cout <<
" Requires --first-frame-index and --last-frame-index." << std::endl;
342 std::cout <<
"- DECIMATE: Keep every N-th frame of the sequence file." << std::endl;
343 std::cout <<
" Requires --decimation-factor." << std::endl;
344 std::cout <<
"- APPEND: Append multiple sequence files (one after the other)." << std::endl;
345 std::cout <<
" Set input files with the --source-seq-files parameter." << std::endl;
346 std::cout <<
"- MIX: Merge fields stored in multiple sequence files." << std::endl;
347 std::cout <<
" Timepoints are defined by the first sequence. Image data is taken from the first sequence." << std::endl;
348 std::cout <<
" No interpolation is performed, fields are copied from the frame with the closest timestamp." << std::endl;
349 std::cout <<
" Set input files with the --source-seq-files parameter." << std::endl;
351 std::cout <<
"- FILL_IMAGE_RECTANGLE: Fill a rectangle in the image (useful for removing patient data from sequences)." << std::endl;
352 std::cout <<
" Requires --rect-origin, --rect-size, and --fill-gray-level. E.g., --rect-origin 12 34 --rect-size 56 78)" << std::endl;
353 std::cout <<
"- CROP: Crop a rectangle in the image (useful for cropping b-mode image from the data obtained via frame-grabber)." << std::endl;
354 std::cout <<
" Requires --rect-origin and --rect-size. (e.g., --rect-size 56 78). Optional: --flip*." << std::endl;
356 std::cout <<
"- REMOVE_IMAGE_DATA: Remove image data from a meta file that has both image and tracker data, and keep only the tracker data." << std::endl;
364 if (inputFileName.empty() && inputFileNames.empty())
366 LOG_ERROR(
"At least one input file name is mandantory!");
370 if (outputFileName.empty())
372 LOG_ERROR(
"Please set output file name!");
377 if (strOperation.empty())
380 LOG_INFO(
"No modification operation has been specified (specify --operation parameter to change the input sequence).");
382 else if (igsioCommon::IsEqualInsensitive(strOperation,
"UPDATE_FRAME_FIELD_NAME"))
386 else if (igsioCommon::IsEqualInsensitive(strOperation,
"UPDATE_FRAME_FIELD_VALUE"))
390 else if (igsioCommon::IsEqualInsensitive(strOperation,
"DELETE_FRAME_FIELD"))
394 else if (igsioCommon::IsEqualInsensitive(strOperation,
"UPDATE_FIELD_NAME"))
398 else if (igsioCommon::IsEqualInsensitive(strOperation,
"UPDATE_FIELD_VALUE"))
402 else if (igsioCommon::IsEqualInsensitive(strOperation,
"DELETE_FIELD"))
406 else if (igsioCommon::IsEqualInsensitive(strOperation,
"ADD_TRANSFORM"))
410 else if (igsioCommon::IsEqualInsensitive(strOperation,
"TRIM"))
414 else if (igsioCommon::IsEqualInsensitive(strOperation,
"DECIMATE"))
418 else if (igsioCommon::IsEqualInsensitive(strOperation,
"APPEND"))
422 else if (igsioCommon::IsEqualInsensitive(strOperation,
"MERGE"))
424 LOG_WARNING(
"MERGE operation name is deprecated. Use APPEND instead.")
427 else if (igsioCommon::IsEqualInsensitive(strOperation,
"MIX"))
431 else if (igsioCommon::IsEqualInsensitive(strOperation,
"FILL_IMAGE_RECTANGLE"))
435 else if (igsioCommon::IsEqualInsensitive(strOperation,
"CROP"))
437 if (rectOriginPix.size() != 2 && rectOriginPix.size() != 3 &&
438 rectSizePix.size() != 2 && rectSizePix.size() != 3)
440 LOG_ERROR(
"--rect-origin and --rect-size must be of the form --rect-origin X Y <Z> and --rect-size I J <K>")
445 else if (igsioCommon::IsEqualInsensitive(strOperation,
"REMOVE_IMAGE_DATA"))
451 LOG_ERROR(
"Invalid operation selected: " << strOperation);
458 LOG_ERROR(
"String to matrix conversion failed for transform start matrix!");
464 LOG_ERROR(
"String to matrix conversion failed for transform increment matrix!");
471 vtkSmartPointer<vtkIGSIOTrackedFrameList> trackedFrameList = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
473 if (!inputFileName.empty())
476 inputFileNames.insert(inputFileNames.begin(), inputFileName);
481 if (operation ==
MIX)
487 status =
AppendTrackedFrameLists(trackedFrameList, inputFileNames, incrementTimestamps, customHeaderFieldsToMaintain);
508 if (firstFrameIndex < 0)
512 if (lastFrameIndex < 0)
516 unsigned int firstFrameIndexUint = static_cast<unsigned int>(firstFrameIndex);
517 unsigned int lastFrameIndexUint = static_cast<unsigned int>(lastFrameIndex);
520 LOG_ERROR(
"Failed to trim sequence file");
529 LOG_ERROR(
"Failed to decimate sequence file");
536 FrameFieldUpdate fieldUpdate;
537 fieldUpdate.TrackedFrameList = trackedFrameList;
538 fieldUpdate.FieldName = fieldName;
539 fieldUpdate.UpdatedFieldName = updatedFieldName;
543 LOG_ERROR(
"Failed to update frame field name '" << fieldName <<
"' to '" << updatedFieldName <<
"'");
550 FrameFieldUpdate fieldUpdate;
551 fieldUpdate.TrackedFrameList = trackedFrameList;
552 fieldUpdate.FieldName = fieldName;
553 fieldUpdate.UpdatedFieldName = updatedFieldName;
554 fieldUpdate.UpdatedFieldValue = updatedFieldValue;
555 fieldUpdate.FrameScalarDecimalDigits = frameScalarDecimalDigits;
556 fieldUpdate.FrameScalarIncrement = frameScalarIncrement;
557 fieldUpdate.FrameScalarStart = frameScalarStart;
558 fieldUpdate.FrameTransformStart = frameTransformStart;
559 fieldUpdate.FrameTransformIncrement = frameTransformIncrement;
560 fieldUpdate.FrameTransformIndexFieldName = strFrameTransformIndexFieldName;
564 LOG_ERROR(
"Failed to update frame field value");
573 LOG_ERROR(
"Failed to delete frame field");
581 LOG_INFO(
"Delete field: " << fieldName);
582 if (trackedFrameList->SetCustomString(fieldName.c_str(), NULL) !=
PLUS_SUCCESS)
584 LOG_ERROR(
"Failed to delete field: " << fieldName);
592 LOG_INFO(
"Update field name '" << fieldName <<
"' to '" << updatedFieldName <<
"'");
593 const char* fieldValue = trackedFrameList->GetCustomString(fieldName.c_str());
594 if (fieldValue != NULL)
597 if (trackedFrameList->SetCustomString(fieldName.c_str(), NULL) !=
PLUS_SUCCESS)
599 LOG_ERROR(
"Failed to delete field: " << fieldName);
604 if (trackedFrameList->SetCustomString(updatedFieldName.c_str(), fieldValue) !=
PLUS_SUCCESS)
606 LOG_ERROR(
"Failed to update field '" << updatedFieldName <<
"' with value '" << fieldValue <<
"'");
615 LOG_INFO(
"Update field '" << fieldName <<
"' with value '" << updatedFieldValue <<
"'");
616 if (trackedFrameList->SetCustomString(fieldName.c_str(), updatedFieldValue.c_str()) !=
PLUS_SUCCESS)
618 LOG_ERROR(
"Failed to update field '" << fieldName <<
"' with value '" << updatedFieldValue <<
"'");
626 LOG_INFO(
"Add transform '" << transformNamesToAdd <<
"' using device set configuration file '" << deviceSetConfigurationFileName <<
"'");
627 std::vector<std::string> transformNamesList;
628 igsioCommon::SplitStringIntoTokens(transformNamesToAdd,
',', transformNamesList);
631 LOG_ERROR(
"Failed to add transform '" << transformNamesToAdd <<
"' using device set configuration file '" << deviceSetConfigurationFileName <<
"'");
638 if (rectOriginPix.size() != 2 || rectSizePix.size() != 2)
640 LOG_ERROR(
"Incorrect size of vector for rectangle origin or size. Aborting.");
643 if (rectOriginPix[0] < 0 || rectOriginPix[1] < 0 || rectSizePix[0] < 0 || rectSizePix[1] < 0)
645 LOG_ERROR(
"Negative value for rectangle origin or size entered. Aborting.");
648 std::vector<unsigned int> rectOriginPixUint(rectOriginPix.begin(), rectOriginPix.end());
649 std::vector<unsigned int> rectSizePixUint(rectSizePix.begin(), rectSizePix.end());
653 LOG_ERROR(
"Failed to fill rectangle");
661 igsioVideoFrame::FlipInfoType flipInfo;
662 flipInfo.hFlip = flipX;
663 flipInfo.vFlip = flipY;
664 flipInfo.eFlip = flipZ;
667 LOG_ERROR(
"Failed to fill rectangle");
677 LOG_WARNING(
"Unknown operation is specified: " << strOperation);
686 if (!strUpdatedReferenceTransformName.empty())
688 igsioTransformName referenceTransformName;
689 if (referenceTransformName.SetTransformName(strUpdatedReferenceTransformName.c_str()) !=
PLUS_SUCCESS)
691 LOG_ERROR(
"Reference transform name is invalid: " << strUpdatedReferenceTransformName);
695 for (
unsigned int i = 0;
i < trackedFrameList->GetNumberOfTrackedFrames(); ++
i)
697 igsioTrackedFrame* trackedFrame = trackedFrameList->GetTrackedFrame(
i);
699 vtkSmartPointer<vtkMatrix4x4> referenceToTrackerMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
700 if (trackedFrame->GetFrameTransform(referenceTransformName, referenceToTrackerMatrix) !=
PLUS_SUCCESS)
702 LOG_WARNING(
"Couldn't get reference transform with name: " << strUpdatedReferenceTransformName);
706 std::vector<igsioTransformName> transformNameList;
707 trackedFrame->GetFrameTransformNameList(transformNameList);
709 vtkSmartPointer<vtkTransform> toolToTrackerTransform = vtkSmartPointer<vtkTransform>::New();
710 vtkSmartPointer<vtkMatrix4x4> toolToReferenceMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
711 for (
unsigned int n = 0; n < transformNameList.size(); ++n)
714 if (transformNameList[n] == referenceTransformName)
719 ToolStatus status = TOOL_INVALID;
720 if (trackedFrame->GetFrameTransform(transformNameList[n], toolToReferenceMatrix) !=
PLUS_SUCCESS)
722 std::string strTransformName;
723 transformNameList[
i].GetTransformName(strTransformName);
724 LOG_ERROR(
"Failed to get frame transform: " << strTransformName);
728 if (trackedFrame->GetFrameTransformStatus(transformNameList[n], status) !=
PLUS_SUCCESS)
730 std::string strTransformName;
731 transformNameList[
i].GetTransformName(strTransformName);
732 LOG_ERROR(
"Failed to get frame transform status: " << strTransformName);
737 toolToTrackerTransform->Identity();
738 toolToTrackerTransform->Concatenate(referenceToTrackerMatrix);
739 toolToTrackerTransform->Concatenate(toolToReferenceMatrix);
742 igsioTransformName toolToTracker(transformNameList[n].From().c_str(),
"Tracker");
744 if (trackedFrame->SetFrameTransform(toolToTracker, toolToTrackerTransform->GetMatrix()) !=
PLUS_SUCCESS)
746 std::string strTransformName;
747 transformNameList[
i].GetTransformName(strTransformName);
748 LOG_ERROR(
"Failed to set frame transform: " << strTransformName);
753 if (trackedFrame->SetFrameTransformStatus(toolToTracker, status) !=
PLUS_SUCCESS)
755 std::string strTransformName;
756 transformNameList[
i].GetTransformName(strTransformName);
757 LOG_ERROR(
"Failed to set frame transform status: " << strTransformName);
762 std::string oldTransformName, oldTransformStatus;
763 transformNameList[n].GetTransformName(oldTransformName);
765 vtksys::RegularExpression isTransform(
"Transform$");
766 if (!isTransform.find(oldTransformName))
768 oldTransformName.append(
"Transform");
770 oldTransformStatus = oldTransformName;
771 oldTransformStatus.append(
"Status");
772 trackedFrame->DeleteFrameField(oldTransformName.c_str());
773 trackedFrame->DeleteFrameField(oldTransformStatus.c_str());
782 LOG_INFO(
"Save output sequence file to: " << outputFileName);
785 LOG_ERROR(
"Couldn't write sequence file: " << outputFileName);
789 LOG_INFO(
"Sequence file editing was successful!");
796 LOG_INFO(
"Trim sequence file from frame #: " << aFirstFrameIndex <<
" to frame #" << aLastFrameIndex);
797 if (aLastFrameIndex >= aTrackedFrameList->GetNumberOfTrackedFrames() || aFirstFrameIndex > aLastFrameIndex)
799 LOG_ERROR(
"Invalid input range: (" << aFirstFrameIndex <<
", " << aLastFrameIndex <<
")" <<
" Permitted range within (0, " << aTrackedFrameList->GetNumberOfTrackedFrames() - 1 <<
")");
803 if (aLastFrameIndex != aTrackedFrameList->GetNumberOfTrackedFrames() - 1)
805 aTrackedFrameList->RemoveTrackedFrameRange(aLastFrameIndex + 1, aTrackedFrameList->GetNumberOfTrackedFrames() - 1);
808 if (aFirstFrameIndex != 0)
810 aTrackedFrameList->RemoveTrackedFrameRange(0, aFirstFrameIndex - 1);
819 LOG_INFO(
"Decimate sequence file: keep 1 frame out of every " << decimationFactor <<
" frames");
820 if (decimationFactor < 2)
822 LOG_ERROR(
"Invalid decimation factor: " << decimationFactor <<
". It must be an integer larger or equal than 2.");
825 for (
unsigned int i = 0;
i < aTrackedFrameList->GetNumberOfTrackedFrames() - 1;
i++)
827 unsigned int removeFirstFrameIndex =
i + 1;
828 unsigned int removeLastFrameIndex =
i + decimationFactor - 1;
829 if (removeLastFrameIndex >= aTrackedFrameList->GetNumberOfTrackedFrames())
831 removeLastFrameIndex = aTrackedFrameList->GetNumberOfTrackedFrames() - 1;
832 if (removeLastFrameIndex < removeFirstFrameIndex)
834 removeLastFrameIndex = removeFirstFrameIndex;
837 aTrackedFrameList->RemoveTrackedFrameRange(removeFirstFrameIndex, removeLastFrameIndex);
845 if (trackedFrameList == NULL)
847 LOG_ERROR(
"Tracked frame list is NULL!");
851 if (fieldName.empty())
853 LOG_ERROR(
"Field name is empty!");
857 LOG_INFO(
"Delete frame field: " << fieldName);
858 int numberOfErrors(0);
859 for (
unsigned int i = 0;
i < trackedFrameList->GetNumberOfTrackedFrames(); ++
i)
861 igsioTrackedFrame* trackedFrame = trackedFrameList->GetTrackedFrame(
i);
865 std::string fieldValue = trackedFrame->GetFrameField(fieldName);
866 if (!fieldValue.empty() && trackedFrame->DeleteFrameField(fieldName) !=
PLUS_SUCCESS)
868 LOG_ERROR(
"Failed to delete frame field '" << fieldName <<
"' for frame #" <<
i);
880 LOG_INFO(
"Update frame field");
881 int numberOfErrors(0);
884 double scalarVariable = fieldUpdate.FrameScalarStart;
887 vtkSmartPointer<vtkTransform> frameTransform = vtkSmartPointer<vtkTransform>::New();
888 if (fieldUpdate.FrameTransformStart != NULL)
890 frameTransform->SetMatrix(fieldUpdate.FrameTransformStart);
893 for (
unsigned int i = 0;
i < fieldUpdate.TrackedFrameList->GetNumberOfTrackedFrames(); ++
i)
895 igsioTrackedFrame* trackedFrame = fieldUpdate.TrackedFrameList->GetTrackedFrame(
i);
899 if (!fieldUpdate.FieldName.empty() && !fieldUpdate.UpdatedFieldName.empty())
901 std::string fieldValue = trackedFrame->GetFrameField(fieldUpdate.FieldName);
902 if (!fieldValue.empty())
904 std::string copyOfFieldValue(fieldValue);
905 trackedFrame->DeleteFrameField(fieldUpdate.FieldName);
906 trackedFrame->SetFrameField(fieldUpdate.UpdatedFieldName, copyOfFieldValue);
910 std::string fieldName = fieldUpdate.FieldName;
911 if (!fieldUpdate.UpdatedFieldName.empty())
913 fieldName = fieldUpdate.UpdatedFieldName;
918 if (!fieldName.empty() && !fieldUpdate.UpdatedFieldValue.empty())
920 if (igsioCommon::IsEqualInsensitive(fieldUpdate.UpdatedFieldValue, FIELD_VALUE_FRAME_SCALAR))
924 std::ostringstream fieldValue;
925 fieldValue << std::fixed << std::setprecision(fieldUpdate.FrameScalarDecimalDigits) << scalarVariable;
927 trackedFrame->SetFrameField(fieldName.c_str(), fieldValue.str().c_str());
928 scalarVariable += fieldUpdate.FrameScalarIncrement;
931 else if (igsioCommon::IsEqualInsensitive(fieldUpdate.UpdatedFieldValue, FIELD_VALUE_FRAME_TRANSFORM))
935 double transformMatrix[16] = { 0 };
936 if (fieldUpdate.FrameTransformIndexFieldName.empty())
938 vtkMatrix4x4::DeepCopy(transformMatrix, frameTransform->GetMatrix());
942 std::string frameIndexStr = trackedFrame->GetFrameField(fieldUpdate.FrameTransformIndexFieldName);
944 if (igsioCommon::StringToNumber<int>(frameIndexStr, frameIndex) !=
PLUS_SUCCESS)
946 LOG_ERROR(
"Cannot retrieve frame index from value " << frameIndexStr);
948 vtkSmartPointer<vtkMatrix4x4> cumulativeTransform = vtkSmartPointer<vtkMatrix4x4>::New();
949 cumulativeTransform->DeepCopy(fieldUpdate.FrameTransformStart);
950 for (
int i = 0;
i < frameIndex;
i++)
952 vtkMatrix4x4::Multiply4x4(fieldUpdate.FrameTransformIncrement, cumulativeTransform, cumulativeTransform);
954 vtkMatrix4x4::DeepCopy(transformMatrix, cumulativeTransform);
958 std::ostringstream strTransform;
959 strTransform << std::fixed << std::setprecision(fieldUpdate.FrameScalarDecimalDigits)
960 << transformMatrix[0] <<
" " << transformMatrix[1] <<
" " << transformMatrix[2] <<
" " << transformMatrix[3] <<
" " 961 << transformMatrix[4] <<
" " << transformMatrix[5] <<
" " << transformMatrix[6] <<
" " << transformMatrix[7] <<
" " 962 << transformMatrix[8] <<
" " << transformMatrix[9] <<
" " << transformMatrix[10] <<
" " << transformMatrix[11] <<
" " 963 << transformMatrix[12] <<
" " << transformMatrix[13] <<
" " << transformMatrix[14] <<
" " << transformMatrix[15] <<
" ";
964 trackedFrame->SetFrameField(fieldName.c_str(), strTransform.str().c_str());
966 if (fieldUpdate.FrameTransformIndexFieldName.empty())
968 frameTransform->Concatenate(fieldUpdate.FrameTransformIncrement);
974 trackedFrame->SetFrameField(fieldName.c_str(), fieldUpdate.UpdatedFieldValue.c_str());
988 LOG_ERROR(
"Failed to convert string to matrix - output matrix is NULL!");
992 if (!strMatrix.empty())
994 double transformMatrix[16] = { 0 };
995 std::istringstream transform(strMatrix);
998 while (transform >> item &&
i < 16)
1000 transformMatrix[
i++] = item;
1002 matrix->DeepCopy(transformMatrix);
1009 PlusStatus AddTransform(vtkIGSIOTrackedFrameList* trackedFrameList, std::vector<std::string> transformNamesToAdd, std::string deviceSetConfigurationFileName)
1011 if (trackedFrameList == NULL)
1013 LOG_ERROR(
"Tracked frame list is invalid");
1017 if (transformNamesToAdd.empty())
1019 LOG_ERROR(
"No transform names are specified to be added");
1023 if (deviceSetConfigurationFileName.empty())
1025 LOG_ERROR(
"Used device set configuration file name is empty");
1030 vtkSmartPointer<vtkXMLDataElement> configRootElement = vtkSmartPointer<vtkXMLDataElement>::New();
1033 LOG_ERROR(
"Unable to read configuration from file " << deviceSetConfigurationFileName.c_str());
1037 for (
unsigned int i = 0;
i < trackedFrameList->GetNumberOfTrackedFrames(); ++
i)
1039 igsioTrackedFrame* trackedFrame = trackedFrameList->GetTrackedFrame(
i);
1042 vtkSmartPointer<vtkIGSIOTransformRepository> transformRepository = vtkSmartPointer<vtkIGSIOTransformRepository>::New();
1043 if (transformRepository->ReadConfiguration(configRootElement) !=
PLUS_SUCCESS)
1045 LOG_ERROR(
"Unable to set device set configuration to transform repository!");
1048 if (transformRepository->SetTransforms(*trackedFrame) !=
PLUS_SUCCESS)
1050 LOG_ERROR(
"Unable to set transforms from tracked frame " <<
i <<
" to transform repository!");
1054 for (std::vector<std::string>::iterator transformNameToAddIt = transformNamesToAdd.begin(); transformNameToAddIt != transformNamesToAdd.end(); ++transformNameToAddIt)
1057 igsioTransformName transformName;
1058 transformName.SetTransformName(transformNameToAddIt->c_str());
1061 ToolStatus status(TOOL_INVALID);
1062 vtkSmartPointer<vtkMatrix4x4> transformMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
1063 if (transformRepository->GetTransform(transformName, transformMatrix, &status) !=
PLUS_SUCCESS)
1065 LOG_WARNING(
"Failed to get transform " << (*transformNameToAddIt) <<
" from tracked frame " <<
i);
1066 transformMatrix->Identity();
1067 status = TOOL_INVALID;
1069 trackedFrame->SetFrameTransform(transformName, transformMatrix);
1070 trackedFrame->SetFrameTransformStatus(transformName, status);
1078 PlusStatus FillRectangle(vtkIGSIOTrackedFrameList* trackedFrameList,
const std::vector<unsigned int>& fillRectOrigin,
const std::vector<unsigned int>& fillRectSize,
int fillGrayLevel)
1080 if (trackedFrameList == NULL)
1082 LOG_ERROR(
"Tracked frame list is NULL!");
1085 if (fillRectOrigin.size() != 2 || fillRectSize.size() != 2)
1087 LOG_ERROR(
"Fill rectangle origin or size is not specified correctly");
1091 for (
unsigned int i = 0;
i < trackedFrameList->GetNumberOfTrackedFrames(); ++
i)
1093 igsioTrackedFrame* trackedFrame = trackedFrameList->GetTrackedFrame(
i);
1094 igsioVideoFrame* videoFrame = trackedFrame->GetImageData();
1095 FrameSizeType frameSize = { 0, 0, 0 };
1096 if (videoFrame == NULL || videoFrame->GetFrameSize(frameSize) !=
PLUS_SUCCESS)
1098 LOG_ERROR(
"Failed to retrieve pixel data from frame " <<
i <<
". Fill rectangle failed.");
1101 if (fillRectOrigin[0] >= frameSize[0] ||
1102 fillRectOrigin[1] >= frameSize[1])
1104 LOG_ERROR(
"Invalid fill rectangle origin is specified (" << fillRectOrigin[0] <<
", " << fillRectOrigin[1] <<
"). The image size is (" 1105 << frameSize[0] <<
", " << frameSize[1] <<
").");
1108 if (fillRectSize[0] <= 0 || fillRectOrigin[0] + fillRectSize[0] > frameSize[0] ||
1109 fillRectSize[1] <= 0 || fillRectOrigin[1] + fillRectSize[1] > frameSize[1])
1111 LOG_ERROR(
"Invalid fill rectangle size is specified (" << fillRectSize[0] <<
", " << fillRectSize[1] <<
"). The specified fill rectangle origin is (" 1112 << fillRectOrigin[0] <<
", " << fillRectOrigin[1] <<
") and the image size is (" << frameSize[0] <<
", " << frameSize[1] <<
").");
1115 if (videoFrame->GetVTKScalarPixelType() != VTK_UNSIGNED_CHAR)
1117 LOG_ERROR(
"Fill rectangle is supported only for B-mode images (unsigned char type)");
1120 unsigned char fillData = 0;
1121 if (fillGrayLevel < 0)
1125 else if (fillGrayLevel > 255)
1131 fillData = fillGrayLevel;
1133 for (
unsigned int y = 0;
y < fillRectSize[1];
y++)
1135 memset(static_cast<unsigned char*>(videoFrame->GetScalarPointer()) + (fillRectOrigin[1] +
y)*frameSize[0] + fillRectOrigin[0], fillData, fillRectSize[0]);
1142 PlusStatus CropRectangle(vtkIGSIOTrackedFrameList* trackedFrameList, igsioVideoFrame::FlipInfoType& flipInfo,
const std::vector<int>& cropRectOrigin,
const std::vector<int>& cropRectSize)
1144 if (trackedFrameList == NULL)
1146 LOG_ERROR(
"Tracked frame list is NULL!");
1149 std::array<int, 3> rectOrigin = { cropRectOrigin[0], cropRectOrigin[1], cropRectOrigin.size() == 3 ? cropRectOrigin[2] : 0 };
1150 std::array<int, 3> rectSize = { cropRectSize[0], cropRectSize[1], cropRectSize.size() == 3 ? cropRectSize[2] : 1 };
1152 vtkSmartPointer<vtkMatrix4x4> tfmMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
1153 tfmMatrix->Identity();
1154 tfmMatrix->SetElement(0, 3, -rectOrigin[0]);
1155 tfmMatrix->SetElement(1, 3, -rectOrigin[1]);
1156 tfmMatrix->SetElement(2, 3, -rectOrigin[2]);
1157 igsioTransformName imageToCroppedImage(
"Image",
"CroppedImage");
1159 for (
unsigned int i = 0;
i < trackedFrameList->GetNumberOfTrackedFrames(); ++
i)
1161 igsioTrackedFrame* trackedFrame = trackedFrameList->GetTrackedFrame(
i);
1162 igsioVideoFrame* videoFrame = trackedFrame->GetImageData();
1164 FrameSizeType frameSize = { 0, 0, 0 };
1165 if (videoFrame == NULL || videoFrame->GetFrameSize(frameSize) !=
PLUS_SUCCESS)
1167 LOG_ERROR(
"Failed to retrieve pixel data from frame " <<
i <<
". Crop rectangle failed.");
1171 vtkSmartPointer<vtkImageData> croppedImage = vtkSmartPointer<vtkImageData>::New();
1173 igsioVideoFrame::FlipClipImage(videoFrame->GetImage(), flipInfo, rectOrigin, rectSize, croppedImage);
1174 videoFrame->DeepCopyFrom(croppedImage);
1175 trackedFrame->SetFrameTransform(imageToCroppedImage, tfmMatrix);
1176 trackedFrame->SetFrameTransformStatus(imageToCroppedImage, TOOL_OK);
PlusStatus DecimateSequenceFile(vtkIGSIOTrackedFrameList *trackedFrameList, unsigned int decimationFactor)
PlusStatus MixTrackedFrameLists(vtkIGSIOTrackedFrameList *trackedFrameList, std::vector< std::string > inputFileNames)
PlusStatus TrimSequenceFile(vtkIGSIOTrackedFrameList *trackedFrameList, unsigned int firstFrameIndex, unsigned int lastFrameIndex)
PlusStatus FillRectangle(vtkIGSIOTrackedFrameList *trackedFrameList, const std::vector< unsigned int > &fillRectOrigin, const std::vector< unsigned int > &fillRectSize, int fillGrayLevel)
PlusStatus AppendTrackedFrameLists(vtkIGSIOTrackedFrameList *trackedFrameList, std::vector< std::string > inputFileNames, bool incrementTimestamps, std::vector< std::string > customHeaderFields)
static igsioStatus Write(const std::string &filename, igsioTrackedFrame *frame, US_IMAGE_ORIENTATION orientationInFile=US_IMG_ORIENT_MF, bool useCompression=true, bool EnableImageDataWrite=true)
static igsioStatus Read(const std::string &filename, vtkIGSIOTrackedFrameList *frameList)
int main(int argc, char **argv)
PlusStatus ConvertStringToMatrix(std::string &strMatrix, vtkMatrix4x4 *matrix)
PlusStatus CropRectangle(vtkIGSIOTrackedFrameList *trackedFrameList, igsioVideoFrame::FlipInfoType &flipInfo, const std::vector< int > &cropRectOrigin, const std::vector< int > &cropRectSize)
static vtkIGSIOLogger * Instance()
PlusStatus AddTransform(vtkIGSIOTrackedFrameList *trackedFrameList, std::vector< std::string > transformNamesToAdd, std::string deviceSetConfigurationFileName)
PlusStatus UpdateFrameFieldValue(FrameFieldUpdate &fieldUpdate)
Direction vectors of rods y
PlusStatus DeleteFrameField(vtkIGSIOTrackedFrameList *trackedFrameList, std::string fieldName)
static PlusStatus ReadDeviceSetConfigurationFromFile(vtkXMLDataElement *config, const char *filename)