diff --git a/CMake/BuildConfigurations/camiPhotoacousticsSetup.cmake b/CMake/BuildConfigurations/camiPhotoacousticsSetup.cmake index 3f745c3d34..4a881e5fb6 100644 --- a/CMake/BuildConfigurations/camiPhotoacousticsSetup.cmake +++ b/CMake/BuildConfigurations/camiPhotoacousticsSetup.cmake @@ -1,25 +1,25 @@ message(STATUS "Configuring MITK Photoacoustics Setup Build") # Enable open cv and open igt link, which is a necessary configuration set(MITK_USE_OpenCV ON CACHE BOOL "MITK Use OpenCV Library" FORCE) set(MITK_USE_OpenIGTLink ON CACHE BOOL "MITK Use OpenIGTLink Library" FORCE) set(MITK_USE_US_DiPhAS_SDK ON CACHE BOOL "Use DiPhAS SDK" FORCE) set(MITK_US_DiPhAS_SDK_PATH "C:/Users/dkfz/Source/Repos/UltrasoundResearchPlatform_SDK/UltrasoundResearchPlatformSDK_Cpp/x64" CACHE PATH "DiPhAS SDK Path") set(MITK_USE_OPHIR_PYRO_HARDWARE ON CACHE BOOL "Use the Ophir sensor build-in in OPOTEK Phocus Mobile" FORCE) set(MITK_OPHIR_API_PATH "C:/OphirCppWrapper" CACHE PATH "Ophir API Path") -set(MITK_USE_OPOTEK_HARDWARE ON CACHE BOOL "Use hardware build-in in OPOTEK Phocus Mobile" FORCE) -set(MITK_GALIL_API_PATH "C:/OphirCppWrapper" CACHE PATH "Galil API Path") +set(MITK_USE_GALIL_HARDWARE ON CACHE BOOL "Use hardware build-in in OPOTEK Phocus Mobile" FORCE) +set(MITK_GALIL_API_PATH "C:/Program Files (x86)/Galil/gclib" CACHE PATH "Galil API Path") # Enable default plugins and the navigation modules set(MITK_CONFIG_PLUGINS org.mitk.gui.qt.datamanager org.mitk.gui.qt.stdmultiwidgeteditor org.mitk.gui.qt.imagenavigator org.mitk.gui.qt.properties org.mitk.gui.qt.viewnavigator org.mitk.gui.qt.ultrasound org.mitk.gui.qt.lasercontrol ) diff --git a/CMake/FindOpenCL.cmake b/CMake/FindOpenCL.cmake index e30fb7a484..d960d45acf 100644 --- a/CMake/FindOpenCL.cmake +++ b/CMake/FindOpenCL.cmake @@ -1,89 +1,89 @@ # - Try to find OpenCL # This module tries to find an OpenCL implementation on your system. It supports # AMD / ATI, Apple and NVIDIA implementations, but should work, too. # # To set manually the paths, define these environment variables: # OpenCL_INCPATH - Include path (e.g. OpenCL_INCPATH=/opt/cuda/4.0/cuda/include) # OpenCL_LIBPATH - Library path (e.h. OpenCL_LIBPATH=/usr/lib64/nvidia) # # Once done this will define # OPENCL_FOUND - system has OpenCL # OPENCL_INCLUDE_DIRS - the OpenCL include directory # OPENCL_LIBRARIES - link these to use OpenCL # # WIN32 should work, but is untested FIND_PACKAGE(PackageHandleStandardArgs) SET (OPENCL_VERSION_STRING "0.1.0") SET(OPENCL_VERSION_MAJOR 0) SET(OPENCL_VERSION_MINOR 1) SET(OPENCL_VERSION_PATCH 0) IF(APPLE) FIND_LIBRARY(OPENCL_LIBRARIES OpenCL DOC "OpenCL lib for OSX") FIND_PATH(OPENCL_INCLUDE_DIRS OpenCL/cl.h DOC "Include for OpenCL on OSX") FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS OpenCL/cl.hpp DOC "Include for OpenCL CPP bindings on OSX") ELSE() IF (WIN32) FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h) FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp) IF(CMAKE_SIZEOF_VOID_P MATCHES "8") SET(OPENCL_LIB_DIR "$ENV{ATISTREAMSDKROOT}/lib/x86_64") if(NOT IS_DIRECTORY ${OPENCL_LIB_DIR}) SET(OPENCL_LIB_DIR "$ENV{CUDA_PATH}/lib/x64") endif() ELSE() SET(OPENCL_LIB_DIR "$ENV{ATISTREAMSDKROOT}/lib/x86") if(NOT IS_DIRECTORY ${OPENCL_LIB_DIR}) # need to convert path in the cmake style ? SET(OPENCL_LIB_DIR "$ENV{CUDA_PATH}/lib/Win32") endif() ENDIF() file(TO_CMAKE_PATH ${OPENCL_LIB_DIR} OPENCL_LIB_DIR) GET_FILENAME_COMPONENT(OPENCL_LIB_DIR ${OPENCL_LIB_DIR} ABSOLUTE) FIND_LIBRARY(OPENCL_LIBRARIES OpenCL.lib PATHS ${OPENCL_LIB_DIR} ENV OpenCL_LIBPATH) GET_FILENAME_COMPONENT(_OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE) # On Win32 search relative to the library FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS "${_OPENCL_INC_CAND}" ENV OpenCL_INCPATH) FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS "${_OPENCL_INC_CAND}" ENV OpenCL_INCPATH) - ELSE (WIN32) + ELSE () # Unix style platforms FIND_LIBRARY(OPENCL_LIBRARIES OpenCL PATHS ENV LD_LIBRARY_PATH ENV OpenCL_LIBPATH ) GET_FILENAME_COMPONENT(OPENCL_LIB_DIR ${OPENCL_LIBRARIES} PATH) GET_FILENAME_COMPONENT(_OPENCL_INC_CAND ${OPENCL_LIB_DIR}/../../include ABSOLUTE) # The AMD SDK currently does not place its headers # in /usr/include, therefore also search relative # to the library FIND_PATH(OPENCL_INCLUDE_DIRS CL/cl.h PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH) FIND_PATH(_OPENCL_CPP_INCLUDE_DIRS CL/cl.hpp PATHS ${_OPENCL_INC_CAND} "/usr/local/cuda/include" "/opt/AMDAPP/include" ENV OpenCL_INCPATH) - ENDIF (WIN32) + ENDIF () -ENDIF (APPLE) +ENDIF () FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenCL DEFAULT_MSG OPENCL_LIBRARIES OPENCL_INCLUDE_DIRS) IF(_OPENCL_CPP_INCLUDE_DIRS) SET( OPENCL_HAS_CPP_BINDINGS TRUE ) LIST( APPEND OPENCL_INCLUDE_DIRS ${_OPENCL_CPP_INCLUDE_DIRS} ) # This is often the same, so clean up LIST( REMOVE_DUPLICATES OPENCL_INCLUDE_DIRS ) -ENDIF(_OPENCL_CPP_INCLUDE_DIRS) +ENDIF() MARK_AS_ADVANCED( OPENCL_INCLUDE_DIRS ) diff --git a/Modules/Core/src/IO/mitkItkImageIO.cpp b/Modules/Core/src/IO/mitkItkImageIO.cpp index f20c45ea28..f2b7970f61 100644 --- a/Modules/Core/src/IO/mitkItkImageIO.cpp +++ b/Modules/Core/src/IO/mitkItkImageIO.cpp @@ -1,671 +1,671 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkItkImageIO.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mitk { const char *const PROPERTY_NAME_TIMEGEOMETRY_TYPE = "org.mitk.timegeometry.type"; const char *const PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS = "org.mitk.timegeometry.timepoints"; const char *const PROPERTY_KEY_TIMEGEOMETRY_TYPE = "org_mitk_timegeometry_type"; const char *const PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS = "org_mitk_timegeometry_timepoints"; ItkImageIO::ItkImageIO(const ItkImageIO &other) : AbstractFileIO(other), m_ImageIO(dynamic_cast(other.m_ImageIO->Clone().GetPointer())) { this->InitializeDefaultMetaDataKeys(); } std::vector ItkImageIO::FixUpImageIOExtensions(const std::string &imageIOName) { std::vector extensions; // Try to fix-up some known ITK image IO classes if (imageIOName == "GiplImageIO") { extensions.push_back("gipl"); extensions.push_back("gipl.gz"); } else if (imageIOName == "GDCMImageIO") { extensions.push_back("gdcm"); extensions.push_back("dcm"); extensions.push_back("DCM"); extensions.push_back("dc3"); extensions.push_back("DC3"); extensions.push_back("ima"); extensions.push_back("img"); } else if (imageIOName == "PNGImageIO") { extensions.push_back("png"); extensions.push_back("PNG"); } else if (imageIOName == "StimulateImageIO") { extensions.push_back("spr"); } else if (imageIOName == "HDF5ImageIO") { extensions.push_back("hdf"); extensions.push_back("h4"); extensions.push_back("hdf4"); extensions.push_back("h5"); extensions.push_back("hdf5"); extensions.push_back("he4"); extensions.push_back("he5"); extensions.push_back("hd5"); } else if (imageIOName == "GE4ImageIO" || imageIOName == "GE5ImageIO") { extensions.push_back(""); } if (!extensions.empty()) { MITK_DEBUG << "Fixing up known extensions for " << imageIOName; } return extensions; } ItkImageIO::ItkImageIO(itk::ImageIOBase::Pointer imageIO) : AbstractFileIO(Image::GetStaticNameOfClass()), m_ImageIO(imageIO) { if (m_ImageIO.IsNull()) { mitkThrow() << "ITK ImageIOBase argument must not be nullptr"; } this->AbstractFileReader::SetMimeTypePrefix(IOMimeTypes::DEFAULT_BASE_NAME() + ".image."); this->InitializeDefaultMetaDataKeys(); std::vector readExtensions = m_ImageIO->GetSupportedReadExtensions(); if (readExtensions.empty()) { std::string imageIOName = m_ImageIO->GetNameOfClass(); MITK_DEBUG << "ITK ImageIOBase " << imageIOName << " does not provide read extensions"; readExtensions = FixUpImageIOExtensions(imageIOName); } CustomMimeType customReaderMimeType; customReaderMimeType.SetCategory("Images"); for (std::vector::const_iterator iter = readExtensions.begin(), endIter = readExtensions.end(); iter != endIter; ++iter) { std::string extension = *iter; if (!extension.empty() && extension[0] == '.') { extension.assign(iter->begin() + 1, iter->end()); } customReaderMimeType.AddExtension(extension); } this->AbstractFileReader::SetMimeType(customReaderMimeType); std::vector writeExtensions = imageIO->GetSupportedWriteExtensions(); if (writeExtensions.empty()) { std::string imageIOName = imageIO->GetNameOfClass(); MITK_DEBUG << "ITK ImageIOBase " << imageIOName << " does not provide write extensions"; writeExtensions = FixUpImageIOExtensions(imageIOName); } if (writeExtensions != readExtensions) { CustomMimeType customWriterMimeType; customWriterMimeType.SetCategory("Images"); for (std::vector::const_iterator iter = writeExtensions.begin(), endIter = writeExtensions.end(); iter != endIter; ++iter) { std::string extension = *iter; if (!extension.empty() && extension[0] == '.') { extension.assign(iter->begin() + 1, iter->end()); } customWriterMimeType.AddExtension(extension); } this->AbstractFileWriter::SetMimeType(customWriterMimeType); } std::string description = std::string("ITK ") + imageIO->GetNameOfClass(); this->SetReaderDescription(description); this->SetWriterDescription(description); this->RegisterService(); } ItkImageIO::ItkImageIO(const CustomMimeType &mimeType, itk::ImageIOBase::Pointer imageIO, int rank) : AbstractFileIO(Image::GetStaticNameOfClass(), mimeType, std::string("ITK ") + imageIO->GetNameOfClass()), m_ImageIO(imageIO) { if (m_ImageIO.IsNull()) { mitkThrow() << "ITK ImageIOBase argument must not be nullptr"; } this->AbstractFileReader::SetMimeTypePrefix(IOMimeTypes::DEFAULT_BASE_NAME() + ".image."); this->InitializeDefaultMetaDataKeys(); if (rank) { this->AbstractFileReader::SetRanking(rank); this->AbstractFileWriter::SetRanking(rank); } this->RegisterService(); } /**Helper function that converts the content of a meta data into a time point vector. * If MetaData is not valid or cannot be converted an empty vector is returned.*/ std::vector ConvertMetaDataObjectToTimePointList(const itk::MetaDataObjectBase *data) { const itk::MetaDataObject *timeGeometryTimeData = dynamic_cast *>(data); std::vector result; if (timeGeometryTimeData) { std::string dataStr = timeGeometryTimeData->GetMetaDataObjectValue(); std::stringstream stream(dataStr); TimePointType tp; while (stream >> tp) { result.push_back(tp); } } return result; }; std::vector ItkImageIO::Read() { std::vector result; mitk::LocaleSwitch localeSwitch("C"); Image::Pointer image = Image::New(); const unsigned int MINDIM = 2; const unsigned int MAXDIM = 4; const std::string path = this->GetLocalFileName(); MITK_INFO << "loading " << path << " via itk::ImageIOFactory... " << std::endl; // Check to see if we can read the file given the name or prefix if (path.empty()) { mitkThrow() << "Empty filename in mitk::ItkImageIO "; } // Got to allocate space for the image. Determine the characteristics of // the image. m_ImageIO->SetFileName(path); m_ImageIO->ReadImageInformation(); unsigned int ndim = m_ImageIO->GetNumberOfDimensions(); if (ndim < MINDIM || ndim > MAXDIM) { MITK_WARN << "Sorry, only dimensions 2, 3 and 4 are supported. The given file has " << ndim << " dimensions! Reading as 4D."; ndim = MAXDIM; } itk::ImageIORegion ioRegion(ndim); itk::ImageIORegion::SizeType ioSize = ioRegion.GetSize(); itk::ImageIORegion::IndexType ioStart = ioRegion.GetIndex(); unsigned int dimensions[MAXDIM]; dimensions[0] = 0; dimensions[1] = 0; dimensions[2] = 0; dimensions[3] = 0; ScalarType spacing[MAXDIM]; spacing[0] = 1.0f; spacing[1] = 1.0f; spacing[2] = 1.0f; spacing[3] = 1.0f; Point3D origin; origin.Fill(0); unsigned int i; for (i = 0; i < ndim; ++i) { ioStart[i] = 0; ioSize[i] = m_ImageIO->GetDimensions(i); if (i < MAXDIM) { dimensions[i] = m_ImageIO->GetDimensions(i); spacing[i] = m_ImageIO->GetSpacing(i); if (spacing[i] <= 0) spacing[i] = 1.0f; } if (i < 3) { origin[i] = m_ImageIO->GetOrigin(i); } } ioRegion.SetSize(ioSize); ioRegion.SetIndex(ioStart); MITK_INFO << "ioRegion: " << ioRegion << std::endl; m_ImageIO->SetIORegion(ioRegion); void *buffer = new unsigned char[m_ImageIO->GetImageSizeInBytes()]; m_ImageIO->Read(buffer); image->Initialize(MakePixelType(m_ImageIO), ndim, dimensions); image->SetImportChannel(buffer, 0, Image::ManageMemory); const itk::MetaDataDictionary &dictionary = m_ImageIO->GetMetaDataDictionary(); // access direction of itk::Image and include spacing mitk::Matrix3D matrix; matrix.SetIdentity(); unsigned int j, itkDimMax3 = (ndim >= 3 ? 3 : ndim); for (i = 0; i < itkDimMax3; ++i) for (j = 0; j < itkDimMax3; ++j) matrix[i][j] = m_ImageIO->GetDirection(j)[i]; // re-initialize PlaneGeometry with origin and direction PlaneGeometry *planeGeometry = image->GetSlicedGeometry(0)->GetPlaneGeometry(0); planeGeometry->SetOrigin(origin); planeGeometry->GetIndexToWorldTransform()->SetMatrix(matrix); // re-initialize SlicedGeometry3D SlicedGeometry3D *slicedGeometry = image->GetSlicedGeometry(0); slicedGeometry->InitializeEvenlySpaced(planeGeometry, image->GetDimension(2)); slicedGeometry->SetSpacing(spacing); MITK_INFO << slicedGeometry->GetCornerPoint(false, false, false); MITK_INFO << slicedGeometry->GetCornerPoint(true, true, true); // re-initialize TimeGeometry TimeGeometry::Pointer timeGeometry; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE) || dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TYPE)) { // also check for the name because of backwards compatibility. Past code version stored with the name and not with // the key itk::MetaDataObject::ConstPointer timeGeometryTypeData = nullptr; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TYPE)) { timeGeometryTypeData = dynamic_cast *>(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TYPE)); } else { timeGeometryTypeData = dynamic_cast *>(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TYPE)); } if (timeGeometryTypeData->GetMetaDataObjectValue() == ArbitraryTimeGeometry::GetStaticNameOfClass()) { MITK_INFO << "used time geometry: " << ArbitraryTimeGeometry::GetStaticNameOfClass() << std::endl; typedef std::vector TimePointVector; TimePointVector timePoints; if (dictionary.HasKey(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS)) { timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS)); } else if (dictionary.HasKey(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS)) { timePoints = ConvertMetaDataObjectToTimePointList(dictionary.Get(PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS)); } if (timePoints.size() - 1 != image->GetDimension(3)) { MITK_ERROR << "Stored timepoints (" << timePoints.size() - 1 << ") and size of image time dimension (" << image->GetDimension(3) << ") do not match. Switch to ProportionalTimeGeometry fallback" << std::endl; } else { ArbitraryTimeGeometry::Pointer arbitraryTimeGeometry = ArbitraryTimeGeometry::New(); TimePointVector::const_iterator pos = timePoints.begin(); TimePointVector::const_iterator prePos = pos++; for (; pos != timePoints.end(); ++prePos, ++pos) { arbitraryTimeGeometry->AppendNewTimeStepClone(slicedGeometry, *prePos, *pos); } timeGeometry = arbitraryTimeGeometry; } } } if (timeGeometry.IsNull()) { // Fallback. If no other valid time geometry has been created, create a ProportionalTimeGeometry MITK_INFO << "used time geometry: " << ProportionalTimeGeometry::GetStaticNameOfClass() << std::endl; ProportionalTimeGeometry::Pointer propTimeGeometry = ProportionalTimeGeometry::New(); propTimeGeometry->Initialize(slicedGeometry, image->GetDimension(3)); timeGeometry = propTimeGeometry; } image->SetTimeGeometry(timeGeometry); buffer = nullptr; MITK_INFO << "number of image components: " << image->GetPixelType().GetNumberOfComponents() << std::endl; for (itk::MetaDataDictionary::ConstIterator iter = dictionary.Begin(), iterEnd = dictionary.End(); iter != iterEnd; ++iter) { if (iter->second->GetMetaDataObjectTypeInfo() == typeid(std::string)) { const std::string &key = iter->first; std::string assumedPropertyName = key; std::replace(assumedPropertyName.begin(), assumedPropertyName.end(), '_', '.'); std::string mimeTypeName = GetMimeType()->GetName(); // Check if there is already a info for the key and our mime type. IPropertyPersistence::InfoResultType infoList = mitk::CoreServices::GetPropertyPersistence()->GetInfoByKey(key); auto predicate = [mimeTypeName](const PropertyPersistenceInfo::ConstPointer &x) { return x.IsNotNull() && x->GetMimeTypeName() == mimeTypeName; }; auto finding = std::find_if(infoList.begin(), infoList.end(), predicate); if (finding == infoList.end()) { auto predicateWild = [](const PropertyPersistenceInfo::ConstPointer &x) { return x.IsNotNull() && x->GetMimeTypeName() == PropertyPersistenceInfo::ANY_MIMETYPE_NAME(); }; finding = std::find_if(infoList.begin(), infoList.end(), predicateWild); } PropertyPersistenceInfo::ConstPointer info; if (finding != infoList.end()) { assumedPropertyName = (*finding)->GetName(); info = *finding; } else { // we have not found anything suitable so we generate our own info PropertyPersistenceInfo::Pointer newInfo = PropertyPersistenceInfo::New(); newInfo->SetNameAndKey(assumedPropertyName, key); newInfo->SetMimeTypeName(PropertyPersistenceInfo::ANY_MIMETYPE_NAME()); info = newInfo; } std::string value = dynamic_cast *>(iter->second.GetPointer())->GetMetaDataObjectValue(); mitk::BaseProperty::Pointer loadedProp = info->GetDeserializationFunction()(value); image->SetProperty(assumedPropertyName.c_str(), loadedProp); // Read properties should be persisted unless they are default properties // which are written anyway bool isDefaultKey(false); for (const auto &defaultKey : m_DefaultMetaDataKeys) { if (defaultKey.length() <= assumedPropertyName.length()) { // does the start match the default key if (assumedPropertyName.substr(0, defaultKey.length()).find(defaultKey) != std::string::npos) { isDefaultKey = true; break; } } } if (!isDefaultKey) { mitk::CoreServices::GetPropertyPersistence()->AddInfo(info); } } } MITK_INFO << "...finished!" << std::endl; result.push_back(image.GetPointer()); return result; } AbstractFileIO::ConfidenceLevel ItkImageIO::GetReaderConfidenceLevel() const { return m_ImageIO->CanReadFile(GetLocalFileName().c_str()) ? IFileReader::Supported : IFileReader::Unsupported; } void ItkImageIO::Write() { const mitk::Image *image = dynamic_cast(this->GetInput()); if (image == nullptr) { mitkThrow() << "Cannot write non-image data"; } // Switch the current locale to "C" LocaleSwitch localeSwitch("C"); // Clone the image geometry, because we might have to change it // for writing purposes BaseGeometry::Pointer geometry = image->GetGeometry()->Clone(); // Check if geometry information will be lost if (image->GetDimension() == 2 && !geometry->Is2DConvertable()) { MITK_WARN << "Saving a 2D image with 3D geometry information. Geometry information will be lost! You might " "consider using Convert2Dto3DImageFilter before saving."; // set matrix to identity mitk::AffineTransform3D::Pointer affTrans = mitk::AffineTransform3D::New(); affTrans->SetIdentity(); mitk::Vector3D spacing = geometry->GetSpacing(); mitk::Point3D origin = geometry->GetOrigin(); geometry->SetIndexToWorldTransform(affTrans); geometry->SetSpacing(spacing); geometry->SetOrigin(origin); } LocalFile localFile(this); const std::string path = localFile.GetFileName(); MITK_INFO << "Writing image: " << path << std::endl; try { // Implementation of writer using itkImageIO directly. This skips the use // of templated itkImageFileWriter, which saves the multiplexing on MITK side. const unsigned int dimension = image->GetDimension(); const unsigned int *const dimensions = image->GetDimensions(); const mitk::PixelType pixelType = image->GetPixelType(); const mitk::Vector3D mitkSpacing = geometry->GetSpacing(); const mitk::Point3D mitkOrigin = geometry->GetOrigin(); // Due to templating in itk, we are forced to save a 4D spacing and 4D Origin, // though they are not supported in MITK itk::Vector spacing4D; spacing4D[0] = mitkSpacing[0]; spacing4D[1] = mitkSpacing[1]; spacing4D[2] = mitkSpacing[2]; spacing4D[3] = 1; // There is no support for a 4D spacing. However, we should have a valid value here itk::Vector origin4D; origin4D[0] = mitkOrigin[0]; origin4D[1] = mitkOrigin[1]; origin4D[2] = mitkOrigin[2]; origin4D[3] = 0; // There is no support for a 4D origin. However, we should have a valid value here // Set the necessary information for imageIO m_ImageIO->SetNumberOfDimensions(dimension); m_ImageIO->SetPixelType(pixelType.GetPixelType()); m_ImageIO->SetComponentType(pixelType.GetComponentType() < PixelComponentUserType ? static_cast(pixelType.GetComponentType()) : itk::ImageIOBase::UNKNOWNCOMPONENTTYPE); m_ImageIO->SetNumberOfComponents(pixelType.GetNumberOfComponents()); itk::ImageIORegion ioRegion(dimension); for (unsigned int i = 0; i < dimension; i++) { m_ImageIO->SetDimensions(i, dimensions[i]); m_ImageIO->SetSpacing(i, spacing4D[i]); m_ImageIO->SetOrigin(i, origin4D[i]); mitk::Vector3D mitkDirection; mitkDirection.SetVnlVector(geometry->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(i)); itk::Vector direction4D; direction4D[0] = mitkDirection[0]; direction4D[1] = mitkDirection[1]; direction4D[2] = mitkDirection[2]; // MITK only supports a 3x3 direction matrix. Due to templating in itk, however, we must // save a 4x4 matrix for 4D images. in this case, add an homogneous component to the matrix. if (i == 3) { direction4D[3] = 1; // homogenous component } else { direction4D[3] = 0; } vnl_vector axisDirection(dimension); for (unsigned int j = 0; j < dimension; j++) { axisDirection[j] = direction4D[j] / spacing4D[i]; } m_ImageIO->SetDirection(i, axisDirection); ioRegion.SetSize(i, image->GetLargestPossibleRegion().GetSize(i)); ioRegion.SetIndex(i, image->GetLargestPossibleRegion().GetIndex(i)); } - // use compression if available - m_ImageIO->UseCompressionOn(); + // dont use compression because it takes rediculusly long + m_ImageIO->UseCompressionOff(); m_ImageIO->SetIORegion(ioRegion); m_ImageIO->SetFileName(path); // Handle time geometry const ArbitraryTimeGeometry *arbitraryTG = dynamic_cast(image->GetTimeGeometry()); if (arbitraryTG) { itk::EncapsulateMetaData(m_ImageIO->GetMetaDataDictionary(), PROPERTY_KEY_TIMEGEOMETRY_TYPE, ArbitraryTimeGeometry::GetStaticNameOfClass()); std::stringstream stream; stream << arbitraryTG->GetTimeBounds(0)[0]; for (TimeStepType pos = 0; pos < arbitraryTG->CountTimeSteps(); ++pos) { stream << " " << arbitraryTG->GetTimeBounds(pos)[1]; } std::string data = stream.str(); itk::EncapsulateMetaData( m_ImageIO->GetMetaDataDictionary(), PROPERTY_KEY_TIMEGEOMETRY_TIMEPOINTS, data); } // Handle properties mitk::PropertyList::Pointer imagePropertyList = image->GetPropertyList(); for (const auto &property : *imagePropertyList->GetMap()) { IPropertyPersistence::InfoResultType infoList = mitk::CoreServices::GetPropertyPersistence()->GetInfo(property.first, GetMimeType()->GetName(), true); if (infoList.empty()) { continue; } std::string value = infoList.front()->GetSerializationFunction()(property.second); if (value == mitk::BaseProperty::VALUE_CANNOT_BE_CONVERTED_TO_STRING) { continue; } std::string key = infoList.front()->GetKey(); itk::EncapsulateMetaData(m_ImageIO->GetMetaDataDictionary(), key, value); } ImageReadAccessor imageAccess(image); m_ImageIO->Write(imageAccess.GetData()); } catch (const std::exception &e) { mitkThrow() << e.what(); } } AbstractFileIO::ConfidenceLevel ItkImageIO::GetWriterConfidenceLevel() const { // Check if the image dimension is supported const Image *image = dynamic_cast(this->GetInput()); if (image == nullptr) { // We cannot write a null object, DUH! return IFileWriter::Unsupported; } if (!m_ImageIO->SupportsDimension(image->GetDimension())) { // okay, dimension is not supported. We have to look at a special case: // 3D-Image with one slice. We can treat that as a 2D image. if ((image->GetDimension() == 3) && (image->GetSlicedGeometry()->GetSlices() == 1)) return IFileWriter::Supported; else return IFileWriter::Unsupported; } // Check if geometry information will be lost if (image->GetDimension() == 2 && !image->GetGeometry()->Is2DConvertable()) { return IFileWriter::PartiallySupported; } return IFileWriter::Supported; } ItkImageIO *ItkImageIO::IOClone() const { return new ItkImageIO(*this); } void ItkImageIO::InitializeDefaultMetaDataKeys() { this->m_DefaultMetaDataKeys.push_back("NRRD.space"); this->m_DefaultMetaDataKeys.push_back("NRRD.kinds"); this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TYPE); this->m_DefaultMetaDataKeys.push_back(PROPERTY_NAME_TIMEGEOMETRY_TIMEPOINTS); this->m_DefaultMetaDataKeys.push_back("ITK.InputFilterName"); } } diff --git a/Modules/OpenCL/mitkOclFilter.cpp b/Modules/OpenCL/mitkOclFilter.cpp index 5312e59117..cdf84d053f 100644 --- a/Modules/OpenCL/mitkOclFilter.cpp +++ b/Modules/OpenCL/mitkOclFilter.cpp @@ -1,248 +1,248 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //Ocl #include "mitkOclFilter.h" #include "mitkOclUtils.h" #include "mitkOpenCLActivator.h" //Mitk #include #include //usService #include "usServiceReference.h" #include #include #include #include #include #include mitk::OclFilter::OclFilter() : m_ClCompilerFlags(""), m_ClProgram(nullptr), m_CommandQue(nullptr), m_FilterID("mitkOclFilter"), m_Preambel(" "), m_Initialized(false) { } mitk::OclFilter::OclFilter(const char* filename) : m_ClCompilerFlags(""), m_ClProgram(nullptr), m_CommandQue(nullptr), m_FilterID(filename), m_Preambel(" "), m_Initialized(false) { m_ClFiles.push_back(filename); } mitk::OclFilter::~OclFilter() { MITK_DEBUG << "OclFilter Destructor"; // release program if (m_ClProgram) { us::ServiceReference ref = GetModuleContext()->GetServiceReference(); OclResourceService* resources = GetModuleContext()->GetService(ref); // remove program from storage resources->RemoveProgram(m_FilterID); } } bool mitk::OclFilter::ExecuteKernel( cl_kernel kernel, unsigned int workSizeDim ) { cl_int clErr = 0; clErr = clEnqueueNDRangeKernel( this->m_CommandQue, kernel, workSizeDim, nullptr, this->m_GlobalWorkSize, m_LocalWorkSize, 0, nullptr, nullptr); CHECK_OCL_ERR( clErr ); return ( clErr == CL_SUCCESS ); } bool mitk::OclFilter::Initialize() { us::ServiceReference ref = GetModuleContext()->GetServiceReference(); OclResourceService* resources = GetModuleContext()->GetService(ref); m_CommandQue = resources->GetCommandQueue(); cl_int clErr = 0; m_Initialized = CHECK_OCL_ERR(clErr); if ( m_ClFiles.empty()) { MITK_ERROR<<"No OpenCL Source FILE specified"; return false; } if (m_ClProgram == nullptr) { try { this->m_ClProgram = resources->GetProgram( this->m_FilterID ); } catch(const mitk::Exception& e) { - MITK_INFO << "Program not stored in resource manager, compiling."; + MITK_INFO << "Program not stored in resource manager, compiling. " << e; this->CompileSource(); } } return m_Initialized; } void mitk::OclFilter::LoadSourceFiles(CStringList &sourceCode, ClSizeList &sourceCodeSize) { for( CStringList::iterator it = m_ClFiles.begin(); it != m_ClFiles.end(); ++it ) { MITK_DEBUG << "Load file :" << *it; us::ModuleResource mdr = GetModule()->GetResource(*it); if( !mdr.IsValid() ) MITK_WARN << "Could not load resource: " << mdr.GetName() << " is invalid!"; us::ModuleResourceStream rss(mdr); // read resource file to a string std::istreambuf_iterator eos; std::string source(std::istreambuf_iterator(rss), eos); // add preambel and build up string to compile std::string src(m_Preambel); src.append("\n"); src.append(source); // allocate new char buffer char* tmp = new char[src.size() + 1]; strcpy(tmp,src.c_str()); // add source to list sourceCode.push_back((const char*)tmp); sourceCodeSize.push_back(src.size()); } } void mitk::OclFilter::CompileSource() { // helper variable int clErr = 0; CStringList sourceCode; ClSizeList sourceCodeSize; if (m_ClFiles.empty()) { MITK_ERROR("ocl.filter") << "No shader source file was set"; return; } //get a valid opencl context us::ServiceReference ref = GetModuleContext()->GetServiceReference(); OclResourceService* resources = GetModuleContext()->GetService(ref); cl_context gpuContext = resources->GetContext(); // load the program source from file LoadSourceFiles(sourceCode, sourceCodeSize); if ( !sourceCode.empty() ) { // create program from all files in the file list m_ClProgram = clCreateProgramWithSource(gpuContext, sourceCode.size(), &sourceCode[0], &sourceCodeSize[0], &clErr); CHECK_OCL_ERR(clErr); // build the source code MITK_DEBUG << "Building Program Source"; std::string compilerOptions = ""; compilerOptions.append(m_ClCompilerFlags); MITK_DEBUG("ocl.filter") << "cl compiler flags: " << compilerOptions.c_str(); clErr = clBuildProgram(m_ClProgram, 0, nullptr, compilerOptions.c_str(), nullptr, nullptr); CHECK_OCL_ERR(clErr); // if OpenCL Source build failed if (clErr != CL_SUCCESS) { MITK_ERROR("ocl.filter") << "Failed to build source"; oclLogBuildInfo(m_ClProgram, resources->GetCurrentDevice() ); oclLogBinary(m_ClProgram, resources->GetCurrentDevice() ); m_Initialized = false; } // store the succesfully build program into the program storage provided by the resource service resources->InsertProgram(m_ClProgram, m_FilterID, true); // free the char buffers with the source code for( CStringList::iterator it = sourceCode.begin(); it != sourceCode.end(); ++it ) { delete[] *it; } } else { MITK_ERROR("ocl.filter") << "Could not load from source"; m_Initialized = false; } } void mitk::OclFilter::SetWorkingSize(unsigned int locx, unsigned int dimx, unsigned int locy, unsigned int dimy, unsigned int locz, unsigned int dimz) { // set the local work size this->m_LocalWorkSize[0] = locx; this->m_LocalWorkSize[1] = locy; this->m_LocalWorkSize[2] = locz; this->m_GlobalWorkSize[0] = dimx; this->m_GlobalWorkSize[1] = dimy; this->m_GlobalWorkSize[2] = dimz; // estimate the global work size this->m_GlobalWorkSize[0] = iDivUp( dimx, this->m_LocalWorkSize[0]) * this->m_LocalWorkSize[0]; if ( dimy > 1) this->m_GlobalWorkSize[1] = iDivUp( dimy, this->m_LocalWorkSize[1]) * this->m_LocalWorkSize[1]; if( dimz > 1 ) this->m_GlobalWorkSize[2] = iDivUp( dimz, this->m_LocalWorkSize[2]) * this->m_LocalWorkSize[2]; } void mitk::OclFilter::SetSourcePreambel(const char* preambel) { this->m_Preambel = preambel; } void mitk::OclFilter::AddSourceFile(const char* filename) { m_ClFiles.push_back(filename); } void mitk::OclFilter::SetCompilerFlags(const char* flags) { m_ClCompilerFlags = flags; } bool mitk::OclFilter::IsInitialized() { return m_Initialized; } diff --git a/Modules/PhotoacousticsHardware/CMakeLists.txt b/Modules/PhotoacousticsHardware/CMakeLists.txt index fa90f023da..06bde63943 100644 --- a/Modules/PhotoacousticsHardware/CMakeLists.txt +++ b/Modules/PhotoacousticsHardware/CMakeLists.txt @@ -1,21 +1,21 @@ if(WIN32) option(MITK_USE_GALIL_HARDWARE "Enable support for OPOTEK Lasers" OFF) - option(MITK_USE_OPHIR_PRYO_HARDWARE "Enable support for Ophir Pyroelectrical Sensors" OFF) + option(MITK_USE_OPHIR_PYRO_HARDWARE "Enable support for Ophir Pyroelectrical Sensors" OFF) - if(MITK_USE_OPHIR_PRYO_HARDWARE) + if(MITK_USE_OPHIR_PYRO_HARDWARE) set(MITK_OPHIR_API_PATH "" CACHE PATH "Path to Ophir API lib.") endif() if(MITK_USE_GALIL_HARDWARE) set(MITK_GALIL_API_PATH "" CACHE PATH "Path to Galil API header files.") MITK_CREATE_MODULE( SUBPROJECTS DEPENDS MitkIGT INCLUDE_DIRS PUBLIC "${MITK_GALIL_API_PATH}/include" "${MITK_OPHIR_API_PATH}" INTERNAL_INCLUDE_DIRS ${INCLUDE_DIRS_INTERNAL} ADDITIONAL_LIBS "${MITK_GALIL_API_PATH}/lib/dynamic/x64/gclib.lib" "${MITK_GALIL_API_PATH}/lib/dynamic/x64/gclibo.lib" tinyxml "${MITK_OPHIR_API_PATH}/OphirPyroWrapper.lib" PACKAGE_DEPENDS tinyxml ) endif() endif() diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp index cba81bd664..ca179df5de 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.cpp @@ -1,894 +1,905 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // std dependencies #include #include #include // mitk dependencies #include "mitkUSDiPhASDevice.h" #include "mitkUSDiPhASImageSource.h" #include #include "mitkUSDiPhASBModeImageFilter.h" #include "ITKUltrasound/itkBModeImageFilter.h" #include "mitkImageCast.h" #include "mitkITKImageImport.h" // itk dependencies #include "itkImage.h" #include "itkResampleImageFilter.h" #include "itkCastImageFilter.h" #include "itkCropImageFilter.h" #include "itkRescaleIntensityImageFilter.h" #include "itkIntensityWindowingImageFilter.h" #include #include "itkMultiplyImageFilter.h" - mitk::USDiPhASImageSource::USDiPhASImageSource(mitk::USDiPhASDevice* device) : m_Device(device), m_StartTime(((float)std::clock()) / CLOCKS_PER_SEC), m_UseGUIOutPut(false), m_DataType(DataType::Image_uChar), m_GUIOutput(nullptr), m_UseBModeFilter(false), m_CurrentlyRecording(false), m_DataTypeModified(true), m_DataTypeNext(DataType::Image_uChar), m_CurrentImageTimestamp(0), m_PyroConnected(false), m_ImageTimestampBuffer(), m_VerticalSpacing(0), m_UseBModeFilterModified(false), m_UseBModeFilterNext(false), m_ScatteringCoefficientModified(false), m_CompensateForScatteringModified(false), m_VerticalSpacingModified(false), m_ScatteringCoefficient(15), m_CompensateForScattering(false), m_CompensateEnergy(false), m_CompensateEnergyNext(false), m_CompensateEnergyModified(false) { m_BufferSize = 100; m_ImageTimestampBuffer.insert(m_ImageTimestampBuffer.begin(), m_BufferSize, 0); m_LastWrittenImage = m_BufferSize - 1; m_ImageBuffer.insert(m_ImageBuffer.begin(), m_BufferSize, nullptr); us::ModuleResource resourceFile; std::string name; m_FluenceCompOriginal.insert(m_FluenceCompOriginal.begin(), 5, Image::New()); for (int i = 5; i <= 25; ++i) { name = "c:\\HomogeneousScatteringAssumptions\\Scattering" + std::to_string(i) + ".nrrd"; m_FluenceCompOriginal.push_back(mitk::IOUtil::LoadImage(name)); } m_FluenceCompResized.insert(m_FluenceCompResized.begin(), 26, Image::New()); m_FluenceCompResizedItk.insert(m_FluenceCompResizedItk.begin(), 26, itk::Image::New()); } mitk::USDiPhASImageSource::~USDiPhASImageSource() { // close the pyro MITK_INFO("Pyro Debug") << "StopDataAcquisition: " << m_Pyro->StopDataAcquisition(); MITK_INFO("Pyro Debug") << "CloseConnection: " << m_Pyro->CloseConnection(); m_PyroConnected = false; m_Pyro = nullptr; } void mitk::USDiPhASImageSource::GetNextRawImage( mitk::Image::Pointer& image) { // modify all settings that have been changed here, so we don't get multithreading issues if (m_DataTypeModified) { SetDataType(m_DataTypeNext); m_DataTypeModified = false; UpdateImageGeometry(); } if (m_UseBModeFilterModified) { SetUseBModeFilter(m_UseBModeFilterNext); m_UseBModeFilterModified = false; } if (m_VerticalSpacingModified) { m_VerticalSpacing = m_VerticalSpacingNext; m_VerticalSpacingModified = false; } if (m_ScatteringCoefficientModified) { m_ScatteringCoefficient = m_ScatteringCoefficientNext; m_ScatteringCoefficientModified = false; } if (m_CompensateForScatteringModified) { m_CompensateForScattering = m_CompensateForScatteringNext; m_CompensateForScatteringModified = false; } if (m_CompensateEnergyModified) { m_CompensateEnergy = m_CompensateEnergyNext; m_CompensateEnergyModified = false; } // make sure image is nullptr image = nullptr; float ImageEnergyValue = 0; for (int i = 100; i > 90 && ImageEnergyValue <= 0; --i) { if (m_ImageTimestampBuffer[(m_LastWrittenImage + i) % 100] != 0) { ImageEnergyValue = m_Pyro->GetClosestEnergyInmJ(m_ImageTimestampBuffer[(m_LastWrittenImage + i) % 100]); if (ImageEnergyValue > 0) { image = &(*m_ImageBuffer[(m_LastWrittenImage + i) % 100]); } } } // if we did not get any usable Energy value, compensate using this default value if (image == nullptr) { image = &(*m_ImageBuffer[m_LastWrittenImage]); ImageEnergyValue = 40; if (image == nullptr) return; } // do image processing before displaying it if (image.IsNotNull()) { - typedef itk::Image< float, 3 > itkFloatImageType; itkFloatImageType::Pointer itkImage; mitk::CastToItkImage(image, itkImage); image = mitk::GrabItkImageMemory(itkImage); //thereby using float images + image = CutOffTop(image, 165); // now apply filters to the image, if the options have been selected. if ((m_CompensateForScattering || m_UseBModeFilter) && m_DataType == DataType::Beamformed_Short) { if (m_Device->GetScanMode().beamformingAlgorithm == Beamforming::PlaneWaveCompound) // this is for ultrasound only mode { if (m_UseBModeFilter) { image = ApplyBmodeFilter(image, true); if (m_VerticalSpacing) image = ResampleOutputVertical(image, m_VerticalSpacing); } } else { Image::Pointer imagePA = Image::New(); unsigned int dim[] = { image->GetDimension(0),image->GetDimension(1),1}; imagePA->Initialize(image->GetPixelType(), 3, dim); imagePA->SetGeometry(image->GetGeometry()); Image::Pointer imageUS = Image::New(); imageUS->Initialize(image->GetPixelType(), 3, dim); imageUS->SetGeometry(image->GetGeometry()); ImageReadAccessor inputReadAccessorCopyPA(image, image->GetSliceData(0)); imagePA->SetSlice(inputReadAccessorCopyPA.GetData(), 0); ImageReadAccessor inputReadAccessorCopyUS(image, image->GetSliceData(1)); imageUS->SetSlice(inputReadAccessorCopyUS.GetData(), 0); // first, seperate the PA image from the USImages // then, we compensate the PAImage using our ImageEnergyValue if(m_CompensateEnergy) imagePA = MultiplyImage(imagePA, 1/ImageEnergyValue); // TODO: add the correct prefactor here!!!! // now we apply the BModeFilter if (m_UseBModeFilter) { imageUS = ApplyBmodeFilter(imageUS, true); // the US Images get a logarithmic filter imagePA = ApplyBmodeFilter(imagePA, false); } ImageReadAccessor inputReadAccessorPA(imagePA, imagePA->GetSliceData(0)); image->SetSlice(inputReadAccessorPA.GetData(), 0); ImageReadAccessor inputReadAccessorUS(imageUS, imageUS->GetSliceData(0)); image->SetSlice(inputReadAccessorUS.GetData(), 1); if (m_VerticalSpacing) { image = ResampleOutputVertical(image, m_VerticalSpacing); } // and finally the scattering corrections if (m_CompensateForScattering) { auto curResizeImage = m_FluenceCompResized.at(m_ScatteringCoefficient); // just for convenience // update the fluence reference images! bool doResampling = image->GetDimension(0) != curResizeImage->GetDimension(0) || image->GetDimension(1) != curResizeImage->GetDimension(1) || image->GetGeometry()->GetSpacing()[0] != curResizeImage->GetGeometry()->GetSpacing()[0] || image->GetGeometry()->GetSpacing()[1] != curResizeImage->GetGeometry()->GetSpacing()[1]; if (doResampling) { curResizeImage = ApplyResampling(m_FluenceCompOriginal.at(m_ScatteringCoefficient), image->GetGeometry()->GetSpacing(), image->GetDimensions()); double* rawOutputData = new double[image->GetDimension(0)*image->GetDimension(1)]; double* rawScatteringData = (double*)curResizeImage->GetData(); int sizeRawScatteringData = curResizeImage->GetDimension(0) * curResizeImage->GetDimension(1); int imageSize = image->GetDimension(0)*image->GetDimension(1); //everything above 1.5mm is still inside the transducer; therefore the fluence compensation image has to be positioned a little lower float upperCutoffmm = 1.5; int lowerBound = std::round(upperCutoffmm / image->GetGeometry()->GetSpacing()[1])*image->GetDimension(0); int upperBound = lowerBound + sizeRawScatteringData; for (int i = 0; i < lowerBound && i < imageSize; ++i) { rawOutputData[i] = 0; // everything than cannot be compensated shall be treated as garbage, here the upper 0.15mm } for (int i = lowerBound; i < upperBound && i < imageSize; ++i) { rawOutputData[i] = 1 / rawScatteringData[i-lowerBound]; } for (int i = upperBound; i < imageSize; ++i) { rawOutputData[i] = 0; // everything than cannot be compensated shall be treated as garbage } unsigned int dim[] = { image->GetDimension(0), image->GetDimension(1), 1 }; curResizeImage->Initialize(mitk::MakeScalarPixelType(), 3, dim); curResizeImage->SetGeometry(image->GetGeometry()); curResizeImage->SetSlice(rawOutputData,0); delete[] rawOutputData; mitk::CastToItkImage(curResizeImage, m_FluenceCompResizedItk.at(m_ScatteringCoefficient)); m_FluenceCompResized.at(m_ScatteringCoefficient) = mitk::GrabItkImageMemory(m_FluenceCompResizedItk.at(m_ScatteringCoefficient)); MITK_INFO << "Resized a fluence image."; } // actually apply the scattering compensation imagePA = ApplyScatteringCompensation(imagePA, m_ScatteringCoefficient); ImageReadAccessor inputReadAccessorPA(imagePA, imagePA->GetSliceData(0)); image->SetSlice(inputReadAccessorPA.GetData(), 0); } } } } } mitk::Image::Pointer mitk::USDiPhASImageSource::ApplyBmodeFilter(mitk::Image::Pointer image, bool useLogFilter) { // we use this seperate ApplyBmodeFilter Method for processing of two-dimensional images // the image needs to be of floating point type for the envelope filter to work; the casting is done automatically by the CastToItkImage - typedef itk::Image< float, 3 > itkFloatImageType; - + typedef itk::BModeImageFilter < itkFloatImageType, itkFloatImageType > BModeFilterType; BModeFilterType::Pointer bModeFilter = BModeFilterType::New(); // LogFilter typedef itk::PhotoacousticBModeImageFilter < itkFloatImageType, itkFloatImageType > PhotoacousticBModeImageFilter; PhotoacousticBModeImageFilter::Pointer photoacousticBModeFilter = PhotoacousticBModeImageFilter::New(); // No LogFilter itkFloatImageType::Pointer itkImage; - - mitk::CastToItkImage(image, itkImage); - itkFloatImageType::Pointer bmode; + mitk::CastToItkImage(image, itkImage); if (useLogFilter) { bModeFilter->SetInput(itkImage); bModeFilter->SetDirection(1); bmode = bModeFilter->GetOutput(); } else { photoacousticBModeFilter->SetInput(itkImage); photoacousticBModeFilter->SetDirection(1); bmode = photoacousticBModeFilter->GetOutput(); } return mitk::GrabItkImageMemory(bmode); } +mitk::Image::Pointer mitk::USDiPhASImageSource::CutOffTop(mitk::Image::Pointer image, int cutOffSize) +{ + typedef itk::CropImageFilter < itkFloatImageType, itkFloatImageType > CutImageFilter; + itkFloatImageType::SizeType cropSize; + itkFloatImageType::Pointer itkImage; + mitk::CastToItkImage(image, itkImage); + + cropSize[0] = 0; + if(itkImage->GetLargestPossibleRegion().GetSize()[1] == 2048) + cropSize[1] = cutOffSize; + else + cropSize[1] = 0; + cropSize[2] = 0; + CutImageFilter::Pointer cutOffFilter = CutImageFilter::New(); + cutOffFilter->SetInput(itkImage); + cutOffFilter->SetLowerBoundaryCropSize(cropSize); + cutOffFilter->UpdateLargestPossibleRegion(); + return mitk::GrabItkImageMemory(cutOffFilter->GetOutput()); +} + mitk::Image::Pointer mitk::USDiPhASImageSource::ResampleOutputVertical(mitk::Image::Pointer image, float verticalSpacing) { - typedef itk::Image< float, 3 > itkFloatImageType; typedef itk::ResampleImageFilter < itkFloatImageType, itkFloatImageType > ResampleImageFilter; ResampleImageFilter::Pointer resampleImageFilter = ResampleImageFilter::New(); itkFloatImageType::Pointer itkImage; mitk::CastToItkImage(image, itkImage); itkFloatImageType::SpacingType outputSpacing; itkFloatImageType::SizeType inputSize = itkImage->GetLargestPossibleRegion().GetSize(); itkFloatImageType::SizeType outputSize = inputSize; outputSpacing[0] = itkImage->GetSpacing()[0] * (static_cast(inputSize[0]) / static_cast(outputSize[0])); outputSpacing[1] = verticalSpacing; outputSpacing[2] = itkImage->GetSpacing()[2]; outputSize[1] = inputSize[1] * itkImage->GetSpacing()[1] / outputSpacing[1]; typedef itk::IdentityTransform TransformType; resampleImageFilter->SetInput(itkImage); resampleImageFilter->SetSize(outputSize); resampleImageFilter->SetOutputSpacing(outputSpacing); resampleImageFilter->SetTransform(TransformType::New()); resampleImageFilter->UpdateLargestPossibleRegion(); return mitk::GrabItkImageMemory(resampleImageFilter->GetOutput()); } mitk::Image::Pointer mitk::USDiPhASImageSource::ApplyScatteringCompensation(mitk::Image::Pointer inputImage, int scattering) { - typedef itk::Image< float, 3 > itkFloatImageType; typedef itk::MultiplyImageFilter MultiplyImageFilterType; itkFloatImageType::Pointer itkImage; mitk::CastToItkImage(inputImage, itkImage); MultiplyImageFilterType::Pointer multiplyFilter = MultiplyImageFilterType::New(); multiplyFilter->SetInput1(itkImage); multiplyFilter->SetInput2(m_FluenceCompResizedItk.at(m_ScatteringCoefficient)); return mitk::GrabItkImageMemory(multiplyFilter->GetOutput()); } mitk::Image::Pointer mitk::USDiPhASImageSource::ApplyResampling(mitk::Image::Pointer inputImage, mitk::Vector3D outputSpacing, unsigned int outputSize[3]) { - typedef itk::Image< double, 3 > itkFloatImageType; - typedef itk::ResampleImageFilter < itkFloatImageType, itkFloatImageType > ResampleImageFilter; ResampleImageFilter::Pointer resampleImageFilter = ResampleImageFilter::New(); itkFloatImageType::Pointer itkImage; mitk::CastToItkImage(inputImage, itkImage); itkFloatImageType::SpacingType outputSpacingItk; itkFloatImageType::SizeType inputSizeItk = itkImage->GetLargestPossibleRegion().GetSize(); itkFloatImageType::SizeType outputSizeItk = inputSizeItk; itkFloatImageType::SpacingType inputSpacing = itkImage->GetSpacing(); outputSizeItk[0] = outputSize[0]; outputSizeItk[1] = 10*(inputSpacing[1] * inputSizeItk[1]) / (outputSpacing[1]); outputSizeItk[2] = 1; outputSpacingItk[0] = 0.996 * inputSpacing[0] * (static_cast(inputSizeItk[0]) / static_cast(outputSizeItk[0])); // TODO: find out why the spacing is not correct, so we need that factor; ?!?! outputSpacingItk[1] = inputSpacing[1] * (static_cast(inputSizeItk[1]) / static_cast(outputSizeItk[1])); outputSpacingItk[2] = outputSpacing[2]; typedef itk::IdentityTransform TransformType; resampleImageFilter->SetInput(itkImage); resampleImageFilter->SetSize(outputSizeItk); resampleImageFilter->SetOutputSpacing(outputSpacingItk); resampleImageFilter->SetTransform(TransformType::New()); resampleImageFilter->UpdateLargestPossibleRegion(); return mitk::GrabItkImageMemory(resampleImageFilter->GetOutput()); } mitk::Image::Pointer mitk::USDiPhASImageSource::MultiplyImage(mitk::Image::Pointer inputImage, double value) { - typedef itk::Image< float, 3 > itkFloatImageType; typedef itk::MultiplyImageFilter MultiplyImageFilterType; itkFloatImageType::Pointer itkImage; mitk::CastToItkImage(inputImage, itkImage); MultiplyImageFilterType::Pointer multiplyFilter = MultiplyImageFilterType::New(); multiplyFilter->SetInput1(itkImage); multiplyFilter->SetConstant(value); return mitk::GrabItkImageMemory(multiplyFilter->GetOutput()); } void mitk::USDiPhASImageSource::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& imageBytesPerPixel, int& imageSetsTotal, double& timeStamp) { if (m_DataTypeModified) return; if (!m_PyroConnected) { m_Pyro = mitk::OphirPyro::New(); MITK_INFO << "[Pyro Debug] OpenConnection: " << m_Pyro->OpenConnection(); MITK_INFO << "[Pyro Debug] StartDataAcquisition: " << m_Pyro->StartDataAcquisition(); m_PyroConnected = true; } bool writeImage = ((m_DataType == DataType::Image_uChar) && (imageData != nullptr)) || ((m_DataType == DataType::Beamformed_Short) && (rfDataArrayBeamformed != nullptr)); if (writeImage) { //get the timestamp we might save later on m_CurrentImageTimestamp = std::chrono::high_resolution_clock::now().time_since_epoch().count(); // create a new image and initialize it mitk::Image::Pointer image = mitk::Image::New(); switch (m_DataType) { case DataType::Image_uChar: { m_ImageDimensions[0] = imageWidth; m_ImageDimensions[1] = imageHeight; m_ImageDimensions[2] = imageSetsTotal; image->Initialize(mitk::MakeScalarPixelType(), 3, m_ImageDimensions); break; } case DataType::Beamformed_Short: { m_ImageDimensions[0] = beamformedLines; m_ImageDimensions[1] = beamformedSamples; m_ImageDimensions[2] = beamformedTotalDatasets; image->Initialize(mitk::MakeScalarPixelType(), 3, m_ImageDimensions); break; } } image->GetGeometry()->SetSpacing(m_ImageSpacing); image->GetGeometry()->Modified(); // write the given buffer into the image switch (m_DataType) { case DataType::Image_uChar: { for (unsigned char i = 0; i < imageSetsTotal; i++) { image->SetSlice(&imageData[i*imageHeight*imageWidth], i); } break; } case DataType::Beamformed_Short: { short* flipme = new short[beamformedLines*beamformedSamples*beamformedTotalDatasets]; int pixelsPerImage = beamformedLines*beamformedSamples; for (unsigned char currentSet = 0; currentSet < beamformedTotalDatasets; currentSet++) { for (unsigned short sample = 0; sample < beamformedSamples; sample++) { for (unsigned short line = 0; line < beamformedLines; line++) { flipme[sample*beamformedLines + line + pixelsPerImage*currentSet] = rfDataArrayBeamformed[line*beamformedSamples + sample + pixelsPerImage*currentSet]; } } // the beamformed pa image is flipped by 90 degrees; we need to flip it manually } for (unsigned char i = 0; i < beamformedTotalDatasets; i++) { image->SetSlice(&flipme[i*beamformedLines*beamformedSamples], i); // set every image to a different slice } delete[] flipme; break; } } if (m_SavingSettings.saveRaw && m_CurrentlyRecording && rfDataChannelData != nullptr) { unsigned int dim[3]; dim[0] = channelDataChannelsPerDataset; dim[1] = channelDataSamplesPerChannel; dim[2] = 1; short offset = m_Device->GetScanMode().accumulation * 2048; short* noOffset = new short[channelDataChannelsPerDataset*channelDataSamplesPerChannel*channelDataTotalDatasets]; for (unsigned char set = 0; set < channelDataTotalDatasets; ++set) { for (unsigned short sam = 0; sam < channelDataSamplesPerChannel; ++sam) { for (unsigned short chan = 0; chan < channelDataChannelsPerDataset; ++chan) { noOffset[set*channelDataSamplesPerChannel*channelDataChannelsPerDataset + sam * channelDataChannelsPerDataset + chan] = rfDataChannelData[set*channelDataSamplesPerChannel*channelDataChannelsPerDataset + sam * channelDataChannelsPerDataset + chan] - offset; // this offset in the raw Images is given by the API... } } } // save the raw images when recording for (unsigned char i = 0; i < channelDataTotalDatasets; ++i) { mitk::Image::Pointer rawImage = mitk::Image::New(); rawImage->Initialize(mitk::MakeScalarPixelType(), 3, dim); rawImage->SetSlice(&noOffset[i*channelDataChannelsPerDataset*channelDataSamplesPerChannel]); float& recordTime = m_Device->GetScanMode().receivePhaseLengthSeconds; int& speedOfSound = m_Device->GetScanMode().averageSpeedOfSound; mitk::Vector3D rawSpacing; rawSpacing[0] = m_Device->GetScanMode().transducerPitchMeter * 1000; // save in mm rawSpacing[1] = recordTime / channelDataSamplesPerChannel / 2 * 1000000; // save in us rawSpacing[2] = 1; rawImage->GetGeometry()->SetSpacing(rawSpacing); rawImage->GetGeometry()->Modified(); m_RawRecordedImages.push_back(rawImage); } delete[] noOffset; } itk::Index<3> pixel = { { (itk::Index<3>::IndexValueType)(image->GetDimension(0) / 2), (itk::Index<3>::IndexValueType)(22.0/532.0*m_Device->GetScanMode().reconstructionSamplesPerLine), 0 } }; //22/532*2048 = 84 if (!m_Pyro->IsSyncDelaySet() &&(image->GetPixelValueByIndex(pixel) < -30)) // #MagicNumber { MITK_INFO << "Setting SyncDelay now"; m_Pyro->SetSyncDelay(m_CurrentImageTimestamp); } m_ImageTimestampBuffer[(m_LastWrittenImage + 1) % m_BufferSize] = m_CurrentImageTimestamp; m_ImageBuffer[(m_LastWrittenImage + 1) % m_BufferSize] = image; m_LastWrittenImage = (m_LastWrittenImage + 1) % m_BufferSize; // if the user decides to start recording, we feed the vector the generated images if (m_CurrentlyRecording) { for (unsigned char index = 0; index < image->GetDimension(2); ++index) { if (image->IsSliceSet(index)) { m_RecordedImages.push_back(Image::New()); unsigned int dim[] = { image ->GetDimension(0), image->GetDimension(1), 1}; m_RecordedImages.back()->Initialize(image->GetPixelType(), 3, dim); m_RecordedImages.back()->SetGeometry(image->GetGeometry()); mitk::ImageReadAccessor inputReadAccessor(image, image->GetSliceData(index)); m_RecordedImages.back()->SetSlice(inputReadAccessor.GetData(),0); } } m_ImageTimestampRecord.push_back(m_CurrentImageTimestamp); // save timestamps for each laser image! } } } void mitk::USDiPhASImageSource::UpdateImageGeometry() { MITK_INFO << "Retreaving Image Geometry Information for Spacing..."; float& recordTime = m_Device->GetScanMode().receivePhaseLengthSeconds; int& speedOfSound = m_Device->GetScanMode().averageSpeedOfSound; float& pitch = m_Device->GetScanMode().reconstructedLinePitchMmOrAngleDegree; int& reconstructionLines = m_Device->GetScanMode().reconstructionLines; switch (m_DataType) { case DataType::Image_uChar : { int& imageWidth = m_Device->GetScanMode().imageWidth; int& imageHeight = m_Device->GetScanMode().imageHeight; m_ImageSpacing[0] = pitch * reconstructionLines / imageWidth; m_ImageSpacing[1] = recordTime * speedOfSound / 2 * 1000 / imageHeight; break; } case DataType::Beamformed_Short : { int& imageWidth = reconstructionLines; int& imageHeight = m_Device->GetScanMode().reconstructionSamplesPerLine; m_ImageSpacing[0] = pitch; m_ImageSpacing[1] = recordTime * speedOfSound / 2 * 1000 / imageHeight; break; } } m_ImageSpacing[2] = 1; MITK_INFO << "Retreaving Image Geometry Information for Spacing " << m_ImageSpacing[0] << " ... " << m_ImageSpacing[1] << " ... " << m_ImageSpacing[2] << " ...[DONE]"; } void mitk::USDiPhASImageSource::ModifyDataType(DataType dataT) { m_DataTypeModified = true; m_DataTypeNext = dataT; } void mitk::USDiPhASImageSource::ModifyUseBModeFilter(bool isSet) { m_UseBModeFilterModified = true; m_UseBModeFilterNext = isSet; } void mitk::USDiPhASImageSource::ModifyScatteringCoefficient(int coeff) { m_ScatteringCoefficientNext = coeff; m_ScatteringCoefficientModified = true; } void mitk::USDiPhASImageSource::ModifyCompensateForScattering(bool useIt) { m_CompensateForScatteringNext = useIt; m_CompensateForScatteringModified = true; } void mitk::USDiPhASImageSource::ModifyEnergyCompensation(bool compensate) { m_CompensateEnergyNext = compensate; m_CompensateEnergyModified = true; } void mitk::USDiPhASImageSource::SetDataType(DataType dataT) { if (dataT != m_DataType) { m_DataType = dataT; MITK_INFO << "Setting new DataType..." << dataT; switch (m_DataType) { case DataType::Image_uChar : MITK_INFO << "height: " << m_Device->GetScanMode().imageHeight << " width: " << m_Device->GetScanMode().imageWidth; break; case DataType::Beamformed_Short : MITK_INFO << "samples: " << m_Device->GetScanMode().reconstructionSamplesPerLine << " lines: " << m_Device->GetScanMode().reconstructionLines; break; } } } void mitk::USDiPhASImageSource::SetGUIOutput(std::function out) { USDiPhASImageSource::m_GUIOutput = out; m_StartTime = ((float)std::clock()) / CLOCKS_PER_SEC; //wait till the callback is available again m_UseGUIOutPut = false; } void mitk::USDiPhASImageSource::SetUseBModeFilter(bool isSet) { m_UseBModeFilter = isSet; } void mitk::USDiPhASImageSource::SetVerticalSpacing(float mm) { m_VerticalSpacingNext = mm; m_VerticalSpacingModified = true; } void mitk::USDiPhASImageSource::SetSavingSettings(SavingSettings settings) { m_SavingSettings = settings; } // this is just a little function to set the filenames below right inline void replaceAll(std::string& str, const std::string& from, const std::string& to) { if (from.empty()) return; size_t start_pos = 0; while ((start_pos = str.find(from, start_pos)) != std::string::npos) { str.replace(start_pos, from.length(), to); start_pos += to.length(); // In case 'to' contains 'from', like replacing 'x' with 'yx' } } void mitk::USDiPhASImageSource::SetRecordingStatus(bool record) { // start the recording process if (record) { m_RecordedImages.clear(); m_RawRecordedImages.clear(); // we make sure there are no leftovers m_ImageTimestampRecord.clear(); // also for the timestamps m_PixelValues.clear(); // aaaand for the pixel values if (m_SavingSettings.saveRaw) { m_Device->GetScanMode().transferChannelData = true; m_Device->UpdateScanmode(); // set the raw Data to be transfered } // tell the callback to start recording images m_CurrentlyRecording = true; } // save images, end recording, and clean up else { m_CurrentlyRecording = false; m_Device->GetScanMode().transferChannelData = false; // make sure raw Channel Data is not transferred anymore! m_Device->UpdateScanmode(); // get the time and date, put them into a nice string and create a folder for the images time_t time = std::time(nullptr); time_t* timeptr = &time; std::string currentDate = std::ctime(timeptr); replaceAll(currentDate, ":", "-"); currentDate.pop_back(); //std::string MakeFolder = "mkdir \"c:/DiPhASImageData/" + currentDate + "\""; //system(MakeFolder.c_str()); // initialize file paths and the images Image::Pointer PAImage = Image::New(); Image::Pointer USImage = Image::New(); std::string pathPA = "c:\\ImageData\\" + currentDate + "-" + "PAbeamformed" + ".nrrd"; std::string pathUS = "c:\\ImageData\\" + currentDate + "-" + "USImages" + ".nrrd"; std::string pathTS = "c:\\ImageData\\" + currentDate + "-" + "ts" + ".csv"; std::string pathS = "c:\\ImageData\\" + currentDate + "-" + "Settings" + ".txt"; // idon't forget the raw Images (if chosen to be saved) Image::Pointer PAImageRaw = Image::New(); Image::Pointer USImageRaw = Image::New(); std::string pathPARaw = "c:\\ImageData\\" + currentDate + "-" + "PAraw" + ".nrrd"; std::string pathUSRaw = "c:\\ImageData\\" + currentDate + "-" + "USImagesRaw" + ".nrrd"; if (m_Device->GetScanMode().beamformingAlgorithm == (int)Beamforming::Interleaved_OA_US) // save a PAImage if we used interleaved mode { // first, save the data, so the pyro does not aquire more unneccessary timestamps m_Pyro->SaveData(); // now order the images and save them // the beamformed ones... if (m_SavingSettings.saveBeamformed) { OrderImagesInterleaved(PAImage, USImage, m_RecordedImages, false); mitk::IOUtil::Save(USImage, pathUS); mitk::IOUtil::Save(PAImage, pathPA); } // ...and the raw images if (m_SavingSettings.saveRaw) { OrderImagesInterleaved(PAImageRaw, USImageRaw, m_RawRecordedImages, true); mitk::IOUtil::Save(USImageRaw, pathUSRaw); mitk::IOUtil::Save(PAImageRaw, pathPARaw); } // read the pixelvalues of the enveloped images at this position itk::Index<3> pixel = { { (itk::Index<3>::IndexValueType)(m_RecordedImages.at(1)->GetDimension(0) / 2), (itk::Index<3>::IndexValueType)(22.0 / 532.0*m_Device->GetScanMode().reconstructionSamplesPerLine), 0 } }; //22/532*2048 = 84 GetPixelValues(pixel, m_PixelValues); // write the Pixelvalues to m_PixelValues // save the timestamps! ofstream timestampFile; timestampFile.open(pathTS); timestampFile << ",timestamp,pixelvalue"; // write the header for (int index = 0; index < m_ImageTimestampRecord.size(); ++index) { timestampFile << "\n" << index << "," << m_ImageTimestampRecord.at(index) << "," << m_PixelValues.at(index); } timestampFile.close(); //save the settings! ofstream settingsFile; settingsFile.open(pathS); auto& sM = m_Device->GetScanMode(); settingsFile << "[General Parameters]\n"; settingsFile << "Scan Depth [mm] = " << sM.receivePhaseLengthSeconds * sM.averageSpeedOfSound / 2 * 1000 << "\n"; settingsFile << "Speed of Sound [m/s] = " << sM.averageSpeedOfSound << "\n"; settingsFile << "Excitation Frequency [MHz] = " << sM.transducerFrequencyHz/1000000 << "\n"; settingsFile << "Voltage [V] = " << sM.voltageV << "\n"; settingsFile << "TGC min = " << (int)sM.tgcdB[0] << " max = " << (int)sM.tgcdB[6] << "\n"; settingsFile << "[Beamforming Parameters]\n"; settingsFile << "Reconstructed Lines = " << sM.reconstructionLines << "\n"; settingsFile << "Samples per Line = " << sM.reconstructionSamplesPerLine << "\n"; settingsFile.close(); } else if (m_Device->GetScanMode().beamformingAlgorithm == (int)Beamforming::PlaneWaveCompound) // save no PAImage if we used US only mode { OrderImagesUltrasound(USImage, m_RecordedImages); mitk::IOUtil::Save(USImage, pathUS); } m_PixelValues.clear(); m_RawRecordedImages.clear(); // clean up the pixel values m_RecordedImages.clear(); // clean up the images m_ImageTimestampRecord.clear(); // clean up the timestamps } } void mitk::USDiPhASImageSource::GetPixelValues(itk::Index<3> pixel, std::vector& values) { unsigned int events = m_Device->GetScanMode().transmitEventsCount + 1; // the PA event is not included in the transmitEvents, so we add 1 here for (int index = 0; index < m_RecordedImages.size(); index += events) // omit sound images { Image::Pointer image = m_RecordedImages.at(index); image = ApplyBmodeFilter(image); values.push_back(image.GetPointer()->GetPixelValueByIndex(pixel)); } } void mitk::USDiPhASImageSource::OrderImagesInterleaved(Image::Pointer PAImage, Image::Pointer USImage, std::vector recordedList, bool raw) { unsigned int width = 32; unsigned int height = 32; unsigned int events = m_Device->GetScanMode().transmitEventsCount + 1; // the PA event is not included in the transmitEvents, so we add 1 here if (raw) { width = recordedList.at(0)->GetDimension(0); height = recordedList.at(0)->GetDimension(1); } else if (m_DataType == DataType::Beamformed_Short) { width = m_Device->GetScanMode().reconstructionLines; height = m_Device->GetScanMode().reconstructionSamplesPerLine; } else if (m_DataType == DataType::Image_uChar) { width = m_Device->GetScanMode().imageWidth; height = m_Device->GetScanMode().imageHeight; } unsigned int dimLaser[] = { (unsigned int)width, (unsigned int)height, (unsigned int)(recordedList.size() / events)}; unsigned int dimSound[] = { (unsigned int)width, (unsigned int)height, (unsigned int)(recordedList.size() / events * (events-1))}; PAImage->Initialize(recordedList.back()->GetPixelType(), 3, dimLaser); PAImage->SetGeometry(recordedList.back()->GetGeometry()); USImage->Initialize(recordedList.back()->GetPixelType(), 3, dimSound); USImage->SetGeometry(recordedList.back()->GetGeometry()); for (int index = 0; index < recordedList.size(); ++index) { mitk::ImageReadAccessor inputReadAccessor(recordedList.at(index)); if (index % events == 0) { PAImage->SetSlice(inputReadAccessor.GetData(), index / events); } else { USImage->SetSlice(inputReadAccessor.GetData(), ((index - (index % events)) / events) + (index % events)-1); } } } void mitk::USDiPhASImageSource::OrderImagesUltrasound(Image::Pointer USImage, std::vector recordedList) { unsigned int width = 32; unsigned int height = 32; unsigned int events = m_Device->GetScanMode().transmitEventsCount; if (m_DataType == DataType::Beamformed_Short) { width = (unsigned int)m_Device->GetScanMode().reconstructionLines; height = (unsigned int)m_Device->GetScanMode().reconstructionSamplesPerLine; } else if (m_DataType == DataType::Image_uChar) { width = (unsigned int)m_Device->GetScanMode().imageWidth; height = (unsigned int)m_Device->GetScanMode().imageHeight; } unsigned int dimSound[] = { (unsigned int)width, (unsigned int)height, (unsigned int)recordedList.size()}; USImage->Initialize(recordedList.back()->GetPixelType(), 3, dimSound); USImage->SetGeometry(recordedList.back()->GetGeometry()); for (int index = 0; index < recordedList.size(); ++index) { mitk::ImageReadAccessor inputReadAccessor(recordedList.at(index)); USImage->SetSlice(inputReadAccessor.GetData(), index); } } \ No newline at end of file diff --git a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h index 3f75369e14..0ed2fdfb89 100644 --- a/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h +++ b/Modules/US/USHardwareDiPhAS/mitkUSDiPhASImageSource.h @@ -1,191 +1,193 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKUSDiPhASImageSource_H_HEADER_INCLUDED_ #define MITKUSDiPhASImageSource_H_HEADER_INCLUDED_ #include "mitkUSImageSource.h" #include "mitkUSDiPhASCustomControls.h" #include "Framework.IBMT.US.CWrapper.h" #include "mitkImageReadAccessor.h" #include "itkFastMutexLock.h" #include #include #include #include #include #include #include #include namespace mitk { class USDiPhASDevice; /** * \brief Implementation of mitk::USImageSource for DiPhAS API devices. * The method mitk::USImageSource::GetNextRawImage() is implemented for * getting images from the DiPhAS API. * * The image data is given to this class from the DiPhAS API by calling * a callback method that writes the image data to an mitk::image */ class USDiPhASImageSource : public USImageSource { public: mitkClassMacro(USDiPhASImageSource, USImageSource); mitkNewMacro1Param(Self, mitk::USDiPhASDevice*); itkCloneMacro(Self); + typedef itk::Image< float, 3 > itkFloatImageType; typedef mitk::USDiPhASDeviceCustomControls::DataType DataType; typedef mitk::USDiPhASDeviceCustomControls::SavingSettings SavingSettings; /** * Implementation of the superclass method. Returns the pointer * to the mitk::Image filled by DiPhAS API callback. */ virtual void GetNextRawImage( mitk::Image::Pointer& ); /** * The API calls this function to pass the image data to the * user; here the m_Image is updated */ void mitk::USDiPhASImageSource::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); void SetGUIOutput(std::function out); /** This starts or ends the recording session*/ void SetRecordingStatus(bool record); void SetSavingSettings(SavingSettings settings); void SetVerticalSpacing(float mm); void ModifyDataType(DataType dataT); void ModifyUseBModeFilter(bool isSet); void ModifyScatteringCoefficient(int coeff); void ModifyCompensateForScattering(bool useIt); void ModifyEnergyCompensation(bool compensate); /** * Sets the spacing used in the image based on the informations of the ScanMode in USDiPhAS Device */ void UpdateImageGeometry(); protected: void SetDataType(DataType dataT); void SetUseBModeFilter(bool isSet); USDiPhASImageSource(mitk::USDiPhASDevice* device); virtual ~USDiPhASImageSource( ); /** This vector holds all the images we record, if recording is set to active. */ std::vector m_RecordedImages; std::vector m_RawRecordedImages; std::vector m_ImageTimestampRecord; std::vector m_ImageTimestampBuffer; long long m_CurrentImageTimestamp; bool m_CurrentlyRecording; mitk::OphirPyro::Pointer m_Pyro; bool m_PyroConnected; std::vector m_FluenceCompOriginal; std::vector m_FluenceCompResized; std::vector::Pointer> m_FluenceCompResizedItk; std::vector m_ImageBuffer; int m_LastWrittenImage; int m_BufferSize; unsigned int m_ImageDimensions[3]; mitk::Vector3D m_ImageSpacing; mitk::Image::Pointer ApplyBmodeFilter(mitk::Image::Pointer image, bool useLogFilter = false); + mitk::Image::Pointer CutOffTop(mitk::Image::Pointer image, int cutOffSize = 165); mitk::Image::Pointer ResampleOutputVertical(mitk::Image::Pointer image, float verticalSpacing = 0.1); mitk::Image::Pointer ApplyScatteringCompensation(mitk::Image::Pointer inputImage, int scatteringCoefficient); mitk::Image::Pointer ApplyResampling(mitk::Image::Pointer inputImage, mitk::Vector3D outputSpacing, unsigned int outputSize[3]); mitk::Image::Pointer MultiplyImage(mitk::Image::Pointer inputImage, double value); void OrderImagesInterleaved(Image::Pointer PAImage, Image::Pointer USImage, std::vector recordedList, bool raw); void OrderImagesUltrasound(Image::Pointer USImage, std::vector recordedList); void GetPixelValues(itk::Index<3> pixel, std::vector& values); float GetPixelValue(itk::Index<3> pixel); std::vector m_PixelValues; mitk::USDiPhASDevice* m_Device; /** This is a callback to pass text data to the GUI. */ std::function m_GUIOutput; /** * Variables for management of current state. */ SavingSettings m_SavingSettings; float m_StartTime; bool m_UseGUIOutPut; BeamformerStateInfoNative m_BeamformerInfos; bool m_UseBModeFilter; bool m_DataTypeModified; DataType m_DataTypeNext; bool m_UseBModeFilterModified; bool m_UseBModeFilterNext; float m_VerticalSpacing; float m_VerticalSpacingNext; bool m_VerticalSpacingModified; int m_ScatteringCoefficient; int m_ScatteringCoefficientNext; bool m_ScatteringCoefficientModified; bool m_CompensateForScattering; bool m_CompensateForScatteringNext; bool m_CompensateForScatteringModified; bool m_CompensateEnergy; bool m_CompensateEnergyNext; bool m_CompensateEnergyModified; DataType m_DataType; }; } // namespace mitk #endif // MITKUSDiPhASImageSource_H diff --git a/Plugins/org.mitk.gui.qt.lasercontrol/CMakeLists.txt b/Plugins/org.mitk.gui.qt.lasercontrol/CMakeLists.txt index 114e4aec48..e1e61eaca6 100644 --- a/Plugins/org.mitk.gui.qt.lasercontrol/CMakeLists.txt +++ b/Plugins/org.mitk.gui.qt.lasercontrol/CMakeLists.txt @@ -1,24 +1,24 @@ project(org_mitk_gui_qt_lasercontrol) if(WIN32) if(MITK_USE_GALIL_HARDWARE) configure_file( ${MITK_GALIL_API_PATH}/dll/x64/gclib.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) configure_file( ${MITK_GALIL_API_PATH}/dll/x64/gclibo.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) configure_file( ${MITK_GALIL_API_PATH}/dll/x64/gclib.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) configure_file( ${MITK_GALIL_API_PATH}/dll/x64/gclibo.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) endif() - if(MITK_USE_OPHIR_PRYO_HARDWARE) + if(MITK_USE_OPHIR_PYRO_HARDWARE) configure_file( ${MITK_OPHIR_API_PATH}/Debug/OphirPyroWrapper.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) configure_file( ${MITK_OPHIR_API_PATH}/Release/OphirPyroWrapper.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) configure_file( ${MITK_OPHIR_API_PATH}/Debug/OphirLMMeasurement.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) configure_file( ${MITK_OPHIR_API_PATH}/Release/OphirLMMeasurement.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) configure_file( ${MITK_OPHIR_API_PATH}/Debug/Interop.OphirLMMeasurementLib.dll ${MITK_BINARY_DIR}/bin/Debug/ COPYONLY ) configure_file( ${MITK_OPHIR_API_PATH}/Release/Interop.OphirLMMeasurementLib.dll ${MITK_BINARY_DIR}/bin/Release/ COPYONLY ) endif() endif() mitk_create_plugin( EXPORT_DIRECTIVE LASERCONTROL_EXPORT EXPORTED_INCLUDE_SUFFIXES src MODULE_DEPENDS MitkQtWidgetsExt MitkPhotoacousticsHardware )