7 #include "PlusConfigure.h" 15 #include "vtkImageAlgorithm.h" 16 #include "vtkInformation.h" 17 #include "vtkTransform.h" 18 #include "vtkPolyData.h" 19 #include "vtkPolyDataToImageStencil.h" 20 #include "vtkSmartPointer.h" 21 #include "vtkImageStencil.h" 22 #include "vtkInformationVector.h" 23 #include "vtkImageData.h" 24 #include "vtkObjectFactory.h" 25 #include "vtkPointData.h" 26 #include "vtkTransformPolyDataFilter.h" 27 #include "vtkImageStencilData.h" 28 #include "vtkPolyData.h" 29 #include "vtksys/SystemTools.hxx" 35 #include "vtkLineSource.h" 36 #include "vtkPerlinNoise.h" 37 #include "vtkProbeFilter.h" 38 #include "vtkSampleFunction.h" 46 : TransformRepository(NULL)
48 SetNumberOfInputPorts(0);
49 SetNumberOfOutputPorts(1);
51 this->ImageCoordinateFrame = NULL;
52 this->ReferenceCoordinateFrame = NULL;
54 this->NumberOfScanlines = 256;
55 this->NumberOfSamplesPerScanline = 1000;
56 this->IncomingIntensityMwPerCm2 = 100;
57 this->FrequencyMhz = 2.5;
58 this->BrightnessConversionGamma = 0.333;
59 this->BrightnessConversionOffset = 30;
60 this->BrightnessConversionScale = 30;
64 this->NoiseAmplitude = 0;
65 this->NoiseFrequency[0] = 0;
66 this->NoiseFrequency[1] = 0;
67 this->NoiseFrequency[2] = 0;
68 this->NoisePhase[0] = 0;
69 this->NoisePhase[1] = 0;
70 this->NoisePhase[2] = 0;
81 if (this->RfProcessor != NULL)
83 this->RfProcessor->Delete();
84 this->RfProcessor = NULL;
92 this->Superclass::PrintSelf(os, indent);
98 info->Set(vtkDataObject::DATA_TYPE_NAME(),
"vtkImageData");
110 u.x[1] = (
int)(
b * (u.x[1] - 1072632447) + 1072632447);
118 if (this->TransformRepository == NULL)
120 LOG_ERROR(
"No transform repository is specified ");
125 vtkInformation* outInfo = outputVector->GetInformationObject(0);
127 for (std::vector<PlusSpatialModel>::iterator spatialModelIt = this->SpatialModels.begin(); spatialModelIt != this->SpatialModels.end(); ++spatialModelIt)
129 spatialModelIt->SetImagingFrequencyMhz(this->FrequencyMhz);
131 this->TransducerSpatialModel.SetImagingFrequencyMhz(this->FrequencyMhz);
133 vtkSmartPointer<vtkImageData> scanLines = vtkSmartPointer<vtkImageData>::New();
134 scanLines->SetExtent(0, this->NumberOfSamplesPerScanline - 1, 0, this->NumberOfScanlines - 1, 0, 0);
135 scanLines->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
138 vtkSmartPointer<vtkPoints> scanLineIntersectionWithModel = vtkSmartPointer<vtkPoints>::New();
141 if (scanConverter == NULL)
143 LOG_ERROR(
"ScanConverter is not defined");
150 double outputImageSpacingMm[3] = {1.0, 1.0, 1.0};
156 vtkSmartPointer<vtkLineSource> noiseSamplerLine_Reference = vtkSmartPointer<vtkLineSource>::New();
157 vtkSmartPointer<vtkPerlinNoise> noiseFunction = vtkSmartPointer<vtkPerlinNoise>::New();
158 double samplePointPosition_Reference[3] = {0, 0, 0};
159 if (this->NoiseAmplitude > 0)
161 noiseSamplerLine_Reference->SetResolution(this->NumberOfSamplesPerScanline - 1);
162 noiseFunction->SetAmplitude(this->NoiseAmplitude);
163 noiseFunction->SetFrequency(this->NoiseFrequency);
164 noiseFunction->SetPhase(this->NoisePhase);
168 vtkSmartPointer<vtkMatrix4x4> imageToReferenceMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
169 if (this->TransformRepository->GetTransform(imageToReferenceTransformName, imageToReferenceMatrix) !=
PLUS_SUCCESS)
171 std::string strTransformName;
172 imageToReferenceTransformName.GetTransformName(strTransformName);
173 LOG_ERROR(
"Failed to get transform from repository: " << strTransformName);
176 vtkImageData* simulatedUsImage = vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
177 if (simulatedUsImage == NULL)
179 LOG_ERROR(
"vtkPlusUsSimulatorAlgo output type is invalid");
182 simulatedUsImage->AllocateScalars(VTK_UNSIGNED_CHAR, 1);
186 vtkSmartPointer<vtkMatrix4x4> referenceToImageMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
187 vtkMatrix4x4::Invert(imageToReferenceMatrix, referenceToImageMatrix);
190 vtkPoints* samplePointPositions_Reference = 0;
192 std::vector<double> intensities;
194 double scanLineStartPoint_Image[4] = {0, 0, 0, 1};
195 double scanLineEndPoint_Image[4] = {0, 0, 0, 1};
196 double scanLineStartPoint_Reference[4] = {0, 0, 0, 1};
197 double scanLineEndPoint_Reference[4] = {0, 0, 0, 1};
199 for (std::vector<PlusSpatialModel>::iterator spatialModelIt = this->SpatialModels.begin(); spatialModelIt != this->SpatialModels.end(); ++spatialModelIt)
201 vtkSmartPointer<vtkMatrix4x4> referenceToObjectMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
202 if (!spatialModelIt->GetObjectCoordinateFrame().empty())
204 igsioTransformName referenceToObjectTransformName(this->
GetReferenceCoordinateFrame(), spatialModelIt->GetObjectCoordinateFrame());
205 if (this->TransformRepository->GetTransform(referenceToObjectTransformName, referenceToObjectMatrix) !=
PLUS_SUCCESS)
207 std::string strTransformName;
208 imageToReferenceTransformName.GetTransformName(strTransformName);
209 LOG_ERROR(
"Error computing spatial position of " << spatialModelIt->GetName() <<
" SpatialModel: failed to get transform from repository: " << strTransformName);
212 spatialModelIt->SetReferenceToObjectTransform(referenceToObjectMatrix);
215 for (
int scanLineIndex = 0; scanLineIndex < this->NumberOfScanlines; scanLineIndex++)
217 scanConverter->
GetScanLineEndPoints(scanLineIndex, scanLineStartPoint_Image, scanLineEndPoint_Image);
218 imageToReferenceMatrix->MultiplyPoint(scanLineStartPoint_Image, scanLineStartPoint_Reference);
219 imageToReferenceMatrix->MultiplyPoint(scanLineEndPoint_Image, scanLineEndPoint_Reference);
221 if (this->NoiseAmplitude > 0)
223 noiseSamplerLine_Reference->SetPoint1(scanLineStartPoint_Reference);
224 noiseSamplerLine_Reference->SetPoint2(scanLineEndPoint_Reference);
225 noiseSamplerLine_Reference->Update();
226 samplePointPositions_Reference = noiseSamplerLine_Reference->GetOutput()->GetPoints();
230 std::deque<PlusSpatialModel::LineIntersectionInfo> lineIntersectionsWithModels;
231 for (std::vector<PlusSpatialModel>::iterator spatialModelIt = this->SpatialModels.begin(); spatialModelIt != this->SpatialModels.end(); ++spatialModelIt)
234 spatialModelIt->GetLineIntersections(lineIntersectionsWithModels, scanLineStartPoint_Reference, scanLineEndPoint_Reference);
239 int currentPixelIndex = 0;
240 int scanLineExtent[6] = {0, this->NumberOfSamplesPerScanline - 1, scanLineIndex, scanLineIndex, 0, 0};
241 unsigned char* dstPixelAddress = (
unsigned char*)scanLines->GetScalarPointerForExtent(scanLineExtent);
242 double incomingBeamIntensity = this->IncomingIntensityMwPerCm2 * 1000;
243 int numIntersectionPoints = lineIntersectionsWithModels.size();
244 if (numIntersectionPoints < 1)
246 LOG_ERROR(
"No intersections with any SpatialObjects. Probably no background object is specified.");
250 for (vtkIdType intersectionIndex = 0; (intersectionIndex <= numIntersectionPoints) && (currentPixelIndex < this->NumberOfSamplesPerScanline); intersectionIndex++)
253 int endOfSegmentPixelIndex = currentPixelIndex;
254 double distanceOfIntersectionPointFromScanLineStartPointMm = 0;
255 if (intersectionIndex + 1 < numIntersectionPoints)
257 distanceOfIntersectionPointFromScanLineStartPointMm = lineIntersectionsWithModels[intersectionIndex + 1].IntersectionDistanceFromStartPointMm;
258 endOfSegmentPixelIndex = distanceOfIntersectionPointFromScanLineStartPointMm / distanceBetweenScanlineSamplePointsMm;
259 if (endOfSegmentPixelIndex > this->NumberOfSamplesPerScanline)
262 endOfSegmentPixelIndex = this->NumberOfSamplesPerScanline;
268 endOfSegmentPixelIndex = this->NumberOfSamplesPerScanline;
271 int numberOfFilledPixels = endOfSegmentPixelIndex - currentPixelIndex;
272 if (numberOfFilledPixels < 1)
278 if (intersectionIndex < numIntersectionPoints)
280 currentModel = lineIntersectionsWithModels[intersectionIndex].Model;
285 currentModel = lineIntersectionsWithModels[numIntersectionPoints - 1].Model;
288 double outgoingBeamIntensity = 0;
289 currentModel->
CalculateIntensity(intensities, numberOfFilledPixels, distanceBetweenScanlineSamplePointsMm, previousModel->
GetAcousticImpedanceMegarayls(), incomingBeamIntensity, outgoingBeamIntensity, lineIntersectionsWithModels[intersectionIndex].IntersectionIncidenceAngleRad);
290 previousModel = currentModel;
292 if (this->NoiseAmplitude > 0)
294 for (
int pixelIndex = 0; pixelIndex < numberOfFilledPixels; pixelIndex++)
296 samplePointPositions_Reference->GetPoint(currentPixelIndex + pixelIndex, samplePointPosition_Reference);
297 double noise = noiseFunction->EvaluateFunction(samplePointPosition_Reference);
299 (*dstPixelAddress++) = std::max(std::min(this->BrightnessConversionOffset + this->BrightnessConversionScale *
fastPow(intensities[pixelIndex], this->BrightnessConversionGamma) + noise, 255.0), 0.0);
304 for (
int pixelIndex = 0; pixelIndex < numberOfFilledPixels; pixelIndex++)
306 (*dstPixelAddress++) = std::max(std::min(this->BrightnessConversionOffset + this->BrightnessConversionScale *
fastPow(intensities[pixelIndex], this->BrightnessConversionGamma), 255.0), 0.0);
310 incomingBeamIntensity = outgoingBeamIntensity;
312 currentPixelIndex += numberOfFilledPixels;
316 vtkImageData* simulatedUsImage = vtkImageData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
317 if (simulatedUsImage == NULL)
319 LOG_ERROR(
"vtkPlusUsSimulatorAlgo output type is invalid");
322 this->RfProcessor->
SetRfFrame(scanLines, US_IMG_BRIGHTNESS);
353 std::map< PlusSpatialModel*, int > cohesiveness;
354 for (
unsigned int i = 0;
i < this->SpatialModels.size();
i++)
356 cohesiveness[&this->SpatialModels[
i]] =
i;
359 std::list<PlusSpatialModel*> insideModel;
360 for (std::deque<PlusSpatialModel::LineIntersectionInfo>::iterator intersectionIt = lineIntersectionsWithModels.begin();
361 intersectionIt != lineIntersectionsWithModels.end(); ++intersectionIt)
363 std::list<PlusSpatialModel*>::iterator foundThisModelAt = find(insideModel.begin(), insideModel.end(), intersectionIt->Model);
364 if (foundThisModelAt != insideModel.end())
367 insideModel.erase(foundThisModelAt);
372 int thisModelsCohesiveness = cohesiveness[intersectionIt->Model];
373 std::list<PlusSpatialModel*>::iterator insertThisModelAt = insideModel.begin();
374 while (insertThisModelAt != insideModel.end() && cohesiveness[*insertThisModelAt] > thisModelsCohesiveness)
378 insideModel.insert(insertThisModelAt, intersectionIt->Model);
380 if (insideModel.empty())
382 LOG_ERROR(
"No model is defined in one segment of the scanline");
386 intersectionIt->Model = insideModel.front();
394 LOG_TRACE(
"vtkPlusUsSimulatorVideoSource::ReadConfiguration");
396 XML_FIND_NESTED_ELEMENT_REQUIRED(usSimulatorAlgoElement, config,
"vtkPlusUsSimulatorAlgo");
398 XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(
int, NumberOfScanlines, usSimulatorAlgoElement);
399 XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(
int, NumberOfSamplesPerScanline, usSimulatorAlgoElement);
400 XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(
double, FrequencyMhz, usSimulatorAlgoElement);
401 XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(
double, BrightnessConversionGamma, usSimulatorAlgoElement);
402 XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(
double, BrightnessConversionOffset, usSimulatorAlgoElement);
403 XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(
double, BrightnessConversionScale, usSimulatorAlgoElement);
404 XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(
double, IncomingIntensityMwPerCm2, usSimulatorAlgoElement);
405 XML_READ_SCALAR_ATTRIBUTE_OPTIONAL(
double, NoiseAmplitude, usSimulatorAlgoElement);
406 XML_READ_VECTOR_ATTRIBUTE_OPTIONAL(
double, 3, NoiseFrequency, usSimulatorAlgoElement);
407 XML_READ_VECTOR_ATTRIBUTE_OPTIONAL(
double, 3, NoisePhase, usSimulatorAlgoElement);
408 XML_READ_CSTRING_ATTRIBUTE_REQUIRED(ImageCoordinateFrame, usSimulatorAlgoElement);
409 XML_READ_CSTRING_ATTRIBUTE_REQUIRED(ReferenceCoordinateFrame, usSimulatorAlgoElement);
411 XML_FIND_NESTED_ELEMENT_REQUIRED(rfProcesingElement, usSimulatorAlgoElement,
"RfProcessing");
414 this->SpatialModels.clear();
415 for (
int i = 0;
i < usSimulatorAlgoElement->GetNumberOfNestedElements(); ++
i)
417 vtkXMLDataElement* spatialModelElement = usSimulatorAlgoElement->GetNestedElement(
i);
418 if (STRCASECMP(spatialModelElement->GetName(),
"SpatialModel") != 0)
427 this->SpatialModels.push_back(model);
437 if (scanConverter == NULL)
439 LOG_ERROR(
"Unable to determine frame size, ScanConverter is not defined");
virtual double * GetOutputImageSpacing()
virtual int FillOutputPortInformation(int port, vtkInformation *info)
virtual PlusStatus GetScanLineEndPoints(int scanLineIndex, double scanlineStartPoint_OutputImage[4], double scanlineEndPoint_OutputImage[4])=0
static vtkPlusRfProcessor * New()
virtual void SetInputImageExtent(int, int, int, int, int, int)
double IntersectionDistanceFromStartPointMm
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *spatialModelElement)
bool lineIntersectionLessThan(PlusSpatialModel::LineIntersectionInfo a, PlusSpatialModel::LineIntersectionInfo b)
void PrintSelf(ostream &os, vtkIndent indent)
virtual vtkPlusUsScanConvert * GetScanConverter()
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *rfElement)
virtual void SetTransformRepository(vtkIGSIOTransformRepository *)
virtual int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector)
virtual vtkImageData * GetBrightnessScanConvertedImage()
virtual PlusStatus SetRfFrame(vtkImageData *rfFrame, US_IMAGE_TYPE imageType)
~vtkPlusUsSimulatorAlgo()
Initial rotation matrix b
double fastPow(double a, double b)
void CalculateIntensity(std::vector< double > &reflectedIntensity, unsigned int numberOfFilledPixels, double distanceBetweenScanlineSamplePointsMm, double previousModelAcousticImpedanceMegarayls, double incidentIntensity, double &transmittedIntensity, double incidenceAngleRad)
void ConvertLineModelIntersectionsToSegmentDescriptor(std::deque< PlusSpatialModel::LineIntersectionInfo > &lineIntersectionsWithModels)
Class that simulates ultrasound images from multiple surface models.
virtual void SetImageCoordinateFrame(const char *)
virtual double GetDistanceBetweenScanlineSamplePointsMm()=0
This is a base class for defining a common scan conversion algorithm interface for all kinds of probe...
virtual char * GetReferenceCoordinateFrame()
virtual FrameSizeType GetOutputImageSizePixel()
virtual char * GetImageCoordinateFrame()
vtkStandardNewMacro(vtkPlusUsSimulatorAlgo)
virtual PlusStatus ReadConfiguration(vtkXMLDataElement *config)
PlusStatus GetFrameSize(FrameSizeType &frameSize)
virtual void SetReferenceCoordinateFrame(const char *)
double GetAcousticImpedanceMegarayls()