23 #include "ITKUltrasound/itkBModeImageFilter.h" 29 #include "itkResampleImageFilter.h" 30 #include "itkCastImageFilter.h" 31 #include "itkCropImageFilter.h" 32 #include "itkRescaleIntensityImageFilter.h" 33 #include "itkIntensityWindowingImageFilter.h" 35 #include "itkMultiplyImageFilter.h" 39 m_StartTime(((float)
std::clock()) / CLOCKS_PER_SEC),
40 m_UseGUIOutPut(false),
43 m_UseBModeFilter(false),
44 m_CurrentlyRecording(false),
45 m_DataTypeModified(true),
46 m_DataTypeNext(
DataType::Image_uChar),
47 m_CurrentImageTimestamp(0),
48 m_PyroConnected(false),
49 m_ImageTimestampBuffer(),
51 m_UseBModeFilterModified(false),
52 m_UseBModeFilterNext(false),
53 m_ScatteringCoefficientModified(false),
54 m_CompensateForScatteringModified(false),
55 m_VerticalSpacingModified(false),
56 m_ScatteringCoefficient(15),
57 m_CompensateForScattering(false),
58 m_CompensateEnergy(false),
59 m_CompensateEnergyNext(false),
60 m_CompensateEnergyModified(false)
70 for (
int i = 5; i <= 25; ++i)
72 name =
"c:\\HomogeneousScatteringAssumptions\\Scattering" + std::to_string(i) +
".nrrd";
84 MITK_INFO(
"Pyro Debug") <<
"StopDataAcquisition: " <<
m_Pyro->StopDataAcquisition();
85 MITK_INFO(
"Pyro Debug") <<
"CloseConnection: " <<
m_Pyro->CloseConnection();
125 if (imageVector.size() != 2)
127 imageVector.resize(2);
132 float ImageEnergyValue = 0;
134 for (
int i = 100; i > 90 && ImageEnergyValue <= 0; --i)
139 if (ImageEnergyValue > 0) {
145 if (image ==
nullptr)
148 ImageEnergyValue = 40;
149 if (image ==
nullptr)
154 if (image.IsNotNull())
156 itkFloatImageType::Pointer itkImage;
178 unsigned int dim[] = { image->GetDimension(0),image->GetDimension(1),1};
179 imagePA->Initialize(image->GetPixelType(), 3, dim);
180 imagePA->SetGeometry(image->GetGeometry());
183 imageUS->Initialize(image->GetPixelType(), 3, dim);
184 imageUS->SetGeometry(image->GetGeometry());
187 imagePA->SetSlice(inputReadAccessorCopyPA.GetData(), 0);
189 imageUS->SetSlice(inputReadAccessorCopyUS.GetData(), 0);
205 image->SetSlice(inputReadAccessorPA.GetData(), 0);
207 image->SetSlice(inputReadAccessorUS.GetData(), 1);
219 bool doResampling = image->GetDimension(0) != curResizeImage->GetDimension(0) || image->GetDimension(1) != curResizeImage->GetDimension(1)
220 || image->GetGeometry()->GetSpacing()[0] != curResizeImage->GetGeometry()->GetSpacing()[0] || image->GetGeometry()->GetSpacing()[1] != curResizeImage->GetGeometry()->GetSpacing()[1];
225 double* rawOutputData =
new double[image->GetDimension(0)*image->GetDimension(1)];
226 double* rawScatteringData = (
double*)curResizeImage->GetData();
227 int sizeRawScatteringData = curResizeImage->GetDimension(0) * curResizeImage->GetDimension(1);
228 int imageSize = image->GetDimension(0)*image->GetDimension(1);
231 float upperCutoffmm = 1.5;
232 int lowerBound = std::round(upperCutoffmm / image->GetGeometry()->GetSpacing()[1])*image->GetDimension(0);
233 int upperBound = lowerBound + sizeRawScatteringData;
235 for (
int i = 0; i < lowerBound && i < imageSize; ++i)
237 rawOutputData[i] = 0;
239 for (
int i = lowerBound; i < upperBound && i < imageSize; ++i)
241 rawOutputData[i] = 1 / rawScatteringData[i-lowerBound];
243 for (
int i = upperBound; i < imageSize; ++i)
245 rawOutputData[i] = 0;
249 unsigned int dim[] = { image->GetDimension(0), image->GetDimension(1), 1 };
250 curResizeImage->Initialize(mitk::MakeScalarPixelType<double>(), 3, dim);
251 curResizeImage->SetGeometry(image->GetGeometry());
252 curResizeImage->SetSlice(rawOutputData,0);
254 delete[] rawOutputData;
264 image->SetSlice(inputReadAccessorPA.GetData(), 0);
272 unsigned int dim[] = { image->GetDimension(0),image->GetDimension(1),1 };
273 imageVector[0]->Initialize(image->GetPixelType(), 3, dim);
274 imageVector[0]->SetGeometry(image->GetGeometry());
277 imageVector[1]->Initialize(image->GetPixelType(), 3, dim);
278 imageVector[1]->SetGeometry(image->GetGeometry());
281 imageVector[0]->SetSlice(inputReadAccessorCopyPA.GetData(), 0);
283 imageVector[1]->SetSlice(inputReadAccessorCopyUS.GetData(), 0);
294 BModeFilterType::Pointer bModeFilter = BModeFilterType::New();
297 PhotoacousticBModeImageFilter::Pointer photoacousticBModeFilter = PhotoacousticBModeImageFilter::New();
299 itkFloatImageType::Pointer itkImage;
300 itkFloatImageType::Pointer bmode;
305 bModeFilter->SetInput(itkImage);
306 bModeFilter->SetDirection(1);
307 bmode = bModeFilter->GetOutput();
311 photoacousticBModeFilter->SetInput(itkImage);
312 photoacousticBModeFilter->SetDirection(1);
313 bmode = photoacousticBModeFilter->GetOutput();
320 typedef itk::CropImageFilter < itkFloatImageType, itkFloatImageType > CutImageFilter;
321 itkFloatImageType::SizeType cropSize;
322 itkFloatImageType::Pointer itkImage;
326 if(itkImage->GetLargestPossibleRegion().GetSize()[1] == 2048)
327 cropSize[1] = cutOffSize;
331 CutImageFilter::Pointer cutOffFilter = CutImageFilter::New();
332 cutOffFilter->SetInput(itkImage);
333 cutOffFilter->SetLowerBoundaryCropSize(cropSize);
334 cutOffFilter->UpdateLargestPossibleRegion();
340 typedef itk::ResampleImageFilter < itkFloatImageType, itkFloatImageType > ResampleImageFilter;
341 ResampleImageFilter::Pointer resampleImageFilter = ResampleImageFilter::New();
343 itkFloatImageType::Pointer itkImage;
346 itkFloatImageType::SpacingType outputSpacing;
347 itkFloatImageType::SizeType inputSize = itkImage->GetLargestPossibleRegion().GetSize();
348 itkFloatImageType::SizeType outputSize = inputSize;
350 outputSpacing[0] = itkImage->GetSpacing()[0] * (
static_cast<double>(inputSize[0]) / static_cast<double>(outputSize[0]));
351 outputSpacing[1] = verticalSpacing;
352 outputSpacing[2] = itkImage->GetSpacing()[2];
354 outputSize[1] = inputSize[1] * itkImage->GetSpacing()[1] / outputSpacing[1];
356 typedef itk::IdentityTransform<double, 3> TransformType;
357 resampleImageFilter->SetInput(itkImage);
358 resampleImageFilter->SetSize(outputSize);
359 resampleImageFilter->SetOutputSpacing(outputSpacing);
360 resampleImageFilter->SetTransform(TransformType::New());
362 resampleImageFilter->UpdateLargestPossibleRegion();
368 typedef itk::MultiplyImageFilter <itkFloatImageType, itkFloatImageType > MultiplyImageFilterType;
370 itkFloatImageType::Pointer itkImage;
373 MultiplyImageFilterType::Pointer multiplyFilter = MultiplyImageFilterType::New();
374 multiplyFilter->SetInput1(itkImage);
382 typedef itk::ResampleImageFilter < itkFloatImageType, itkFloatImageType > ResampleImageFilter;
383 ResampleImageFilter::Pointer resampleImageFilter = ResampleImageFilter::New();
385 itkFloatImageType::Pointer itkImage;
389 itkFloatImageType::SpacingType outputSpacingItk;
390 itkFloatImageType::SizeType inputSizeItk = itkImage->GetLargestPossibleRegion().GetSize();
391 itkFloatImageType::SizeType outputSizeItk = inputSizeItk;
392 itkFloatImageType::SpacingType inputSpacing = itkImage->GetSpacing();
394 outputSizeItk[0] = outputSize[0];
395 outputSizeItk[1] = 10*(inputSpacing[1] * inputSizeItk[1]) / (outputSpacing[1]);
396 outputSizeItk[2] = 1;
398 outputSpacingItk[0] = 0.996 * inputSpacing[0] * (
static_cast<double>(inputSizeItk[0]) / static_cast<double>(outputSizeItk[0]));
399 outputSpacingItk[1] = inputSpacing[1] * (
static_cast<double>(inputSizeItk[1]) / static_cast<double>(outputSizeItk[1]));
400 outputSpacingItk[2] = outputSpacing[2];
402 typedef itk::IdentityTransform<double, 3> TransformType;
403 resampleImageFilter->SetInput(itkImage);
404 resampleImageFilter->SetSize(outputSizeItk);
405 resampleImageFilter->SetOutputSpacing(outputSpacingItk);
406 resampleImageFilter->SetTransform(TransformType::New());
408 resampleImageFilter->UpdateLargestPossibleRegion();
414 typedef itk::MultiplyImageFilter <itkFloatImageType, itkFloatImageType > MultiplyImageFilterType;
416 itkFloatImageType::Pointer itkImage;
419 MultiplyImageFilterType::Pointer multiplyFilter = MultiplyImageFilterType::New();
420 multiplyFilter->SetInput1(itkImage);
421 multiplyFilter->SetConstant(value);
427 short* rfDataChannelData,
428 int& channelDataChannelsPerDataset,
429 int& channelDataSamplesPerChannel,
430 int& channelDataTotalDatasets,
432 short* rfDataArrayBeamformed,
433 int& beamformedLines,
434 int& beamformedSamples,
435 int& beamformedTotalDatasets,
437 unsigned char* imageData,
440 int& imageBytesPerPixel,
451 MITK_INFO <<
"[Pyro Debug] OpenConnection: " <<
m_Pyro->OpenConnection();
452 MITK_INFO <<
"[Pyro Debug] StartDataAcquisition: " <<
m_Pyro->StartDataAcquisition();
456 bool writeImage = ((
m_DataType == DataType::Image_uChar) && (imageData !=
nullptr)) || ((
m_DataType == DataType::Beamformed_Short) && (rfDataArrayBeamformed !=
nullptr));
467 case DataType::Image_uChar: {
471 image->Initialize(mitk::MakeScalarPixelType<unsigned char>(), 3,
m_ImageDimensions);
474 case DataType::Beamformed_Short: {
483 image->GetGeometry()->Modified();
488 case DataType::Image_uChar: {
489 for (
unsigned char i = 0; i < imageSetsTotal; i++) {
490 image->SetSlice(&imageData[i*imageHeight*imageWidth], i);
495 case DataType::Beamformed_Short: {
496 short* flipme =
new short[beamformedLines*beamformedSamples*beamformedTotalDatasets];
497 int pixelsPerImage = beamformedLines*beamformedSamples;
499 for (
unsigned char currentSet = 0; currentSet < beamformedTotalDatasets; currentSet++)
501 for (
unsigned short sample = 0; sample < beamformedSamples; sample++)
503 for (
unsigned short line = 0;
line < beamformedLines;
line++)
505 flipme[sample*beamformedLines +
line + pixelsPerImage*currentSet]
506 = rfDataArrayBeamformed[
line*beamformedSamples + sample + pixelsPerImage*currentSet];
511 for (
unsigned char i = 0; i < beamformedTotalDatasets; i++) {
512 image->SetSlice(&flipme[i*beamformedLines*beamformedSamples], i);
524 dim[0] = channelDataChannelsPerDataset;
525 dim[1] = channelDataSamplesPerChannel;
529 short* noOffset =
new short[channelDataChannelsPerDataset*channelDataSamplesPerChannel*channelDataTotalDatasets];
530 for (
unsigned char set = 0;
set < 1; ++
set)
532 for (
unsigned short sam = 0; sam < channelDataSamplesPerChannel; ++sam)
534 for (
unsigned short chan = 0; chan < channelDataChannelsPerDataset; ++chan)
536 noOffset[
set*channelDataSamplesPerChannel*channelDataChannelsPerDataset + sam * channelDataChannelsPerDataset + chan] =
537 rfDataChannelData[
set*channelDataSamplesPerChannel*channelDataChannelsPerDataset + sam * channelDataChannelsPerDataset + chan] -
offset;
543 for (
unsigned char i = 0; i < 1; ++i)
546 rawImage->Initialize(mitk::MakeScalarPixelType<short>(), 3, dim);
548 rawImage->SetSlice(&noOffset[i*channelDataChannelsPerDataset*channelDataSamplesPerChannel]);
555 rawSpacing[1] = recordTime / channelDataSamplesPerChannel * 1000000;
558 rawImage->GetGeometry()->SetSpacing(rawSpacing);
559 rawImage->GetGeometry()->Modified();
571 if (!
m_Pyro->IsSyncDelaySet() &&(image->GetPixelValueByIndex(pixel) < -30))
583 for (
unsigned char index = 0; index < image->GetDimension(2); ++index)
585 if (image->IsSliceSet(index))
588 unsigned int dim[] = { image ->GetDimension(0), image->GetDimension(1), 1};
604 MITK_INFO <<
"Retreaving Image Geometry Information for Spacing...";
612 case DataType::Image_uChar : {
616 m_ImageSpacing[1] = recordTime * speedOfSound / 2 * 1000 / imageHeight;
619 case DataType::Beamformed_Short : {
620 int& imageWidth = reconstructionLines;
623 m_ImageSpacing[1] = recordTime * speedOfSound / 2 * 1000 / imageHeight;
667 MITK_INFO <<
"Setting new DataType..." << dataT;
670 case DataType::Image_uChar :
673 case DataType::Beamformed_Short :
683 m_StartTime = ((float)std::clock()) / CLOCKS_PER_SEC;
704 inline void replaceAll(std::string& str,
const std::string& from,
const std::string& to) {
707 size_t start_pos = 0;
708 while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
709 str.replace(start_pos, from.length(), to);
710 start_pos += to.length();
743 time_t time = std::time(
nullptr);
744 time_t* timeptr = &time;
745 std::string currentDate = std::ctime(timeptr);
747 currentDate.pop_back();
754 std::string pathPA =
"c:\\ImageData\\" + currentDate +
"-" +
"PAbeamformed" +
".nrrd";
755 std::string pathUS =
"c:\\ImageData\\" + currentDate +
"-" +
"USImages" +
".nrrd";
756 std::string pathTS =
"c:\\ImageData\\" + currentDate +
"-" +
"ts" +
".csv";
757 std::string pathS =
"c:\\ImageData\\" + currentDate +
"-" +
"Settings" +
".txt";
762 std::string pathPARaw =
"c:\\ImageData\\" + currentDate +
"-" +
"PAraw" +
".nrrd";
763 std::string pathUSRaw =
"c:\\ImageData\\" + currentDate +
"-" +
"USImagesRaw" +
".nrrd";
797 ofstream timestampFile;
799 timestampFile.open(pathTS);
800 timestampFile <<
",timestamp,pixelvalue";
806 timestampFile.close();
810 ofstream settingsFile;
812 settingsFile.open(pathS);
815 settingsFile <<
"[General Parameters]\n";
816 settingsFile <<
"Scan Depth [mm] = " << sM.receivePhaseLengthSeconds * sM.averageSpeedOfSound / 2 * 1000 <<
"\n";
817 settingsFile <<
"Speed of Sound [m/s] = " << sM.averageSpeedOfSound <<
"\n";
818 settingsFile <<
"Excitation Frequency [MHz] = " << sM.transducerFrequencyHz/1000000 <<
"\n";
819 settingsFile <<
"Voltage [V] = " << sM.voltageV <<
"\n";
820 settingsFile <<
"TGC min = " << (int)sM.tgcdB[0] <<
" max = " << (
int)sM.tgcdB[7] <<
"\n";
822 settingsFile <<
"[Beamforming Parameters]\n";
823 settingsFile <<
"Reconstructed Lines = " << sM.reconstructionLines <<
"\n";
824 settingsFile <<
"Samples per Line = " << sM.reconstructionSamplesPerLine <<
"\n";
826 settingsFile.close();
828 else if (
m_Device->
GetScanMode().beamformingAlgorithm == (int)Beamforming::PlaneWaveCompound)
843 unsigned int events = 2;
848 values.push_back(image.GetPointer()->GetPixelValueByIndex(pixel));
854 unsigned int width = 32;
855 unsigned int height = 32;
862 width = recordedList.at(0)->GetDimension(0);
863 height = recordedList.at(0)->GetDimension(1);
865 else if (
m_DataType == DataType::Beamformed_Short)
876 unsigned int dimLaser[] = { (
unsigned int)width, (
unsigned int)height, (
unsigned int)(recordedList.size() / events)};
877 unsigned int dimSound[] = { (
unsigned int)width, (
unsigned int)height, (
unsigned int)(recordedList.size() / events * (events-1))};
879 PAImage->Initialize(recordedList.back()->GetPixelType(), 3, dimLaser);
880 PAImage->SetGeometry(recordedList.back()->GetGeometry());
881 USImage->Initialize(recordedList.back()->GetPixelType(), 3, dimSound);
882 USImage->SetGeometry(recordedList.back()->GetGeometry());
884 for (
int index = 0; index < recordedList.size(); ++index)
888 if (index % events == 0)
890 PAImage->SetSlice(inputReadAccessor.GetData(), index / events);
895 USImage->SetSlice(inputReadAccessor.GetData(), ((index - (index % events)) / events) + (index % events)-1);
902 unsigned int width = 32;
903 unsigned int height = 32;
917 unsigned int dimSound[] = { (
unsigned int)width, (
unsigned int)height, (
unsigned int)recordedList.size()};
919 USImage->Initialize(recordedList.back()->GetPixelType(), 3, dimSound);
920 USImage->SetGeometry(recordedList.back()->GetGeometry());
922 for (
int index = 0; index < recordedList.size(); ++index)
925 USImage->SetSlice(inputReadAccessor.GetData(), index);
void ImageDataCallback(short *rfDataChannelData, int &channelDataChannelsPerDataset, int &channelDataSamplesPerChannel, int &channelDataTotalDatasets, short *rfDataArrayBeamformed, int &beamformedLines, int &beamformedSamples, int &beamformedTotalDatasets, unsigned char *imageData, int &imageWidth, int &imageHeight, int &imagePixelFormat, int &imageSetsTotal, double &timeStamp)
SavingSettings m_SavingSettings
bool m_CompensateForScattering
long long m_CurrentImageTimestamp
std::vector< mitk::Image::Pointer > m_ImageBuffer
void UpdateImageGeometry()
float m_VerticalSpacingNext
void ModifyDataType(DataType dataT)
void replaceAll(std::string &str, const std::string &from, const std::string &to)
void OrderImagesUltrasound(Image::Pointer USImage, std::vector< Image::Pointer > recordedList)
void SetRecordingStatus(bool record)
void SetGUIOutput(std::function< void(QString)> out)
virtual ~USDiPhASImageSource()
mitk::Image::Pointer ApplyResampling(mitk::Image::Pointer inputImage, mitk::Vector3D outputSpacing, unsigned int outputSize[3])
mitk::USDiPhASDevice * m_Device
void SetVerticalSpacing(float mm)
mitk::Vector3D m_ImageSpacing
void ModifyScatteringCoefficient(int coeff)
bool m_CurrentlyRecording
std::vector< Image::Pointer > m_FluenceCompOriginal
bool m_ScatteringCoefficientModified
void ModifyEnergyCompensation(bool compensate)
mitk::OphirPyro::Pointer m_Pyro
Image::Pointer GrabItkImageMemory(itk::SmartPointer< ItkOutputImageType > &itkimage, mitk::Image *mitkImage=nullptr, const BaseGeometry *geometry=nullptr, bool update=true)
Grabs the memory of an itk::Image (with a specific type) and puts it into an mitk::Image.The memory is managed by the mitk::Image after calling this function. The itk::Image remains valid until the mitk::Image decides to free the memory.
std::vector< float > m_PixelValues
This specialization of mitk::Image only appends necessary Metadata to an MITK image. Otherwise it can safely be treated like it's mother class. To generate an USImage from a standard mitkImage, call the appropriate constructor USImage(image::Pointer)
std::vector< mitk::Image::Pointer > m_RawRecordedImages
std::vector< long long > m_ImageTimestampRecord
mitk::Image::Pointer ResampleOutputVertical(mitk::Image::Pointer image, float verticalSpacing=0.1)
bool m_CompensateEnergyModified
mitk::Image::Pointer MultiplyImage(mitk::Image::Pointer inputImage, double value)
bool m_CompensateEnergyNext
int m_ScatteringCoefficientNext
std::vector< long long > m_ImageTimestampBuffer
std::vector< Image::Pointer > m_FluenceCompResized
void ModifyCompensateForScattering(bool useIt)
void SetSavingSettings(SavingSettings settings)
std::function< void(QString)> m_GUIOutput
mitk::Image::Pointer image
mitk::Image::Pointer ApplyScatteringCompensation(mitk::Image::Pointer inputImage, int scatteringCoefficient)
void SetUseBModeFilter(bool isSet)
bool m_UseBModeFilterModified
std::vector< itk::Image< float, 3 >::Pointer > m_FluenceCompResizedItk
void MITKCORE_EXPORT CastToItkImage(const mitk::Image *mitkImage, itk::SmartPointer< ItkOutputImageType > &itkOutputImage)
Cast an mitk::Image to an itk::Image with a specific type.
mitk::Image::Pointer CutOffTop(mitk::Image::Pointer image, int cutOffSize=165)
static void Save(const mitk::BaseData *data, const std::string &path, bool setPathProperty=false)
Save a mitk::BaseData instance.
void GetPixelValues(itk::Index< 3 > pixel, std::vector< float > &values)
ScanModeNative & GetScanMode()
virtual void GetNextRawImage(std::vector< mitk::Image::Pointer > &) override
Create an Photoacoustic B-Mode (Brightness-Mode) image from raw "RF" data. The RF's envelope is calcu...
bool m_CompensateForScatteringNext
int m_ScatteringCoefficient
ImageReadAccessor class to get locked read access for a particular image part.
USDiPhASImageSource(mitk::USDiPhASDevice *device)
std::vector< mitk::Image::Pointer > m_RecordedImages
Create an ultrasound B-Mode (Brightness-Mode) image from raw "RF" data. The RF's envelope is calculat...
bool m_VerticalSpacingModified
bool m_UseBModeFilterNext
bool m_CompensateForScatteringModified
mitk::Image::Pointer ApplyBmodeFilter(mitk::Image::Pointer image, bool useLogFilter=false)
void SetDataType(DataType dataT)
void OrderImagesInterleaved(Image::Pointer PAImage, Image::Pointer USImage, std::vector< Image::Pointer > recordedList, bool raw)
unsigned int m_ImageDimensions[3]
void ModifyUseBModeFilter(bool isSet)