diff --git a/Modules/Qmitk/QmitkServiceListWidget.h b/Modules/Qmitk/QmitkServiceListWidget.h index aefac9a464..9e05ed89d3 100644 --- a/Modules/Qmitk/QmitkServiceListWidget.h +++ b/Modules/Qmitk/QmitkServiceListWidget.h @@ -1,245 +1,247 @@ /*=================================================================== 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 _QmitkServiceListWidget_H_INCLUDED #define _QmitkServiceListWidget_H_INCLUDED #include "QmitkExports.h" #include "ui_QmitkServiceListWidgetControls.h" #include //QT headers #include #include //Microservices #include "usServiceReference.h" #include "usModuleContext.h" #include "usServiceEvent.h" #include "usServiceInterface.h" /** * \ingroup QmitkModule * * \brief This widget provides abstraction for the handling of MicroServices. * * Place one in your Plugin and set it to look for a certain interface. * One can also specify a filter and / or a property to use for captioning of * the services. It also offers functionality to signal * ServiceEvents and to return the actual classes, so only a minimum of * interaction with the MicroserviceInterface is required. * To get started, just put it in your Plugin or Widget, call the Initialize * Method and optionally connect it's signals. * As QT limits templating possibilities, events only throw ServiceReferences. * You can manually dereference them using TranslateServiceReference() */ class QMITK_EXPORT QmitkServiceListWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT private: mitk::ModuleContext* m_Context; /** \brief a filter to further narrow down the list of results*/ std::string m_Filter; /** \brief The name of the ServiceInterface that this class should list */ std::string m_Interface; /** \brief The name of the ServiceProperty that will be displayed in the list to represent the service */ std::string m_NamingProperty; public: static const std::string VIEW_ID; QmitkServiceListWidget(QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkServiceListWidget(); /** \brief This method is part of the widget an needs not to be called separately. */ virtual void CreateQtPartControl(QWidget *parent); /** \brief This method is part of the widget an needs not to be called separately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); /** * \brief Will return true, if a service is currently selected and false otherwise. * * Call this before requesting service references to avoid invalid ServiceReferences. */ bool GetIsServiceSelected(); /** * \brief Returns the currently selected Service as a ServiceReference. * * If no Service is selected, the result will probably be a bad pointer. call GetIsServiceSelected() * beforehand to avoid this */ mitk::ServiceReference GetSelectedServiceReference(); /** * \brief Use this function to return the currently selected service as a class directly. * * Make sure you pass the appropriate type, or else this call will fail. * Usually, you will pass the class itself, not the SmartPointer, but the function returns a pointer. Example: * \verbatim mitk::USDevice::Pointer device = GetSelectedService(); \endverbatim + * @return Returns the current selected device. Returns NULL if no device is selected. */ template T* GetSelectedService() { + if (this->m_Controls->m_ServiceList->currentRow()==-1) return NULL; mitk::ServiceReference ref = GetServiceForListItem( this->m_Controls->m_ServiceList->currentItem() ); return ( m_Context->GetService(ref) ); } /** * \brief Initializes the Widget with essential parameters. * * The string filter is an LDAP parsable String, compare mitk::ModuleContext for examples on filtering. * Pass class T to tell the widget which class it should filter for - only services of this class will be listed. * NamingProperty is a property that will be used to caption the Items in the list. If no filter is supplied, all * matching interfaces are shown. If no namingProperty is supplied, the interfaceName will be used to caption Items in the list. * For example, this Initialization will filter for all USDevices that are set to active. The USDevice's model will be used to display it in the list: * \verbatim std::string filter = "(&(" + mitk::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(IsActive=true))"; m_Controls.m_ActiveVideoDevices->Initialize(mitk::USImageMetadata::PROP_DEV_MODEL ,filter); * \endverbatim */ template void Initialize(const std::string& namingProperty = static_cast< std::string >(""),const std::string& filter = static_cast< std::string >("")) { std::string interfaceName ( us_service_interface_iid() ); m_Interface = interfaceName; InitPrivate(namingProperty, filter); } /** * \brief Translates a serviceReference to a class of the given type. * * Use this to translate the signal's parameters. To adhere to the MicroService contract, * only ServiceReferences stemming from the same widget should be used as parameters for this method. * \verbatim mitk::USDevice::Pointer device = TranslateReference(myDeviceReference); \endverbatim */ template T* TranslateReference(mitk::ServiceReference reference) { return dynamic_cast ( m_Context->GetService(reference) ); } /** *\brief This Function listens to ServiceRegistry changes and updates the list of services accordingly. * * The user of this widget does not need to call this method, it is instead used to recieve events from the module registry. */ void OnServiceEvent(const mitk::ServiceEvent event); signals: /** *\brief Emitted when a new Service matching the filter is being registered. * * Be careful if you use a filter: * If a device does not match the filter when registering, but modifies it's properties later to match the filter, * then the first signal you will see this device in will be ServiceModified. */ void ServiceRegistered(mitk::ServiceReference); /** *\brief Emitted directly before a Service matching the filter is being unregistered. */ void ServiceUnregistering(mitk::ServiceReference); /** *\brief Emitted when a Service matching the filter changes it's properties, or when a service that formerly not matched the filter * changed it's properties and now matches the filter. */ void ServiceModified(mitk::ServiceReference); /** *\brief Emitted when a Service matching the filter changes it's properties, * * and the new properties make it fall trough the filter. This effectively means that * the widget will not track the service anymore. Usually, the Service should still be useable though */ void ServiceModifiedEndMatch(mitk::ServiceReference); /** *\brief Emitted if the user selects a Service from the list. * * If no service is selected, an invalid serviceReference is returned. The user can easily check for this. * if (serviceReference) will evaluate to false, if the reference is invalid and true if valid. */ void ServiceSelectionChanged(mitk::ServiceReference); public slots: protected slots: /** \brief Called, when the selection in the list of Services changes. */ void OnServiceSelectionChanged(); protected: Ui::QmitkServiceListWidgetControls* m_Controls; ///< member holding the UI elements of this widget /** * \brief Internal structure used to link ServiceReferences to their QListWidgetItems */ struct ServiceListLink { mitk::ServiceReference service; QListWidgetItem* item; }; /** * \brief Finishes initialization after Initialize has been called. * * This function assumes that m_Interface is set correctly (Which Initialize does). */ void InitPrivate(const std::string& namingProperty, const std::string& filter); /** * \brief Contains a list of currently active services and their entires in the list. This is wiped with every ServiceRegistryEvent. */ std::vector m_ListContent; /** * \brief Constructs a ListItem from the given service, displays it, and locally stores the service. */ QListWidgetItem* AddServiceToList(mitk::ServiceReference serviceRef); /** * \brief Removes the given service from the list and cleans up. Returns true if successful, false if service was not found. */ bool RemoveServiceFromList(mitk::ServiceReference serviceRef); /** * \brief Returns the serviceReference corresponding to the given ListEntry or an invalid one if none was found (will evaluate to false in bool expressions). */ mitk::ServiceReference GetServiceForListItem(QListWidgetItem* item); /** * \brief Returns a list of ServiceReferences matching the filter criteria by querying the service registry. */ std::list GetAllRegisteredServices(); }; #endif // _QmitkServiceListWidget_H_INCLUDED diff --git a/Modules/US/USFilters/mitkUSImageVideoSource.cpp b/Modules/US/USFilters/mitkUSImageVideoSource.cpp index 3dc890ed33..ace4e5b8fa 100644 --- a/Modules/US/USFilters/mitkUSImageVideoSource.cpp +++ b/Modules/US/USFilters/mitkUSImageVideoSource.cpp @@ -1,156 +1,168 @@ /*=================================================================== 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. ===================================================================*/ // MITK HEADER #include "mitkUSImageVideoSource.h" #include "mitkImage.h" //OpenCV HEADER #include #include //Other #include mitk::USImageVideoSource::USImageVideoSource() : itk::Object(), m_VideoCapture(new cv::VideoCapture()), m_IsVideoReady(false), m_IsGreyscale(false), m_OpenCVToMitkFilter(mitk::OpenCVToMitkImageFilter::New()), m_ResolutionOverrideWidth(0), m_ResolutionOverrideHeight(0), m_ResolutionOverride(false) { m_OpenCVToMitkFilter->SetCopyBuffer(false); } mitk::USImageVideoSource::~USImageVideoSource() { } void mitk::USImageVideoSource::SetVideoFileInput(std::string path) { m_VideoCapture->open(path.c_str()); if(!m_VideoCapture->isOpened()) // check if we succeeded m_IsVideoReady = false; else m_IsVideoReady = true; // If Override is enabled, use it if (m_ResolutionOverride) { m_VideoCapture->set(CV_CAP_PROP_FRAME_WIDTH, this->m_ResolutionOverrideWidth); m_VideoCapture->set(CV_CAP_PROP_FRAME_HEIGHT, this->m_ResolutionOverrideHeight); } } void mitk::USImageVideoSource::SetCameraInput(int deviceID) { m_VideoCapture->open(deviceID); if(!m_VideoCapture->isOpened()) // check if we succeeded m_IsVideoReady = false; else m_IsVideoReady = true; // If Override is enabled, use it if (m_ResolutionOverride) { m_VideoCapture->set(CV_CAP_PROP_FRAME_WIDTH, this->m_ResolutionOverrideWidth); m_VideoCapture->set(CV_CAP_PROP_FRAME_HEIGHT, this->m_ResolutionOverrideHeight); } } void mitk::USImageVideoSource::SetColorOutput(bool isColor){ m_IsGreyscale = !isColor; } +int mitk::USImageVideoSource::GetImageHeight() +{ +if (m_VideoCapture) return m_VideoCapture->get(CV_CAP_PROP_FRAME_HEIGHT); +else return 0; +} + +int mitk::USImageVideoSource::GetImageWidth() +{ +if (m_VideoCapture) return m_VideoCapture->get(CV_CAP_PROP_FRAME_WIDTH); +else return 0; +} + void mitk::USImageVideoSource::SetRegionOfInterest(int topLeftX, int topLeftY, int bottomRightX, int bottomRightY) { // First, let's do some basic checks to make sure rectangle is inside of actual image if (topLeftX < 0) topLeftX = 0; if (topLeftY < 0) topLeftY = 0; // We can try and correct too large boundaries if (bottomRightX > m_VideoCapture->get(CV_CAP_PROP_FRAME_WIDTH)) bottomRightX = m_VideoCapture->get(CV_CAP_PROP_FRAME_WIDTH); - if (bottomRightX > m_VideoCapture->get(CV_CAP_PROP_FRAME_HEIGHT)) bottomRightY = m_VideoCapture->get(CV_CAP_PROP_FRAME_HEIGHT); + if (bottomRightY > m_VideoCapture->get(CV_CAP_PROP_FRAME_HEIGHT)) bottomRightY = m_VideoCapture->get(CV_CAP_PROP_FRAME_HEIGHT); // Nothing to save, throw an exception if (topLeftX > bottomRightX) mitkThrow() << "Invalid boundaries supplied to USImageVideoSource::SetRegionOfInterest()"; if (topLeftY > bottomRightY) mitkThrow() << "Invalid boundaries supplied to USImageVideoSource::SetRegionOfInterest()"; m_CropRegion = cv::Rect(topLeftX, topLeftY, bottomRightX - topLeftX, bottomRightY - topLeftY); } void mitk::USImageVideoSource::RemoveRegionOfInterest(){ m_CropRegion.width = 0; m_CropRegion.height = 0; } mitk::USImage::Pointer mitk::USImageVideoSource::GetNextImage() { // Loop video if necessary if (m_VideoCapture->get(CV_CAP_PROP_POS_AVI_RATIO) >= 0.99 ) m_VideoCapture->set(CV_CAP_PROP_POS_AVI_RATIO, 0); // Setup pointers cv::Mat image; cv::Mat buffer; // Retrieve image *m_VideoCapture >> image; // get a new frame from camera // if Region of interest is set, crop image if (m_CropRegion.width > 0){ buffer = image(m_CropRegion); image.release(); image = buffer; } // If this source is set to deliver greyscale images, convert it if (m_IsGreyscale) { cv::cvtColor(image, buffer, CV_RGB2GRAY, 1); image.release(); image = buffer; } // Convert to MITK-Image IplImage ipl_img = image; this->m_OpenCVToMitkFilter->SetOpenCVImage(&ipl_img); this->m_OpenCVToMitkFilter->Update(); // OpenCVToMitkImageFilter returns a standard mitk::image. We then transform it into an USImage mitk::USImage::Pointer result = mitk::USImage::New(this->m_OpenCVToMitkFilter->GetOutput(0)); // Clean up buffer.release(); image.release(); return result; } void mitk::USImageVideoSource::OverrideResolution(int width, int height){ this->m_ResolutionOverrideHeight = height; this->m_ResolutionOverrideWidth = width; if (m_VideoCapture != 0) { m_VideoCapture->set(CV_CAP_PROP_FRAME_WIDTH, width); m_VideoCapture->set(CV_CAP_PROP_FRAME_HEIGHT, height); } } diff --git a/Modules/US/USFilters/mitkUSImageVideoSource.h b/Modules/US/USFilters/mitkUSImageVideoSource.h index c34509c033..bdbd2af224 100644 --- a/Modules/US/USFilters/mitkUSImageVideoSource.h +++ b/Modules/US/USFilters/mitkUSImageVideoSource.h @@ -1,139 +1,144 @@ /*=================================================================== 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 MITKUSImageVideoSource_H_HEADER_INCLUDED_ #define MITKUSImageVideoSource_H_HEADER_INCLUDED_ // ITK #include // MITK #include "mitkUSImage.h" #include "mitkOpenCVToMitkImageFilter.h" // OpenCV #include namespace mitk { /**Documentation * \brief This class can be pointed to a video file or a videodevice and delivers USImages. * * Images are in color by default, but can be set to greyscale via SetColorOutput(false), * which significantly improves performance. * * Images can also be cropped to a region of interest, further increasing performance. * * \ingroup US */ class MitkUS_EXPORT USImageVideoSource : public itk::Object { public: mitkClassMacro(USImageVideoSource, itk::ProcessObject); itkNewMacro(Self); /** * \brief Opens a video file for streaming. If nothing goes wrong, the * VideoSource is ready to deliver images after calling this function. */ void SetVideoFileInput(std::string path); /** * \brief Opens a video device for streaming. Takes the Device id. Try -1 for "grab the first you can get" * which works quite well if only one device is available. If nothing goes wrong, the * VideoSource is ready to deliver images after calling this function. */ void SetCameraInput(int deviceID); /** * \brief Sets the output image to rgb or grayscale. * Output is color by default * and can be set to color by passing true, or to grayscale again by passing false. */ void SetColorOutput(bool isColor); /** * /brief Defines the cropping area. The rectangle will be justified to the image borders * if the given rectangle is larger than the video source. If a correct rectangle is given, * The dimensions of the output image will be equal to those of the rectangle. */ void SetRegionOfInterest(int topLeftX, int topLeftY, int bottomRightX, int bottomRightY); /** * /brief Removes the region of interest. Produced images will be uncropped after call. */ void RemoveRegionOfInterest(); /** * \brief Retrieves the next frame. This will typically be the next frame in a file * or the last cached file in a device. */ mitk::USImage::Pointer GetNextImage(); /** * \brief This is a workaround for a problem that happens with some video device drivers. * * If you encounter OpenCV Warnings that buffer sizes do not match while calling getNextFrame, * then do the following: Using the drivers control panel to force a certain resolution, then call * this method with the same Dimensions after opening the device. */ void OverrideResolution(int width, int height); // Getter & Setter itkGetMacro(IsVideoReady, bool); itkGetMacro(ResolutionOverride, bool); itkSetMacro(ResolutionOverride, bool); + itkGetMacro(IsGreyscale,bool); + itkGetMacro(ResolutionOverrideWidth,int); + itkGetMacro(ResolutionOverrideHeight,int); + int GetImageHeight(); + int GetImageWidth(); protected: USImageVideoSource(); virtual ~USImageVideoSource(); /** * \brief The source of the video, managed internally */ cv::VideoCapture* m_VideoCapture; /** * \brief If true, a frame can be grabbed anytime. */ bool m_IsVideoReady; /** * \brief If true, image output will be greyscale. */ bool m_IsGreyscale; /** * \brief If values inside are nonzero, this rectangle will be cropped from the stream and used as an output. * Used to mark Region of Interest. */ cv::Rect m_CropRegion; /** * \brief Used to convert from OpenCV Images to MITK Images. */ mitk::OpenCVToMitkImageFilter::Pointer m_OpenCVToMitkFilter; /** * These Variables determined whether Resolution Override is on, what dimensions to use. */ int m_ResolutionOverrideWidth; int m_ResolutionOverrideHeight; bool m_ResolutionOverride; }; } // namespace mitk #endif /* MITKUSImageVideoSource_H_HEADER_INCLUDED_ */ diff --git a/Modules/US/USModel/mitkUSDevice.cpp b/Modules/US/USModel/mitkUSDevice.cpp index 1d8634c802..386d973f56 100644 --- a/Modules/US/USModel/mitkUSDevice.cpp +++ b/Modules/US/USModel/mitkUSDevice.cpp @@ -1,294 +1,319 @@ /*=================================================================== 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 "mitkUSDevice.h" -#include "mitkUSImageMetadata.h" //Microservices #include #include #include #include "mitkModuleContext.h" const std::string mitk::USDevice::US_INTERFACE_NAME = "org.mitk.services.UltrasoundDevice"; const std::string mitk::USDevice::US_PROPKEY_LABEL = US_INTERFACE_NAME + ".label"; const std::string mitk::USDevice::US_PROPKEY_ISACTIVE = US_INTERFACE_NAME + ".isActive"; const std::string mitk::USDevice::US_PROPKEY_CLASS = US_INTERFACE_NAME + ".class"; +mitk::USDevice::USImageCropArea mitk::USDevice::GetCropArea() +{ + MITK_INFO << "Return Crop Area L:" << m_CropArea.cropLeft << " R:" << m_CropArea.cropRight << " T:" << m_CropArea.cropTop << " B:" << m_CropArea.cropBottom; + return m_CropArea; +} mitk::USDevice::USDevice(std::string manufacturer, std::string model) : mitk::ImageSource() { // Initialize Members m_Metadata = mitk::USImageMetadata::New(); m_Metadata->SetDeviceManufacturer(manufacturer); m_Metadata->SetDeviceModel(model); m_IsActive = false; + USImageCropArea empty; + empty.cropBottom = 0; + empty.cropTop = 0; + empty.cropLeft = 0; + empty.cropRight = 0; + this->m_CropArea = empty; + m_IsConnected = false; //set number of outputs this->SetNumberOfOutputs(1); //create a new output mitk::USImage::Pointer newOutput = mitk::USImage::New(); this->SetNthOutput(0,newOutput); } mitk::USDevice::USDevice(mitk::USImageMetadata::Pointer metadata) : mitk::ImageSource() { m_Metadata = metadata; m_IsActive = false; + m_IsConnected = false; + + USImageCropArea empty; + empty.cropBottom = 0; + empty.cropTop = 0; + empty.cropLeft = 0; + empty.cropRight = 0; + this->m_CropArea = empty; //set number of outputs this->SetNumberOfOutputs(1); //create a new output mitk::USImage::Pointer newOutput = mitk::USImage::New(); this->SetNthOutput(0,newOutput); } mitk::USDevice::~USDevice() { } mitk::ServiceProperties mitk::USDevice::ConstructServiceProperties() { ServiceProperties props; std::string yes = "true"; std::string no = "false"; if(this->GetIsActive()) props[mitk::USDevice::US_PROPKEY_ISACTIVE] = yes; else props[mitk::USDevice::US_PROPKEY_ISACTIVE] = no; std::string isActive; if (GetIsActive()) isActive = " (Active)"; else isActive = " (Inactive)"; // e.g.: Zonare MyLab5 (Active) props[ mitk::USDevice::US_PROPKEY_LABEL] = m_Metadata->GetDeviceManufacturer() + " " + m_Metadata->GetDeviceModel() + isActive; if( m_Calibration.IsNotNull() ) props[ mitk::USImageMetadata::PROP_DEV_ISCALIBRATED ] = yes; else props[ mitk::USImageMetadata::PROP_DEV_ISCALIBRATED ] = no; props[ mitk::USDevice::US_PROPKEY_CLASS ] = GetDeviceClass(); props[ mitk::USImageMetadata::PROP_DEV_MANUFACTURER ] = m_Metadata->GetDeviceManufacturer(); props[ mitk::USImageMetadata::PROP_DEV_MODEL ] = m_Metadata->GetDeviceModel(); props[ mitk::USImageMetadata::PROP_DEV_COMMENT ] = m_Metadata->GetDeviceComment(); props[ mitk::USImageMetadata::PROP_PROBE_NAME ] = m_Metadata->GetProbeName(); props[ mitk::USImageMetadata::PROP_PROBE_FREQUENCY ] = m_Metadata->GetProbeFrequency(); props[ mitk::USImageMetadata::PROP_ZOOM ] = m_Metadata->GetZoom(); return props; } bool mitk::USDevice::Connect() { if (GetIsConnected()) { MITK_WARN << "Tried to connect an ultrasound device that was already connected. Ignoring call..."; return false; } // Prepare connection, fail if this fails. if (! this->OnConnection()) return false; + // Update state + m_IsConnected = true; + // Get Context and Module mitk::ModuleContext* context = GetModuleContext(); ServiceProperties props = ConstructServiceProperties(); m_ServiceRegistration = context->RegisterService(this, props); // This makes sure that the SmartPointer to this device does not invalidate while the device is connected this->Register(); return true; } bool mitk::USDevice::Disconnect() { if ( ! GetIsConnected()) { MITK_WARN << "Tried to disconnect an ultrasound device that was not connected. Ignoring call..."; return false; } // Prepare connection, fail if this fails. if (! this->OnDisconnection()) return false; + // Update state + m_IsConnected = false; + // Unregister m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; // Undo the manual registration done in Connect(). Pointer will invalidte, if no one holds a reference to this object anymore. this->UnRegister(); return true; } bool mitk::USDevice::Activate() { if (! this->GetIsConnected()) return false; m_IsActive = true; // <- Necessary to safely allow Subclasses to start threading based on activity state m_IsActive = OnActivation(); ServiceProperties props = ConstructServiceProperties(); this->m_ServiceRegistration.SetProperties(props); return m_IsActive; } void mitk::USDevice::Deactivate() { m_IsActive= false; ServiceProperties props = ConstructServiceProperties(); this->m_ServiceRegistration.SetProperties(props); OnDeactivation(); } void mitk::USDevice::AddProbe(mitk::USProbe::Pointer probe) { for(int i = 0; i < m_ConnectedProbes.size(); i++) { if (m_ConnectedProbes[i]->IsEqualToProbe(probe)) return; } this->m_ConnectedProbes.push_back(probe); } void mitk::USDevice::ActivateProbe(mitk::USProbe::Pointer probe){ // currently, we may just add the probe. This behaviour should be changed, should more complicated SDK applications emerge AddProbe(probe); int index = -1; for(int i = 0; i < m_ConnectedProbes.size(); i++) { if (m_ConnectedProbes[i]->IsEqualToProbe(probe)) index = i; } // index now contains the position of the original instance of this probe m_ActiveProbe = m_ConnectedProbes[index]; } void mitk::USDevice::DeactivateProbe(){ m_ActiveProbe = 0; } mitk::USImage* mitk::USDevice::GetOutput() { if (this->GetNumberOfOutputs() < 1) return NULL; return static_cast(this->ProcessObject::GetOutput(0)); } mitk::USImage* mitk::USDevice::GetOutput(unsigned int idx) { if (this->GetNumberOfOutputs() < 1) return NULL; return static_cast(this->ProcessObject::GetOutput(idx)); } void mitk::USDevice::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::USDevice::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter only has " << this->GetNumberOfOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a NULL pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" ); } // Call Graft on USImage to copy member data output->Graft( graft ); } itk::ProcessObject::DataObjectPointer mitk::USDevice::MakeOutput( unsigned int /*idx */) { mitk::USImage::Pointer p = mitk::USImage::New(); return static_cast(p.GetPointer()); } bool mitk::USDevice::ApplyCalibration(mitk::USImage::Pointer image){ if ( m_Calibration.IsNull() ) return false; image->GetGeometry()->SetIndexToWorldTransform(m_Calibration); return true; } //########### GETTER & SETTER ##################// void mitk::USDevice::setCalibration (mitk::AffineTransform3D::Pointer calibration){ if (calibration.IsNull()) { MITK_ERROR << "Null pointer passed to SetCalibration of mitk::USDevice. Ignoring call."; return; } m_Calibration = calibration; m_Metadata->SetDeviceIsCalibrated(true); if (m_ServiceRegistration != 0) { ServiceProperties props = ConstructServiceProperties(); this->m_ServiceRegistration.SetProperties(props); } } bool mitk::USDevice::GetIsActive() { return m_IsActive; } bool mitk::USDevice::GetIsConnected() { // a device is connected if it is registered with the Microservice Registry return (m_ServiceRegistration != 0); } std::string mitk::USDevice::GetDeviceManufacturer(){ return this->m_Metadata->GetDeviceManufacturer(); } std::string mitk::USDevice::GetDeviceModel(){ return this->m_Metadata->GetDeviceModel(); } std::string mitk::USDevice::GetDeviceComment(){ return this->m_Metadata->GetDeviceComment(); } std::vector mitk::USDevice::GetConnectedProbes() { return m_ConnectedProbes; } diff --git a/Modules/US/USModel/mitkUSDevice.h b/Modules/US/USModel/mitkUSDevice.h index c982eadca9..ffb9aa1501 100644 --- a/Modules/US/USModel/mitkUSDevice.h +++ b/Modules/US/USModel/mitkUSDevice.h @@ -1,298 +1,313 @@ /*=================================================================== 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 MITKUSDevice_H_HEADER_INCLUDED_ #define MITKUSDevice_H_HEADER_INCLUDED_ // STL #include // MitkUS #include "mitkUSProbe.h" #include "mitkUSImageMetadata.h" #include "mitkUSImage.h" #include // MITK #include #include // ITK #include // Microservices #include #include #include namespace mitk { /**Documentation * \brief A device holds information about it's model, make and the connected probes. It is the * common super class for all devices and acts as an image source for mitkUSImages. It is the base class * for all US Devices, and every new device should extend it. * * US Devices support output of calibrated images, i.e. images that include a specific geometry. * To achieve this, call SetCalibration, and make sure that the subclass also calls apply * transformation at some point (The USDevice does not automatically apply the transformation to the image) * * Note that SmartPointers to USDevices will not invalidate while the device is still connected. * \ingroup US */ class MitkUS_EXPORT USDevice : public mitk::ImageSource { public: mitkClassMacro(USDevice, mitk::ImageSource); + struct USImageCropArea + { + int cropLeft; + int cropRight; + int cropBottom; + int cropTop; + }; + /** *\brief These constants are used in conjunction with Microservices */ static const std::string US_INTERFACE_NAME; // Common Interface name of all US Devices. Used to refer to this device via Microservices static const std::string US_PROPKEY_LABEL; // Human readable text represntation of this device static const std::string US_PROPKEY_ISACTIVE; // Whether this Device is active or not. static const std::string US_PROPKEY_CLASS; // Class Name of this Object /** * \brief Connects this device. A connected device is ready to deliver images (i.e. be Activated). A Connected Device can be active. A disconnected Device cannot be active. * Internally calls onConnect and then registers the device with the service. A device usually should * override the OnConnection() method, but never the Connect() method, since this will possibly exclude the device * from normal service management. The exact flow of events is: * 0. Check if the device is already connected. If yes, return true anyway, but don't do anything. * 1. Call OnConnection() Here, a device should establish it's connection with the hardware Afterwards, it should be ready to start transmitting images at any time. * 2. If OnConnection() returns true ("successful"), then the device is registered with the service. * 3. if not, it the method itself returns false or may throw an expection, depeneding on the device implementation. * */ bool Connect(); /** * \brief Works analogously to mitk::USDevice::Connect(). Don't override this Method, but onDisconnection instead. */ bool Disconnect(); /** * \brief Activates this device. After the activation process, the device will start to produce images. This Method will fail, if the device is not connected. */ bool Activate(); /** * \brief Deactivates this device. After the deactivation process, the device will no longer produce images, but still be connected. */ void Deactivate(); /** * \brief Add a probe to the device without connecting to it. * This should usually be done before connecting to the probe. */ virtual void AddProbe(mitk::USProbe::Pointer probe); /** * \brief Connect to a probe and activate it. The probe should be added first. * Usually, a VideoDevice will simply add a probe it wants to connect to, * but an SDK Device might require adding a probe first. */ virtual void ActivateProbe(mitk::USProbe::Pointer probe); /** * \brief Deactivates the currently active probe. */ virtual void DeactivateProbe(); /** * \brief Removes a probe from the ist of currently added probes. */ //virtual void removeProbe(mitk::USProbe::Pointer probe); /** * \brief Returns a vector containing all connected probes. */ std::vector GetConnectedProbes(); /** *\brief return the output (output with id 0) of the filter */ USImage* GetOutput(void); /** *\brief return the output with id idx of the filter */ USImage* GetOutput(unsigned int idx); /** *\brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::GraftNthOutput for details */ virtual void GraftNthOutput(unsigned int idx, itk::DataObject *graft); /** * \brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::Graft Output for details */ virtual void GraftOutput(itk::DataObject *graft); /** * \brief Make a DataObject of the correct type to used as the specified output. * * This method is automatically called when DataObject::DisconnectPipeline() * is called. DataObject::DisconnectPipeline, disconnects a data object * from being an output of its current source. When the data object * is disconnected, the ProcessObject needs to construct a replacement * output data object so that the ProcessObject is in a valid state. * Subclasses of USImageVideoSource that have outputs of different * data types must overwrite this method so that proper output objects * are created. */ virtual DataObjectPointer MakeOutput(unsigned int idx); //########### GETTER & SETTER ##################// /** * \brief Returns the Class of the Device. This Method must be reimplemented by every Inheriting Class. */ virtual std::string GetDeviceClass() = 0; /** * \brief True, if the device is currently generating image data, false otherwise. */ bool GetIsActive(); /** * \brief True, if the device is currently ready to start transmitting image data or is already * transmitting image data. A disconnected device cannot be activated. */ bool GetIsConnected(); /** * \brief Sets a transformation as Calibration data. It also marks the device as Calibrated. This data is not automatically applied to the image. Subclasses must call ApplyTransformation * to achieve this. */ void setCalibration (mitk::AffineTransform3D::Pointer calibration); /** * \brief Returns the current Calibration */ itkGetMacro(Calibration, mitk::AffineTransform3D::Pointer); /** * \brief Returns the currently active probe or null, if none is active */ itkGetMacro(ActiveProbe, mitk::USProbe::Pointer); + /* @return Returns the area that will be cropped from the US image. Is disabled / [0,0,0,0] by default. */ + mitk::USDevice::USImageCropArea GetCropArea(); + std::string GetDeviceManufacturer(); std::string GetDeviceModel(); std::string GetDeviceComment(); protected: mitk::USProbe::Pointer m_ActiveProbe; std::vector m_ConnectedProbes; bool m_IsActive; + bool m_IsConnected; + + /* @brief defines the area that should be cropped from the US image */ + USImageCropArea m_CropArea; /* * \brief This Method constructs the service properties which can later be used to * register the object with the Microservices * Return service properties */ mitk::ServiceProperties ConstructServiceProperties(); /** * \brief Is called during the connection process. Override this method in your subclass to handle the actual connection. * Return true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ virtual bool OnConnection() = 0; /** * \brief Is called during the disconnection process. Override this method in your subclass to handle the actual disconnection. * Return true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ virtual bool OnDisconnection() = 0; /** * \brief Is called during the activation process. After this method is finished, the device should be generating images */ virtual bool OnActivation() = 0; /** * \brief Is called during the deactivation process. After a call to this method the device should still be connected, but not producing images anymore. */ virtual void OnDeactivation() = 0; /** * \brief This metadata set is privately used to imprint USImages with Metadata later. * At instantiation time, it only contains Information about the Device, * At scan time, it integrates this data with the probe information and imprints it on * the produced images. This field is intentionally hidden from outside interference. */ mitk::USImageMetadata::Pointer m_Metadata; /** * \brief Enforces minimal Metadata to be set. */ USDevice(std::string manufacturer, std::string model); /** * \brief Constructs a device with the given Metadata. Make sure the Metadata contains meaningful content! */ USDevice(mitk::USImageMetadata::Pointer metadata); virtual ~USDevice(); /** * \brief Grabs the next frame from the Video input. This method is called internally, whenever Update() is invoked by an Output. */ void GenerateData() = 0; /** * \brief The Calibration Transformation of this US-Device. This will automatically be written into the image once */ mitk::AffineTransform3D::Pointer m_Calibration; /** * \brief Convenience method that can be used by subclasses to apply the Calibration Data to the image. A subclass has to call * this method or set the transformation itself for the output to be calibrated! Returns true if a Calibration was set and false otherwise * (Usually happens when no transformation was set yet). */ bool ApplyCalibration(mitk::USImage::Pointer image); private: /** * \brief The device's ServiceRegistration object that allows to modify it's Microservice registraton details. */ mitk::ServiceRegistration m_ServiceRegistration; }; } // namespace mitk // This is the microservice declaration. Do not meddle! US_DECLARE_SERVICE_INTERFACE(mitk::USDevice, "org.mitk.services.UltrasoundDevice") #endif \ No newline at end of file diff --git a/Modules/US/USModel/mitkUSVideoDevice.cpp b/Modules/US/USModel/mitkUSVideoDevice.cpp index 5729d2004f..7cbe2e126b 100644 --- a/Modules/US/USModel/mitkUSVideoDevice.cpp +++ b/Modules/US/USModel/mitkUSVideoDevice.cpp @@ -1,135 +1,170 @@ /*=================================================================== 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 "mitkUSVideoDevice.h" mitk::USVideoDevice::USVideoDevice(int videoDeviceNumber, std::string manufacturer, std::string model) : mitk::USDevice(manufacturer, model) { Init(); m_SourceIsFile = false; m_DeviceID = videoDeviceNumber; + m_FilePath = ""; } mitk::USVideoDevice::USVideoDevice(std::string videoFilePath, std::string manufacturer, std::string model) : mitk::USDevice(manufacturer, model) { Init(); m_SourceIsFile = true; m_FilePath = videoFilePath; } mitk::USVideoDevice::USVideoDevice(int videoDeviceNumber, mitk::USImageMetadata::Pointer metadata) : mitk::USDevice(metadata) { Init(); m_SourceIsFile = false; m_DeviceID = videoDeviceNumber; + m_FilePath = ""; } mitk::USVideoDevice::USVideoDevice(std::string videoFilePath, mitk::USImageMetadata::Pointer metadata) : mitk::USDevice(metadata) { Init(); m_SourceIsFile = true; m_FilePath = videoFilePath; } mitk::USVideoDevice::~USVideoDevice() { } void mitk::USVideoDevice::Init() { m_Source = mitk::USImageVideoSource::New(); //this->SetNumberOfInputs(1); this->SetNumberOfOutputs(1); // mitk::USImage::Pointer output = mitk::USImage::New(); // output->Initialize(); this->SetNthOutput(0, this->MakeOutput(0)); this->m_MultiThreader = itk::MultiThreader::New(); this->m_ImageMutex = itk::FastMutexLock::New(); this->m_CameraActiveMutex= itk::FastMutexLock::New(); m_IsActive = false; } std::string mitk::USVideoDevice::GetDeviceClass(){ return "org.mitk.modules.us.USVideoDevice"; } bool mitk::USVideoDevice::OnConnection() { if (m_SourceIsFile){ m_Source->SetVideoFileInput(m_FilePath); } else { m_Source->SetCameraInput(m_DeviceID); } + SetSourceCropArea(); return true; } bool mitk::USVideoDevice::OnDisconnection() { if (m_IsActive) this->Deactivate(); return true; } bool mitk::USVideoDevice::OnActivation() { MITK_INFO << "Activated UsVideoDevice!"; this->m_ThreadID = this->m_MultiThreader->SpawnThread(this->Acquire, this); return true; } void mitk::USVideoDevice::OnDeactivation() { // happens automatically when m_Active is set to false } void mitk::USVideoDevice::GenerateData() { mitk::USImage::Pointer result; result = m_Image; // Set Metadata result->SetMetadata(this->m_Metadata); //Apply Transformation this->ApplyCalibration(result); // Set Output this->SetNthOutput(0, result); } void mitk::USVideoDevice::GrabImage() { m_Image = m_Source->GetNextImage(); //this->SetNthOutput(0, m_Image); //this->Modified(); } +void mitk::USVideoDevice::SetSourceCropArea() +{ +if (this->m_Source.IsNotNull()) + { + if((m_CropArea.cropBottom==0)&& + (m_CropArea.cropTop==0)&& + (m_CropArea.cropLeft==0)&& + (m_CropArea.cropRight==0)) + {this->m_Source->RemoveRegionOfInterest();} + else + { + int right = m_Source->GetImageWidth() - m_CropArea.cropRight; + int bottom = m_Source->GetImageHeight() - m_CropArea.cropBottom; + this->m_Source->SetRegionOfInterest(m_CropArea.cropLeft, + m_CropArea.cropTop, + right, + bottom); + } + + } +else + {MITK_WARN << "Cannot set crop are, source is not initialized!";} + +} + +void mitk::USVideoDevice::SetCropArea(mitk::USDevice::USImageCropArea newArea) +{ +m_CropArea = newArea; +MITK_INFO << "Set Crop Area L:" << m_CropArea.cropLeft << " R:" << m_CropArea.cropRight << " T:" << m_CropArea.cropTop << " B:" << m_CropArea.cropBottom; +if (m_IsConnected) SetSourceCropArea(); +} + ITK_THREAD_RETURN_TYPE mitk::USVideoDevice::Acquire(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; mitk::USVideoDevice * device = (mitk::USVideoDevice *) pInfo->UserData; while (device->GetIsActive()) { device->GrabImage(); } return ITK_THREAD_RETURN_VALUE; } diff --git a/Modules/US/USModel/mitkUSVideoDevice.h b/Modules/US/USModel/mitkUSVideoDevice.h index c04e13e1a4..fa7ef2f703 100644 --- a/Modules/US/USModel/mitkUSVideoDevice.h +++ b/Modules/US/USModel/mitkUSVideoDevice.h @@ -1,148 +1,154 @@ /*=================================================================== 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 MITKUSVideoDevice_H_HEADER_INCLUDED_ #define MITKUSVideoDevice_H_HEADER_INCLUDED_ #include #include #include "mitkUSDevice.h" #include #include "mitkUSImageVideoSource.h" namespace mitk { /**Documentation * \brief A VideoDevice is the common class for video only devices. They capture Video Input either from * a file or from a device, and transform the output into an mitkUSImage with attached Metadata. * This simple implementation does only capture and display 2D Images without cropping or registration. * One can simply inherit from this class and overwrite the handle2D and handle 3Dmethods to get full access to the data * \ingroup US */ class MitkUS_EXPORT USVideoDevice : public mitk::USDevice { public: mitkClassMacro(USVideoDevice, mitk::USDevice); // To open a device (DeviceID, Manufacturer, Model) mitkNewMacro3Param(Self, int, std::string, std::string); // To open A VideoFile (Path, Manufacturer, Model) mitkNewMacro3Param(Self, std::string, std::string, std::string); // To open a device (DeviceID, Metadata) mitkNewMacro2Param(Self, int, mitk::USImageMetadata::Pointer); // To open A VideoFile (Path, Metadata) mitkNewMacro2Param(Self, std::string, mitk::USImageMetadata::Pointer); + /*@brief Sets the area that will be cropped from the US image. Set [0,0,0,0] to disable it, which is also default. */ + void SetCropArea(mitk::USDevice::USImageCropArea newArea); /** * \brief Returns the qualified name of this class. Be sure to override this when inheriting from VideoDevice! */ virtual std::string GetDeviceClass(); void GenerateData(); itkGetMacro(Source, mitk::USImageVideoSource::Pointer); itkGetMacro(Image, mitk::USImage::Pointer); + itkGetMacro(DeviceID,int); + itkGetMacro(FilePath,std::string); void GrabImage(); protected: static ITK_THREAD_RETURN_TYPE Acquire(void* pInfoStruct); /** * \brief Creates a new device that will deliver USImages taken from a video device. * under windows, try -1 for device number, which will grab the first available one * (Open CV functionality) */ USVideoDevice(int videoDeviceNumber, std::string manufacturer, std::string model); /** * \brief Creates a new device that will deliver USImages taken from a video file. */ USVideoDevice(std::string videoFilePath, std::string manufacturer, std::string model); /** * \brief Creates a new device that will deliver USImages taken from a video device. * under windows, try -1 for device number, which will grab the first available one * (Open CV functionality) */ USVideoDevice(int videoDeviceNumber, mitk::USImageMetadata::Pointer metadata); /** * \brief Creates a new device that will deliver USImages taken from a video file. */ USVideoDevice(std::string videoFilePath, mitk::USImageMetadata::Pointer metadata); virtual ~USVideoDevice(); /** * \brief Initializes common properties for all constructors. */ void Init(); /** * \brief Is called during the connection process. * Returns true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ virtual bool OnConnection(); /** * \brief Is called during the disconnection process. * Returns true if successful and false if unsuccessful. Additionally, you may throw an exception to clarify what went wrong. */ virtual bool OnDisconnection(); /** * \brief Is called during the activation process. After this method is finsihed, the device should be generating images */ virtual bool OnActivation(); /** * \brief Is called during the deactivation process. After a call to this method the device should still be connected, but not producing images anymore. */ virtual void OnDeactivation(); /** * \brief The image source that we use to aquire data */ mitk::USImageVideoSource::Pointer m_Source; /** * \brief True, if this source plays back a file, false if it recieves data from a device */ bool m_SourceIsFile; /** * \brief The device id to connect to. Undefined, if m_SourceIsFile == true; */ int m_DeviceID; /** * \brief The Filepath id to connect to. Undefined, if m_SourceIsFile == false; */ std::string m_FilePath; + void SetSourceCropArea(); + // Threading-Related itk::MultiThreader::Pointer m_MultiThreader; ///< itk::MultiThreader used for thread handling itk::FastMutexLock::Pointer m_ImageMutex; ///< mutex for images provided by the range camera itk::FastMutexLock::Pointer m_CameraActiveMutex; ///< mutex for the cameraActive flag int m_ThreadID; ///< ID of the started thread mitk::USImage::Pointer m_Image; }; } // namespace mitk #endif diff --git a/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.cpp b/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.cpp index 527a551ae0..69eef55116 100644 --- a/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.cpp +++ b/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.cpp @@ -1,101 +1,116 @@ /*=================================================================== 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. ===================================================================*/ //#define _USE_MATH_DEFINES #include +#include +#include const std::string QmitkUSDeviceManagerWidget::VIEW_ID = "org.mitk.views.QmitkUSDeviceManagerWidget"; QmitkUSDeviceManagerWidget::QmitkUSDeviceManagerWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { m_Controls = NULL; CreateQtPartControl(this); } QmitkUSDeviceManagerWidget::~QmitkUSDeviceManagerWidget() { } //////////////////// INITIALIZATION ///////////////////// void QmitkUSDeviceManagerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkUSDeviceManagerWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); } // Initializations std::string empty = ""; m_Controls->m_ConnectedDevices->Initialize(mitk::USDevice::US_PROPKEY_LABEL, empty); } void QmitkUSDeviceManagerWidget::CreateConnections() { if ( m_Controls ) { connect( m_Controls->m_BtnActivate, SIGNAL( clicked() ), this, SLOT(OnClickedActivateDevice()) ); connect( m_Controls->m_BtnDisconnect, SIGNAL( clicked() ), this, SLOT(OnClickedDisconnectDevice()) ); connect( m_Controls->m_ConnectedDevices, SIGNAL( ServiceSelectionChanged(mitk::ServiceReference) ), this, SLOT(OnDeviceSelectionChanged(mitk::ServiceReference)) ); } } ///////////// Methods & Slots Handling Direct Interaction ///////////////// void QmitkUSDeviceManagerWidget::OnClickedActivateDevice() { mitk::USDevice::Pointer device = m_Controls->m_ConnectedDevices->GetSelectedService(); if (device.IsNull()) return; if (device->GetIsActive()) device->Deactivate(); else device->Activate(); // Manually reevaluate Button logic OnDeviceSelectionChanged(m_Controls->m_ConnectedDevices->GetSelectedServiceReference()); } void QmitkUSDeviceManagerWidget::OnClickedDisconnectDevice(){ mitk::USDevice::Pointer device = m_Controls->m_ConnectedDevices->GetSelectedService(); if (device.IsNull()) return; device->Disconnect(); } void QmitkUSDeviceManagerWidget::OnDeviceSelectionChanged(mitk::ServiceReference reference){ if (! reference) { m_Controls->m_BtnActivate->setEnabled(false); m_Controls->m_BtnDisconnect->setEnabled(false); return; } std::string isActive = reference.GetProperty( mitk::USDevice::US_PROPKEY_ISACTIVE ).ToString(); if (isActive.compare("true") == 0) { m_Controls->m_BtnActivate->setEnabled(true); m_Controls->m_BtnDisconnect->setEnabled(false); m_Controls->m_BtnActivate->setText("Deactivate"); } else { m_Controls->m_BtnActivate->setEnabled(true); m_Controls->m_BtnDisconnect->setEnabled(true); m_Controls->m_BtnActivate->setText("Activate"); } } +void QmitkUSDeviceManagerWidget::DisconnectAllDevices() +{ +//at the moment disconnects ALL devices. Maybe we only want to disconnect the devices handled by this widget? +mitk::ModuleContext* thisContext = mitk::GetModuleContext(); +std::list services = thisContext->GetServiceReferences(); +for(std::list::iterator it = services.begin(); it != services.end(); ++it) + { + mitk::USDevice::Pointer currentDevice = thisContext->GetService(*it); + currentDevice->Disconnect(); + } +MITK_INFO << "Disconnected ALL US devises!"; +} + diff --git a/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.h b/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.h index 7eaaaea8be..90f6ab757f 100644 --- a/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.h +++ b/Modules/USUI/Qmitk/QmitkUSDeviceManagerWidget.h @@ -1,85 +1,87 @@ /*=================================================================== 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 _QmitkUSDeviceManagerWidget_H_INCLUDED #define _QmitkUSDeviceManagerWidget_H_INCLUDED #include "MitkUSUIExports.h" #include "ui_QmitkUSDeviceManagerWidgetControls.h" #include "mitkUSDevice.h" #include //QT headers #include #include /** * @brief This Widget is used to manage available Ultrasound Devices. * * It allows activation, deactivation and disconnection of connected devices. * * @ingroup USUI */ class MitkUSUI_EXPORT QmitkUSDeviceManagerWidget :public QWidget { //this is needed for all Qt objects that should have a MOC object (everything that derives from QObject) Q_OBJECT public: static const std::string VIEW_ID; QmitkUSDeviceManagerWidget(QWidget* p = 0, Qt::WindowFlags f1 = 0); virtual ~QmitkUSDeviceManagerWidget(); /* @brief This method is part of the widget an needs not to be called seperately. */ virtual void CreateQtPartControl(QWidget *parent); /* @brief This method is part of the widget an needs not to be called seperately. (Creation of the connections of main and control widget.)*/ virtual void CreateConnections(); + /* @brief Disconnects all devices immediately. */ + virtual void DisconnectAllDevices(); public slots: protected slots: /* \brief Called, when the button "Activate Device" was clicked. */ void OnClickedActivateDevice(); /* \brief Called, when the button "Disconnect Device" was clicked. */ void OnClickedDisconnectDevice(); /* \brief Called, when the selection in the devicelist changes. */ void OnDeviceSelectionChanged(mitk::ServiceReference reference); protected: Ui::QmitkUSDeviceManagerWidgetControls* m_Controls; ///< member holding the UI elements of this widget private: }; #endif // _QmitkUSDeviceManagerWidget_H_INCLUDED diff --git a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp index dd66bcc330..738643af9a 100644 --- a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp +++ b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidget.cpp @@ -1,162 +1,169 @@ /*=================================================================== 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. ===================================================================*/ //#define _USE_MATH_DEFINES #include //QT headers //mitk headers //itk headers const std::string QmitkUSNewVideoDeviceWidget::VIEW_ID = "org.mitk.views.QmitkUSNewVideoDeviceWidget"; QmitkUSNewVideoDeviceWidget::QmitkUSNewVideoDeviceWidget(QWidget* parent, Qt::WindowFlags f): QWidget(parent, f) { m_Controls = NULL; CreateQtPartControl(this); + + //disable a few UI components which are not needed at the moment + m_Controls->probe_label->setVisible(false); + m_Controls->probe_label2->setVisible(false); + m_Controls->zoom_label->setVisible(false); + m_Controls->m_Probe->setVisible(false); + m_Controls->m_Zoom->setVisible(false); } QmitkUSNewVideoDeviceWidget::~QmitkUSNewVideoDeviceWidget() { } //////////////////// INITIALIZATION ///////////////////// void QmitkUSNewVideoDeviceWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkUSNewVideoDeviceWidgetControls; m_Controls->setupUi(parent); this->CreateConnections(); } } void QmitkUSNewVideoDeviceWidget::CreateConnections() { if ( m_Controls ) { connect( m_Controls->m_BtnDone, SIGNAL(clicked()), this, SLOT(OnClickedDone()) ); connect( m_Controls->m_BtnCancel, SIGNAL(clicked()), this, SLOT(OnClickedCancel()) ); connect( m_Controls->m_RadioDeviceSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection()) ); connect( m_Controls->m_RadioFileSource, SIGNAL(clicked()), this, SLOT(OnDeviceTypeSelection()) ); } // Hide & show stuff m_Controls->m_FilePathSelector->setVisible(false); } ///////////// Methods & Slots Handling Direct Interaction ///////////////// void QmitkUSNewVideoDeviceWidget::OnClickedDone(){ m_Active = false; // Assemble Metadata mitk::USImageMetadata::Pointer metadata = mitk::USImageMetadata::New(); metadata->SetDeviceComment(m_Controls->m_Comment->text().toStdString()); metadata->SetDeviceModel(m_Controls->m_Model->text().toStdString()); metadata->SetDeviceManufacturer(m_Controls->m_Manufacturer->text().toStdString()); metadata->SetProbeName(m_Controls->m_Probe->text().toStdString()); metadata->SetZoom(m_Controls->m_Zoom->text().toStdString()); // Create Device mitk::USVideoDevice::Pointer newDevice; if (m_Controls->m_RadioDeviceSource->isChecked()){ int deviceID = m_Controls->m_DeviceSelector->value(); newDevice = mitk::USVideoDevice::New(deviceID, metadata); } else { std::string filepath = m_Controls->m_FilePathSelector->text().toStdString(); newDevice = mitk::USVideoDevice::New(filepath, metadata); } // Set Video Options newDevice->GetSource()->SetColorOutput(! m_Controls->m_CheckGreyscale->isChecked()); // If Resolution override is activated, apply it if (m_Controls->m_CheckResolutionOverride->isChecked()) { int width = m_Controls->m_ResolutionWidth->value(); int height = m_Controls->m_ResolutionHeight->value(); newDevice->GetSource()->OverrideResolution(width, height); newDevice->GetSource()->SetResolutionOverride(true); } newDevice->Connect(); emit Finished(); } void QmitkUSNewVideoDeviceWidget::OnClickedCancel(){ m_TargetDevice = 0; m_Active = false; emit Finished(); } void QmitkUSNewVideoDeviceWidget::OnDeviceTypeSelection(){ m_Controls->m_FilePathSelector->setVisible(m_Controls->m_RadioFileSource->isChecked()); m_Controls->m_DeviceSelector->setVisible(m_Controls->m_RadioDeviceSource->isChecked()); } ///////////////// Methods & Slots Handling Logic ////////////////////////// void QmitkUSNewVideoDeviceWidget::EditDevice(mitk::USDevice::Pointer device) { // If no VideoDevice is given, throw an exception if (device->GetDeviceClass().compare("org.mitk.modules.us.USVideoDevice") != 0){ // TODO Alert if bad path - mitkThrow() << "NewVideoDevcieWidget recieved an incompatible Device Type to edit. Devicetype was: " << device->GetDeviceClass(); + mitkThrow() << "NewVideoDeviceWidget recieved an incompatible Device Type to edit. Devicetype was: " << device->GetDeviceClass(); } m_TargetDevice = static_cast (device.GetPointer()); m_Active = true; } void QmitkUSNewVideoDeviceWidget::CreateNewDevice() { m_TargetDevice = 0; InitFields(mitk::USImageMetadata::New()); m_Active = true; } /////////////////////// HOUSEHOLDING CODE /////////////////////////////// QListWidgetItem* QmitkUSNewVideoDeviceWidget::ConstructItemFromDevice(mitk::USDevice::Pointer device){ QListWidgetItem *result = new QListWidgetItem; std::string text = device->GetDeviceManufacturer() + "|" + device->GetDeviceModel(); result->setText(text.c_str()); return result; } void QmitkUSNewVideoDeviceWidget::InitFields(mitk::USImageMetadata::Pointer metadata){ this->m_Controls->m_Manufacturer->setText (metadata->GetDeviceManufacturer().c_str()); this->m_Controls->m_Model->setText (metadata->GetDeviceModel().c_str()); this->m_Controls->m_Comment->setText (metadata->GetDeviceComment().c_str()); this->m_Controls->m_Probe->setText (metadata->GetProbeName().c_str()); this->m_Controls->m_Zoom->setText (metadata->GetZoom().c_str()); } diff --git a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui index d9458881a4..9e0e6663a0 100644 --- a/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui +++ b/Modules/USUI/Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui @@ -1,292 +1,292 @@ QmitkUSNewVideoDeviceWidgetControls 0 0 405 - 569 + 595 0 0 QmitkUSNewVideoDeviceWidget Metadata: 50 false true Device Information: Manufacturer Model Comment - + true Probe Information: - + Probe - + Zoom - GroupBox: + Video Source: -1 10 -1 From Device: true From File: Cancel Override: If you encounter problems with devices (e.g. Images of uniform color and error messages in the log window), then try to set the resolution externally using the device's driver panel and then enter the same resolution here. true Enable Resolution Override 10 2048 10 640 10 2048 10 480 Width: Height: Qt::Vertical 20 40 Add Device Video Options: Greyscale Image (Significantly faster) true m_Manufacturer m_Model m_Comment m_Probe m_Zoom m_RadioDeviceSource m_DeviceSelector m_RadioFileSource m_FilePathSelector m_BtnCancel m_CheckResolutionOverride m_ResolutionWidth m_ResolutionHeight diff --git a/Modules/USUI/Qmitk/mitkUSDevicePersistence.cpp b/Modules/USUI/Qmitk/mitkUSDevicePersistence.cpp new file mode 100644 index 0000000000..e80db1e4c3 --- /dev/null +++ b/Modules/USUI/Qmitk/mitkUSDevicePersistence.cpp @@ -0,0 +1,185 @@ +/*=================================================================== + +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 "mitkUSDevicePersistence.h" + +//Microservices +#include "usServiceReference.h" +#include "usModuleContext.h" +#include +#include + + +mitk::USDevicePersistence::USDevicePersistence() : m_devices("MITK US","Device Settings") + { + } + +void mitk::USDevicePersistence::StoreCurrentDevices() + { + mitk::ModuleContext* thisContext = mitk::GetModuleContext(); + + std::list services = thisContext->GetServiceReferences(); + MITK_INFO << "Trying to save " << services.size() << " US devices."; + int numberOfSavedDevices = 0; + for(std::list::iterator it = services.begin(); it != services.end(); ++it) + { + mitk::USDevice::Pointer currentDevice = thisContext->GetService(*it); + //check if it is a USVideoDevice + if (currentDevice->GetDeviceClass()=="org.mitk.modules.us.USVideoDevice") + { + mitk::USVideoDevice::Pointer currentVideoDevice = dynamic_cast(currentDevice.GetPointer()); + QString identifier = "device" + QString::number(numberOfSavedDevices); + m_devices.setValue(identifier,USVideoDeviceToString(currentVideoDevice)); + numberOfSavedDevices++; + } + + else + { + MITK_WARN << "Saving of US devices of the type " << currentDevice->GetDeviceClass() << " is not supported at the moment. Skipping device."; + } + } + m_devices.setValue("numberOfSavedDevices",numberOfSavedDevices); + MITK_INFO << "Successfully saved " << numberOfSavedDevices << " US devices."; + } + +void mitk::USDevicePersistence::RestoreLastDevices() + { + int numberOfSavedDevices = m_devices.value("numberOfSavedDevices").toInt(); + + for(int i=0; iConnect(); + } + + MITK_INFO << "Restoring " << numberOfSavedDevices << " US devices."; + } + +QString mitk::USDevicePersistence::USVideoDeviceToString(mitk::USVideoDevice::Pointer d) +{ + +QString manufacturer = d->GetDeviceManufacturer().c_str(); +QString model = d->GetDeviceModel().c_str(); +QString comment = d->GetDeviceComment().c_str(); +int source = d->GetDeviceID(); +std::string file = d->GetFilePath(); +if (file == "") file = "none"; +int greyscale = d->GetSource()->GetIsGreyscale(); +int resOverride = d->GetSource()->GetResolutionOverride(); +int resWidth = d->GetSource()->GetResolutionOverrideWidth(); +int resHight = d->GetSource()->GetResolutionOverrideHeight(); +int cropRight = d->GetCropArea().cropRight; +int cropLeft = d->GetCropArea().cropLeft; +int cropBottom = d->GetCropArea().cropBottom; +int cropTop = d->GetCropArea().cropTop; +char seperator = '|'; + +QString returnValue = manufacturer + seperator + + model + seperator + + comment + seperator + + QString::number(source) + seperator + + file.c_str() + seperator + + QString::number(greyscale) + seperator + + QString::number(resOverride) + seperator + + QString::number(resWidth) + seperator + + QString::number(resHight) + seperator + + QString::number(cropRight) + seperator + + QString::number(cropLeft) + seperator + + QString::number(cropBottom) + seperator + + QString::number(cropTop) + ; + +MITK_INFO << "Output String: " << returnValue.toStdString(); +return returnValue; +} + +mitk::USVideoDevice::Pointer mitk::USDevicePersistence::StringToUSVideoDevice(QString s) +{ +MITK_INFO << "Input String: " << s.toStdString(); +std::vector data; +std::string seperators = "|"; +split(s.toStdString(),seperators,data); +if(data.size() != 13) + { + MITK_ERROR << "Cannot parse US device! (Size: " << data.size() << ")"; + return mitk::USVideoDevice::New("INVALID","INVALID","INVALID"); + } + +std::string manufacturer = data.at(0); +std::string model = data.at(1); +std::string comment = data.at(2); +int source = (QString(data.at(3).c_str())).toInt(); +std::string file = data.at(4); +bool greyscale = (QString(data.at(5).c_str())).toInt(); +bool resOverride = (QString(data.at(6).c_str())).toInt(); +int resWidth = (QString(data.at(7).c_str())).toInt(); +int resHight = (QString(data.at(8).c_str())).toInt(); +mitk::USDevice::USImageCropArea cropArea; +cropArea.cropRight = (QString(data.at(9).c_str())).toInt(); +cropArea.cropLeft = (QString(data.at(10).c_str())).toInt(); +cropArea.cropBottom = (QString(data.at(11).c_str())).toInt(); +cropArea.cropTop = (QString(data.at(12).c_str())).toInt(); + +// Assemble Metadata +mitk::USImageMetadata::Pointer metadata = mitk::USImageMetadata::New(); +metadata->SetDeviceManufacturer(manufacturer); +metadata->SetDeviceComment(comment); +metadata->SetDeviceModel(model); +metadata->SetProbeName(""); +metadata->SetZoom(""); + +// Create Device +mitk::USVideoDevice::Pointer returnValue; +if (file == "none") + { + returnValue = mitk::USVideoDevice::New(source, metadata); + } +else + { + returnValue = mitk::USVideoDevice::New(file, metadata); + } + +// Set Video Options +returnValue->GetSource()->SetColorOutput(!greyscale); + +// If Resolution override is activated, apply it +if (resOverride) + { + returnValue->GetSource()->OverrideResolution(resWidth, resHight); + returnValue->GetSource()->SetResolutionOverride(true); + } + +// Set Crop Area +returnValue->SetCropArea(cropArea); + +return returnValue; +} + +void mitk::USDevicePersistence::split(std::string& text, std::string& separators, std::vector& words) + { + int n = text.length(); + int start, stop; + + start = text.find_first_not_of(separators); + while ((start >= 0) && (start < n)) + { + stop = text.find_first_of(separators, start); + if ((stop < 0) || (stop > n)) stop = n; + words.push_back(text.substr(start, stop - start)); + start = text.find_first_not_of(separators, stop+1); + } + } diff --git a/Modules/USUI/Qmitk/mitkUSDevicePersistence.h b/Modules/USUI/Qmitk/mitkUSDevicePersistence.h new file mode 100644 index 0000000000..eb6d757537 --- /dev/null +++ b/Modules/USUI/Qmitk/mitkUSDevicePersistence.h @@ -0,0 +1,66 @@ +/*=================================================================== + +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 MITKUSDevicePersistence_H_HEADER_INCLUDED_ +#define MITKUSDevicePersistence_H_HEADER_INCLUDED_ + +// MITK +#include "MitkUSUIExports.h" +#include +#include + +// ITK +#include + +// QT + #include + + +namespace mitk { + + /**Documentation + * TODO + */ + + class MitkUSUI_EXPORT USDevicePersistence : public itk::Object + { + public: + mitkClassMacro(USDevicePersistence, itk::Object); + itkNewMacro(Self); + + void StoreCurrentDevices(); + + void RestoreLastDevices(); + + protected: + + USDevicePersistence(); + virtual ~USDevicePersistence(){} + + QString USVideoDeviceToString(mitk::USVideoDevice::Pointer d); + mitk::USVideoDevice::Pointer StringToUSVideoDevice(QString s); + + QSettings m_devices; + + void split(std::string& text, std::string& separators, std::vector& words); + + + }; +} // namespace mitk + + +#endif diff --git a/Modules/USUI/files.cmake b/Modules/USUI/files.cmake index 0747fcff17..9d8fd3d4e3 100644 --- a/Modules/USUI/files.cmake +++ b/Modules/USUI/files.cmake @@ -1,19 +1,20 @@ set(CPP_FILES Qmitk/QmitkUSDeviceManagerWidget.cpp Qmitk/QmitkUSNewVideoDeviceWidget.cpp + Qmitk/mitkUSDevicePersistence.cpp ) set(UI_FILES Qmitk/QmitkUSDeviceManagerWidgetControls.ui Qmitk/QmitkUSNewVideoDeviceWidgetControls.ui ) set(MOC_H_FILES Qmitk/QmitkUSDeviceManagerWidget.h Qmitk/QmitkUSNewVideoDeviceWidget.h ) # uncomment the following line if you want to use Qt resources set(QRC_FILES # resources/QmitkToFUtilWidget.qrc ) diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp index 2d637e6c92..5a696f73a5 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp @@ -1,128 +1,214 @@ /*=================================================================== 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. ===================================================================*/ // Blueberry #include #include //Mitk -#include "mitkDataNode.h" +#include +#include +#include // Qmitk #include "UltrasoundSupport.h" #include // Qt #include // Ultrasound #include "mitkUSDevice.h" const std::string UltrasoundSupport::VIEW_ID = "org.mitk.views.ultrasoundsupport"; void UltrasoundSupport::SetFocus() { m_Controls.m_AddDevice->setFocus(); } void UltrasoundSupport::CreateQtPartControl( QWidget *parent ) { m_Timer = new QTimer(this); // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); connect( m_Controls.m_AddDevice, SIGNAL(clicked()), this, SLOT(OnClickedAddNewDevice()) ); // Change Widget Visibilities connect( m_Controls.m_AddDevice, SIGNAL(clicked()), this->m_Controls.m_NewVideoDeviceWidget, SLOT(CreateNewDevice()) ); // Init NewDeviceWidget connect( m_Controls.m_NewVideoDeviceWidget, SIGNAL(Finished()), this, SLOT(OnNewDeviceWidgetDone()) ); // After NewDeviceWidget finished editing connect( m_Controls.m_BtnView, SIGNAL(clicked()), this, SLOT(OnClickedViewDevice()) ); connect( m_Timer, SIGNAL(timeout()), this, SLOT(DisplayImage())); + connect( m_Controls.crop_left, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged()) ); + connect( m_Controls.crop_right, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged()) ); + connect( m_Controls.crop_top, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged()) ); + connect( m_Controls.crop_bot, SIGNAL(valueChanged(int)), this, SLOT(OnCropAreaChanged()) ); + + //connect (m_Controls.m_ActiveVideoDevices, SIGNAL()) // Initializations m_Controls.m_NewVideoDeviceWidget->setVisible(false); std::string filter = "(&(" + mitk::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(" + mitk::USDevice::US_PROPKEY_ISACTIVE + "=true))"; - m_Controls.m_ActiveVideoDevices->Initialize(mitk::USImageMetadata::PROP_DEV_MODEL ,filter); + m_Controls.m_ActiveVideoDevices->Initialize(mitk::USDevice::US_PROPKEY_LABEL ,filter); + + //UI initializations + m_Controls.crop_left->setEnabled(false); + m_Controls.crop_right->setEnabled(false); + m_Controls.crop_bot->setEnabled(false); + m_Controls.crop_top->setEnabled(false); m_Node = mitk::DataNode::New(); m_Node->SetName("US Image Stream"); this->GetDataStorage()->Add(m_Node); } void UltrasoundSupport::OnClickedAddNewDevice() { m_Controls.m_NewVideoDeviceWidget->setVisible(true); m_Controls.m_DeviceManagerWidget->setVisible(false); m_Controls.m_AddDevice->setVisible(false); m_Controls.m_Headline->setText("Add New Device:"); } void UltrasoundSupport::DisplayImage() { - // m_Device->UpdateOutputData(0); - // mitk::USImage::Pointer image = m_Device->GetOutput(); - m_Device->UpdateOutputData(0); m_Node->SetData(m_Device->GetOutput()); this->RequestRenderWindowUpdate(); m_FrameCounter ++; if (m_FrameCounter == 10) { int nMilliseconds = m_Clock.restart(); - float fps = 10000.0f / (nMilliseconds ); + int fps = 10000.0f / (nMilliseconds ); m_Controls.m_FramerateLabel->setText("Current Framerate: "+ QString::number(fps) +" FPS"); m_FrameCounter = 0; } } +void UltrasoundSupport::OnCropAreaChanged() +{ +if (m_Device->GetDeviceClass()=="org.mitk.modules.us.USVideoDevice") + { + mitk::USVideoDevice::Pointer currentVideoDevice = dynamic_cast(m_Device.GetPointer()); + + mitk::USDevice::USImageCropArea newArea; + newArea.cropLeft = m_Controls.crop_left->value(); + newArea.cropTop = m_Controls.crop_top->value(); + newArea.cropRight = m_Controls.crop_right->value(); + newArea.cropBottom = m_Controls.crop_bot->value(); + + //check enabled: if not we are in the initializing step and don't need to do anything + //otherwise: update crop area + if (m_Controls.crop_right->isEnabled()) + currentVideoDevice->SetCropArea(newArea); + + GlobalReinit(); + } +else + { + MITK_WARN << "No USVideoDevice: Cannot Crop!"; + } +} + void UltrasoundSupport::OnClickedViewDevice() { m_FrameCounter = 0; + // We use the activity state of the timer to determine whether we are currently viewing images if ( ! m_Timer->isActive() ) // Activate Imaging { + //get device & set data node m_Device = m_Controls.m_ActiveVideoDevices->GetSelectedService(); if (m_Device.IsNull()){ m_Timer->stop(); return; } - //m_Device->UpdateOutputData(0); m_Device->Update(); m_Node->SetData(m_Device->GetOutput()); + + //start timer int interval = (1000 / m_Controls.m_FrameRate->value()); m_Timer->setInterval(interval); m_Timer->start(); + + //reinit view + GlobalReinit(); + + //change UI elements m_Controls.m_BtnView->setText("Stop Viewing"); + m_Controls.m_FrameRate->setEnabled(false); + m_Controls.crop_left->setValue(m_Device->GetCropArea().cropLeft); + m_Controls.crop_right->setValue(m_Device->GetCropArea().cropRight); + m_Controls.crop_bot->setValue(m_Device->GetCropArea().cropBottom); + m_Controls.crop_top->setValue(m_Device->GetCropArea().cropTop); + m_Controls.crop_left->setEnabled(true); + m_Controls.crop_right->setEnabled(true); + m_Controls.crop_bot->setEnabled(true); + m_Controls.crop_top->setEnabled(true); } - else - { //deactivate imaging - m_Controls.m_BtnView->setText("Start Viewing"); + else //deactivate imaging + { + //stop timer & release data m_Timer->stop(); m_Node->ReleaseData(); this->RequestRenderWindowUpdate(); + + //change UI elements + m_Controls.m_BtnView->setText("Start Viewing"); + m_Controls.m_FrameRate->setEnabled(true); + m_Controls.crop_left->setEnabled(false); + m_Controls.crop_right->setEnabled(false); + m_Controls.crop_bot->setEnabled(false); + m_Controls.crop_top->setEnabled(false); } } void UltrasoundSupport::OnNewDeviceWidgetDone() { m_Controls.m_NewVideoDeviceWidget->setVisible(false); m_Controls.m_DeviceManagerWidget->setVisible(true); m_Controls.m_AddDevice->setVisible(true); m_Controls.m_Headline->setText("Connected Devices:"); +} + +void UltrasoundSupport::GlobalReinit() +{ + // get all nodes that have not set "includeInBoundingBox" to false + mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false))); + mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); + + // calculate bounding geometry of these nodes + mitk::TimeSlicedGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); + + // initialize the views to the bounding geometry + mitk::RenderingManager::GetInstance()->InitializeViews(bounds); +} + +UltrasoundSupport::UltrasoundSupport() +{ +m_DevicePersistence = mitk::USDevicePersistence::New(); +m_DevicePersistence->RestoreLastDevices(); +} + +UltrasoundSupport::~UltrasoundSupport() +{ +m_DevicePersistence->StoreCurrentDevices(); +m_Controls.m_DeviceManagerWidget->DisconnectAllDevices(); } \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h index bf8a990af0..0bc0766b9d 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h @@ -1,97 +1,108 @@ /*=================================================================== 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 UltrasoundSupport_h #define UltrasoundSupport_h #include #include +#include #include "ui_UltrasoundSupportControls.h" #include /*! \brief UltrasoundSupport This plugin provides functionality to manage Ultrasound devices, create video devices and to view device images. \sa QmitkFunctionality \ingroup ${plugin_target}_internal */ class UltrasoundSupport : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: virtual void SetFocus(); static const std::string VIEW_ID; virtual void CreateQtPartControl(QWidget *parent); - signals: + UltrasoundSupport(); + virtual ~UltrasoundSupport(); public slots: /* * \brief This is called when the newDeviceWidget is closed */ void OnNewDeviceWidgetDone(); protected slots: void OnClickedAddNewDevice(); void OnClickedViewDevice(); + void OnCropAreaChanged(); + /* * \brief This is the main imaging loop that is called regularily during the imaging process */ void DisplayImage(); protected: + + int m_FrameCounter; /* * \brief This timer triggers periodic updates to the pipeline */ QTimer *m_Timer; QTime m_Clock; /* * \brief The device that is currently used to aquire images */ mitk::USDevice::Pointer m_Device; /* * \brief The node that we feed images into */ mitk::DataNode::Pointer m_Node; mitk::Image::Pointer m_Image; Ui::UltrasoundSupportControls m_Controls; + /** @brief reinits the view globally. */ + void GlobalReinit(); + + mitk::USDevicePersistence::Pointer m_DevicePersistence; + }; #endif // UltrasoundSupport_h diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui index 9e89ec192d..03a2baab20 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui @@ -1,193 +1,450 @@ UltrasoundSupportControls 0 0 - 467 + 410 461 0 0 QmitkTemplate 0 Device Management 12 75 true - Connected Devices: + Ultrasound Devices: - - - New Device - - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 120 + 0 + + + + New Device + + + + Qt::Vertical 20 40 US Imaging - + 12 75 true Active Ultrasound Devices: 0 0 - - - Start Viewing + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 120 + 0 + + + + Start Viewing + + + + + + + + + Qt::Vertical - + + + 20 + 40 + + + - - - Current Framerate: 0 FPS + + + Qt::Horizontal - - - - 75 - true - - + - Framerate Limit: + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Crop Ultrasound Image:</span></p></body></html> - - - 1 - - - 50 - - - 30 + + + + + + + Top + + + + + + + + + 999 + + + 5 + + + + + + + mm + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Bottom + + + + + + + + + 999 + + + 5 + + + + + + + mm + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Right + + + + + + + + + 999 + + + 5 + + + + + + + mm + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Left + + + + + + + + + 999 + + + 5 + + + + + + + mm + + + + + + + + + + + + + Qt::Horizontal - + - (Restart viewing to make changes effective) + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Framrate Settings:</span></p></body></html> - - - Qt::Vertical - - - - 20 - 40 - + + + Current Framerate: 0 FPS - + + + + + + + + Framerate Limit: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + 50 + + + 30 + + + + QmitkUSDeviceManagerWidget QWidget
QmitkUSDeviceManagerWidget.h
1
QmitkUSNewVideoDeviceWidget QWidget
QmitkUSNewVideoDeviceWidget.h
1
QmitkServiceListWidget QWidget
QmitkServiceListWidget.h
1