8 #include "PlusConfigure.h" 9 #include "igsioCommon.h" 11 #include "igsioTrackedFrame.h" 12 #include "igsioVideoFrame.h" 14 #include "vtkIGSIOTrackedFrameList.h" 18 #include <vtkImageData.h> 20 #include <vtkSmartPointer.h> 21 #include <vtkXMLUtilities.h> 22 #include <vtksys/CommandLineArguments.hxx> 26 static const float DRAWING_COLOR = 255;
30 void DrawSector(vtkImageData* imageData,
int* imageExtent,
double* origin,
double* fanAnglesDeg,
double radius,
int numberOfPoints)
32 double startAngleRad = vtkMath::RadiansFromDegrees(fanAnglesDeg[0]);
33 double deltaAngleRad = vtkMath::RadiansFromDegrees((fanAnglesDeg[1] - fanAnglesDeg[0]) / (numberOfPoints - 1));
34 for (
int pointIndex = 0; pointIndex < numberOfPoints; ++pointIndex)
36 double angleRad = startAngleRad + pointIndex * deltaAngleRad;
37 int pixelCoordX = origin[0] + radius * sin(angleRad);
38 int pixelCoordY = origin[1] + radius * cos(angleRad);
39 if (pixelCoordX < imageExtent[0] || pixelCoordX > imageExtent[1] || pixelCoordY < imageExtent[2] || pixelCoordY > imageExtent[3])
44 imageData->SetScalarComponentFromFloat(pixelCoordX, pixelCoordY, 0, 0, DRAWING_COLOR);
49 void DrawFan(vtkImageData* imageData,
double* fanOrigin,
double startRadius,
double stopRadius,
double* fanAnglesDeg,
int pointSpacing,
bool drawOrigin)
51 double fanAnglesRad[2] = {vtkMath::RadiansFromDegrees(fanAnglesDeg[0]), vtkMath::RadiansFromDegrees(fanAnglesDeg[1])};
52 int* extent = imageData->GetExtent();
56 int numberOfPointsForDrawing = startRadius / 10;
57 double rounded = std::round(fanOrigin[1]);
58 unsigned int val = static_cast<unsigned int>(rounded);
59 std::array<int, 3> startPoint = { static_cast<int>(std::round(fanOrigin[0])),
60 static_cast<int>(std::round(fanOrigin[1])),
63 std::array<int, 3> endPointLeft = { static_cast<int>(std::round(fanOrigin[0] + startRadius * sin(fanAnglesRad[0]))),
64 static_cast<int>(std::round(fanOrigin[1] + startRadius * cos(fanAnglesRad[0]))),
67 std::array<int, 3> endPointRight = { static_cast<int>(std::round(fanOrigin[0] + startRadius * sin(fanAnglesRad[1]))),
68 static_cast<int>(std::round(fanOrigin[1] + startRadius * cos(fanAnglesRad[1]))),
71 igsioCommon::DrawLine(*imageData, DRAWING_COLOR, igsioCommon::LINE_STYLE_DOTS, startPoint, endPointLeft, numberOfPointsForDrawing);
72 igsioCommon::DrawLine(*imageData, DRAWING_COLOR, igsioCommon::LINE_STYLE_DOTS, startPoint, endPointRight, numberOfPointsForDrawing);
76 int numberOfPointsForDrawing = (stopRadius - startRadius) / pointSpacing;
78 std::array<int, 3> startPoint = { static_cast<int>(std::round(fanOrigin[0] + startRadius * sin(fanAnglesRad[0]))),
79 static_cast<int>(std::round(fanOrigin[1] + startRadius * cos(fanAnglesRad[0]))),
82 std::array<int, 3> endPoint = { static_cast<int>(std::round(fanOrigin[0] + stopRadius * sin(fanAnglesRad[0]))),
83 static_cast<int>(std::round(fanOrigin[1] + stopRadius * cos(fanAnglesRad[0]))),
86 igsioCommon::DrawLine(*imageData, DRAWING_COLOR, igsioCommon::LINE_STYLE_DOTS, startPoint, endPoint, numberOfPointsForDrawing);
90 std::array<int, 3> startPoint = { static_cast<int>(std::round(fanOrigin[0] + startRadius * sin(fanAnglesRad[1]))),
91 static_cast<int>(std::round(fanOrigin[1] + startRadius * cos(fanAnglesRad[1]))),
94 std::array<int, 3> endPoint = { static_cast<int>(std::round(fanOrigin[0] + stopRadius * sin(fanAnglesRad[1]))),
95 static_cast<int>(std::round(fanOrigin[1] + stopRadius * cos(fanAnglesRad[1]))),
98 igsioCommon::DrawLine(*imageData, DRAWING_COLOR, igsioCommon::LINE_STYLE_DOTS, startPoint, endPoint, numberOfPointsForDrawing);
103 int numberOfPointsForDrawing = startRadius * (fanAnglesRad[1] - fanAnglesRad[0]) / pointSpacing;
104 DrawSector(imageData, extent, fanOrigin, fanAnglesDeg, startRadius, numberOfPointsForDrawing);
105 numberOfPointsForDrawing = stopRadius * (fanAnglesRad[1] - fanAnglesRad[0]) / pointSpacing;
106 DrawSector(imageData, extent, fanOrigin, fanAnglesDeg, stopRadius, numberOfPointsForDrawing);
113 int* clipRectangleOrigin = reconstructor->GetClipRectangleOrigin();
114 int* clipRectangleSize = reconstructor->GetClipRectangleSize();
115 int* extent = imageData->GetExtent();
116 int numberOfPoints = 200;
120 std::array<int, 3> startPoint = { static_cast<int>(std::round(clipRectangleOrigin[0])),
121 static_cast<int>(std::round(clipRectangleOrigin[1])),
124 std::array<int, 3> endPoint = { static_cast<int>(std::round(clipRectangleOrigin[0] + clipRectangleSize[0] - 1)),
125 static_cast<int>(std::round(clipRectangleOrigin[1])),
128 igsioCommon::DrawLine(*imageData, DRAWING_COLOR, igsioCommon::LINE_STYLE_DOTS, startPoint, endPoint, numberOfPoints);
131 std::array<int, 3> startPoint = { static_cast<int>(std::round(clipRectangleOrigin[0])),
132 static_cast<int>(std::round(clipRectangleOrigin[1] + clipRectangleSize[1] - 1)),
135 std::array<int, 3> endPoint = { static_cast<int>(std::round(clipRectangleOrigin[0] + clipRectangleSize[0] - 1)),
136 static_cast<int>(std::round(clipRectangleOrigin[1] + clipRectangleSize[1] - 1)),
139 igsioCommon::DrawLine(*imageData, DRAWING_COLOR, igsioCommon::LINE_STYLE_DOTS, startPoint, endPoint, numberOfPoints);
144 std::array<int, 3> startPoint = { static_cast<int>(std::round(clipRectangleOrigin[0])),
145 static_cast<int>(std::round(clipRectangleOrigin[1])),
148 std::array<int, 3> endPoint = { static_cast<int>(std::round(clipRectangleOrigin[0])),
149 static_cast<int>(std::round(clipRectangleOrigin[1] + clipRectangleSize[1] - 1)),
152 igsioCommon::DrawLine(*imageData, DRAWING_COLOR, igsioCommon::LINE_STYLE_DOTS, startPoint, endPoint, numberOfPoints);
155 std::array<int, 3> startPoint = { static_cast<int>(std::round(clipRectangleOrigin[0] + clipRectangleSize[0] - 1)),
156 static_cast<int>(std::round(clipRectangleOrigin[1])),
159 std::array<int, 3> endPoint = { static_cast<int>(std::round(clipRectangleOrigin[0] + clipRectangleSize[0] - 1)),
160 static_cast<int>(std::round(clipRectangleOrigin[1] + clipRectangleSize[1] - 1)),
163 igsioCommon::DrawLine(*imageData, DRAWING_COLOR, igsioCommon::LINE_STYLE_DOTS, startPoint, endPoint, numberOfPoints);
170 bool isImageEmpty =
false;
171 reconstructor->UpdateFanAnglesFromImage(imageData, isImageEmpty);
172 if (!reconstructor->FanClippingApplied())
177 double* fanOrigin = reconstructor->GetFanOrigin();
178 double* maxFanAnglesDeg = reconstructor->GetFanAnglesDeg();
179 double* detectedFanAnglesDeg = reconstructor->GetDetectedFanAnglesDeg();
180 double fanRadiusStartPixel = reconstructor->GetFanRadiusStartPixel();
181 double fanRadiusStopPixel = reconstructor->GetFanRadiusStopPixel();
186 DrawFan(imageData, fanOrigin, fanRadiusStartPixel, fanRadiusStopPixel, maxFanAnglesDeg, 10,
true );
190 if (reconstructor->GetEnableFanAnglesAutoDetect())
193 DrawFan(imageData, fanOrigin, fanRadiusStartPixel, fanRadiusStopPixel, maxFanAnglesDeg, 10,
true );
194 DrawFan(imageData, fanOrigin, fanRadiusStartPixel, fanRadiusStopPixel, detectedFanAnglesDeg, 1,
false );
199 DrawFan(imageData, fanOrigin, fanRadiusStartPixel, fanRadiusStopPixel, maxFanAnglesDeg, 1,
true );
206 int main(
int argc,
char** argv)
209 bool printHelp(
false);
210 std::string inputImgSeqFileName;
211 std::string outputImgSeqFileName;
212 std::string inputConfigFileName;
213 int verboseLevel = vtkPlusLogger::LOG_LEVEL_UNDEFINED;
215 vtksys::CommandLineArguments args;
216 args.Initialize(argc, argv);
218 args.AddArgument(
"--source-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputImgSeqFileName,
"Input ultrasound image sequence.");
219 args.AddArgument(
"--output-seq-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &outputImgSeqFileName,
"Output ultrasound sequence, with clipping rectangle and fan overlaid.");
220 args.AddArgument(
"--config-file", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &inputConfigFileName,
"The ultrasound sequence config file.");
221 args.AddArgument(
"--help", vtksys::CommandLineArguments::NO_ARGUMENT, &printHelp,
"Print this help.");
222 args.AddArgument(
"--verbose", vtksys::CommandLineArguments::EQUAL_ARGUMENT, &verboseLevel,
"Verbose level (1=error only, 2=warning, 3=info, 4=debug, 5=trace)");
227 std::cerr <<
"Error parsing arguments." << std::endl;
228 std::cout <<
"Help: " << args.GetHelp() << std::endl;
234 std::cout << args.GetHelp() << std::endl;
241 if (inputImgSeqFileName.empty())
243 LOG_ERROR(
"--seq-file required");
247 if (inputConfigFileName.empty())
249 LOG_ERROR(
"--config-file required");
254 vtkSmartPointer<vtkIGSIOTrackedFrameList> trackedFrameList = vtkSmartPointer<vtkIGSIOTrackedFrameList>::New();
257 LOG_ERROR(
"Unable to load input sequences file.");
262 vtkSmartPointer<vtkXMLDataElement> configRootElement = vtkSmartPointer<vtkXMLDataElement>::New();
265 LOG_ERROR(
"Unable to read configuration from file " << inputConfigFileName.c_str());
268 vtkXMLDataElement* volumeReconstructionElement = configRootElement->LookupElementWithName(
"VolumeReconstruction");
269 if (volumeReconstructionElement == NULL)
271 LOG_ERROR(
"VolumeReconstruction element was not found in input configuration file");
274 vtkSmartPointer<vtkPlusVolumeReconstructor> reconstructor = vtkSmartPointer<vtkPlusVolumeReconstructor>::New();
275 if (reconstructor->ReadConfiguration(volumeReconstructionElement->GetParent()) ==
PLUS_FAIL)
277 LOG_ERROR(
"Failed to parse VolumeReconstruction element in input configuration file");
282 int numberOfFrames = trackedFrameList->GetNumberOfTrackedFrames();
283 LOG_INFO(
"Processing " << numberOfFrames <<
" frames...");
284 for (
int frameIndex = 0; frameIndex < numberOfFrames; frameIndex++)
286 igsioTrackedFrame* frame = trackedFrameList->GetTrackedFrame(frameIndex);
287 vtkImageData* imageData = frame->GetImageData()->GetImage();
293 LOG_INFO(
"Writing new sequence to file...");
294 if (outputImgSeqFileName.empty())
296 int extensionDot = inputImgSeqFileName.find_last_of(
".");
297 if (extensionDot != std::string::npos)
299 inputImgSeqFileName = inputImgSeqFileName.substr(0, extensionDot);
301 outputImgSeqFileName = inputImgSeqFileName +
"-Scanlines.nrrd";
308 LOG_INFO(
"Writing to " << outputImgSeqFileName <<
" complete.");
int main(int argc, char **argv)
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)
Reconstructs a volume from tracked frames.
void DrawSector(vtkImageData *imageData, int *imageExtent, double *origin, double *fanAnglesDeg, double radius, int numberOfPoints)
void DrawClipFan(vtkImageData *imageData, vtkPlusVolumeReconstructor *reconstructor)
void DrawClipRectangle(vtkImageData *imageData, vtkPlusVolumeReconstructor *reconstructor)
static vtkIGSIOLogger * Instance()
void DrawFan(vtkImageData *imageData, double *fanOrigin, double startRadius, double stopRadius, double *fanAnglesDeg, int pointSpacing, bool drawOrigin)
static PlusStatus ReadDeviceSetConfigurationFromFile(vtkXMLDataElement *config, const char *filename)