NifTK  16.4.1 - 0798f20
CMIC's Translational Medical Imaging Platform
itkCreatePositiveMammogram.h
Go to the documentation of this file.
1 /*=============================================================================
2 
3  NifTK: A software platform for medical image computing.
4 
5  Copyright (c) University College London (UCL). All rights reserved.
6 
7  This software is distributed WITHOUT ANY WARRANTY; without even
8  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
9  PURPOSE.
10 
11  See LICENSE.txt in the top level directory for details.
12 
13 =============================================================================*/
14 
15 #ifndef __itkCreatePositiveMammogram_h
16 #define __itkCreatePositiveMammogram_h
17 
18 #include <itksys/SystemTools.hxx>
19 
20 #include <itkImage.h>
21 #include <itkMetaDataDictionary.h>
22 #include <itkMetaDataObject.h>
23 
25 #include <itkMinimumMaximumImageCalculator.h>
26 #include <itkRescaleIntensityImageFilter.h>
28 #include <itkCastImageFilter.h>
29 
30 namespace itk
31 {
32 
33 
34 
35 // -------------------------------------------------------------------------
36 // SetTag()
37 // -------------------------------------------------------------------------
38 
39 void SetTag( itk::MetaDataDictionary &dictionary,
40  std::string tagID,
41  std::string newTagValue )
42 {
43  typedef itk::MetaDataDictionary DictionaryType;
44  typedef itk::MetaDataObject< std::string > MetaDataStringType;
45 
46  // Search for the tag
47 
48  DictionaryType::ConstIterator tagItr = dictionary.Find( tagID );
49  DictionaryType::ConstIterator end = dictionary.End();
50 
51  if ( tagItr != end )
52  {
53  MetaDataStringType::ConstPointer entryvalue =
54  dynamic_cast<const MetaDataStringType *>( tagItr->second.GetPointer() );
55 
56  if ( entryvalue )
57  {
58  std::string tagValue = entryvalue->GetMetaDataObjectValue();
59 
60  std::cout << "Changing tag (" << tagID << ") "
61  << " from: " << tagValue
62  << " to: " << newTagValue << std::endl;
63 
64  itk::EncapsulateMetaData<std::string>( dictionary, tagID, newTagValue );
65  }
66  }
67  else
68  {
69  std::cout << "Setting tag (" << tagID << ") "
70  << " to: " << newTagValue << std::endl;
71 
72  itk::EncapsulateMetaData<std::string>( dictionary, tagID, newTagValue );
73  }
74 
75 };
76 
77 
78 // -------------------------------------------------------------------------
79 // ModifyTag()
80 // -------------------------------------------------------------------------
81 
82 void ModifyTag( itk::MetaDataDictionary &dictionary,
83  std::string tagID,
84  std::string newTagValue )
85 {
86  typedef itk::MetaDataDictionary DictionaryType;
87  typedef itk::MetaDataObject< std::string > MetaDataStringType;
88 
89  // Search for the tag
90 
91  std::string tagValue;
92 
93  DictionaryType::ConstIterator tagItr = dictionary.Find( tagID );
94  DictionaryType::ConstIterator tagEnd = dictionary.End();
95 
96  if ( tagItr != tagEnd )
97  {
98  MetaDataStringType::ConstPointer entryvalue =
99  dynamic_cast<const MetaDataStringType *>( tagItr->second.GetPointer() );
100 
101  if ( entryvalue )
102  {
103  std::string tagValue = entryvalue->GetMetaDataObjectValue();
104 
105  std::cout << "Modifying tag (" << tagID << ") "
106  << " from: " << tagValue
107  << " to: " << newTagValue << std::endl;
108 
109  itk::EncapsulateMetaData<std::string>( dictionary, tagID, newTagValue );
110  }
111  }
112 
113 };
114 
115 
116 // --------------------------------------------------------------------------
118 // --------------------------------------------------------------------------
119 
120 template < typename TImage >
121 void CreatePositiveMammogram( typename TImage::Pointer &image,
122  itk::MetaDataDictionary &dictionary,
123  bool flgInvert=false )
124 {
125  typedef itk::MetaDataDictionary DictionaryType;
126  typedef itk::MetaDataObject< std::string > MetaDataStringType;
127 
128  // Check if the DICOM Inverse tag is set
129 
130  std::string tagInverse = "2050|0020";
131 
132  DictionaryType::ConstIterator tagInverseItr = dictionary.Find( tagInverse );
133  DictionaryType::ConstIterator tagInverseEnd = dictionary.End();
134 
135  if ( tagInverseItr != tagInverseEnd )
136  {
137  MetaDataStringType::ConstPointer entryvalue =
138  dynamic_cast<const MetaDataStringType *>( tagInverseItr->second.GetPointer() );
139 
140  if ( entryvalue )
141  {
142  std::string strInverse( "INVERSE" );
143  std::string tagInverseValue = entryvalue->GetMetaDataObjectValue();
144 
145  std::cout << "Tag (" << tagInverse
146  << ") is: " << tagInverseValue << std::endl;
147 
148  std::size_t foundInverse = tagInverseValue.find( strInverse );
149  if (foundInverse != std::string::npos)
150  {
151  flgInvert = true;
152  std::cout << "Image is INVERSE - inverting" << std::endl;
153  SetTag( dictionary, tagInverse, "IDENTITY" );
154  }
155  }
156  }
157 
158 
159  // Fix the MONOCHROME1 issue
160 
161  std::string tagPhotoInterpID = "0028|0004";
162 
163  DictionaryType::ConstIterator tagPhotoInterpItr = dictionary.Find( tagPhotoInterpID );
164  DictionaryType::ConstIterator tagPhotoInterpEnd = dictionary.End();
165 
166  if ( tagPhotoInterpItr != tagPhotoInterpEnd )
167  {
168  MetaDataStringType::ConstPointer entryvalue =
169  dynamic_cast<const MetaDataStringType *>( tagPhotoInterpItr->second.GetPointer() );
170 
171  if ( entryvalue )
172  {
173  std::string strMonochrome1( "MONOCHROME1" );
174  std::string tagPhotoInterpValue = entryvalue->GetMetaDataObjectValue();
175 
176  std::cout << "Tag (" << tagPhotoInterpID
177  << ") is: " << tagPhotoInterpValue << std::endl;
178 
179  std::size_t foundMonochrome1 = tagPhotoInterpValue.find( strMonochrome1 );
180  if (foundMonochrome1 != std::string::npos)
181  {
182  flgInvert = true;
183  std::cout << "Image is MONOCHROME1 - inverting" << std::endl;
184  SetTag( dictionary, tagPhotoInterpID, "MONOCHROME2" );
185  }
186  }
187  }
188 
189 
190  // Invert the image
191 
192  if ( flgInvert )
193  {
194  typedef typename itk::InvertIntensityBetweenMaxAndMinImageFilter< TImage > InvertFilterType;
195 
196  typename InvertFilterType::Pointer invertFilter = InvertFilterType::New();
197  invertFilter->SetInput( image );
198 
199  invertFilter->Update( );
200 
201  image = invertFilter->GetOutput();
202  image->DisconnectPipeline();
203  }
204 
205 };
206 
207 
208 // --------------------------------------------------------------------------
210 // --------------------------------------------------------------------------
211 
212 template < typename TImage >
213 bool ConvertMammogramFromRawToPresentation( typename TImage::Pointer &image,
214  itk::MetaDataDictionary &dictionary )
215 {
216  bool flgPreInvert = false;
217 
218  itksys_ios::ostringstream value;
219 
220  typedef itk::MetaDataDictionary DictionaryType;
221  typedef itk::MetaDataObject< std::string > MetaDataStringType;
222 
223  typedef itk::Image< float, TImage::ImageDimension > FloatImageType;
224 
225  typedef itk::MinimumMaximumImageCalculator< TImage > MinimumMaximumImageCalculatorType;
226 
227  typedef itk::CastImageFilter< TImage, FloatImageType > CastFilterType;
230 
231  typedef itk::RescaleIntensityImageFilter< FloatImageType, TImage > RescalerType;
232 
233  DictionaryType::ConstIterator tagItr;
234  DictionaryType::ConstIterator tagEnd;
235 
236  // Check that the modality DICOM tag is 'MG'
237 
238  std::string tagModalityID = "0008|0060";
239  std::string tagModalityValue;
240 
241  tagItr = dictionary.Find( tagModalityID );
242  tagEnd = dictionary.End();
243 
244  if( tagItr != tagEnd )
245  {
246  MetaDataStringType::ConstPointer entryvalue =
247  dynamic_cast<const MetaDataStringType *>( tagItr->second.GetPointer() );
248 
249  if ( entryvalue )
250  {
251  tagModalityValue = entryvalue->GetMetaDataObjectValue();
252  std::cout << "Modality Name (" << tagModalityID << ") "
253  << " is: " << tagModalityValue << std::endl;
254  }
255  }
256 
257  // Check that the 'Presentation Intent Type' is 'For Processing'
258 
259  std::string tagForProcessingID = "0008|0068";
260  std::string tagForProcessingValue;
261 
262  tagItr = dictionary.Find( tagForProcessingID );
263  tagEnd = dictionary.End();
264 
265  if( tagItr != tagEnd )
266  {
267  MetaDataStringType::ConstPointer entryvalue =
268  dynamic_cast<const MetaDataStringType *>( tagItr->second.GetPointer() );
269 
270  if ( entryvalue )
271  {
272  tagForProcessingValue = entryvalue->GetMetaDataObjectValue();
273  std::cout << "Presentation Intent Type (" << tagForProcessingID << ") "
274  << " is: " << tagForProcessingValue << std::endl;
275  }
276  }
277 
278  // Process this file?
279 
280  if ( ( ( tagModalityValue == std::string( "CR" ) ) || // Computed Radiography
281  ( tagModalityValue == std::string( "MG" ) ) ) && // Mammography
282  ( tagForProcessingValue == std::string( "FOR PROCESSING" ) ) )
283  {
284  std::cout << "Image is a raw \"FOR PROCESSING\" mammogram - converting"
285  << std::endl;
286  }
287  else
288  {
289  std::cout << "Skipping image - does not appear to be a \"FOR PROCESSING\" mammogram"
290  << std::endl << std::endl;
291  return false;
292  }
293 
294  // Set the desired output range (i.e. the same as the input)
295 
296  typename MinimumMaximumImageCalculatorType::Pointer
297  imageRangeCalculator = MinimumMaximumImageCalculatorType::New();
298 
299  imageRangeCalculator->SetImage( image );
300  imageRangeCalculator->Compute();
301 
302 
303  // Change the tag to "FOR PRESENTATION"
304 
305  ModifyTag( dictionary, "0008|0068", "FOR PRESENTATION" );
306 
307  // Set the pixel intensity relationship sign to linear
308  value.str("");
309  value << "LIN";
310  itk::EncapsulateMetaData<std::string>(dictionary,"0028|1040", value.str());
311 
312  // Set the pixel intensity relationship sign to one
313  value.str("");
314  value << 1;
315  itk::EncapsulateMetaData<std::string>(dictionary,"0028|1041", value.str());
316 
317  // Set the presentation LUT shape
318  ModifyTag( dictionary, "2050|0020", "IDENTITY" );
319 
320  // Check whether this is MONOCHROME1 or 2 and hence whether to invert
321 
322  std::string tagPhotoInterpID = "0028|0004";
323  std::string tagPhotoInterpValue;
324 
325  tagItr = dictionary.Find( tagPhotoInterpID );
326  tagEnd = dictionary.End();
327 
328  if( tagItr != tagEnd )
329  {
330  MetaDataStringType::ConstPointer entryvalue =
331  dynamic_cast<const MetaDataStringType *>( tagItr->second.GetPointer() );
332 
333  if ( entryvalue )
334  {
335  tagPhotoInterpValue = entryvalue->GetMetaDataObjectValue();
336  std::cout << "Photometric interportation is (" << tagPhotoInterpID << ") "
337  << " is: " << tagPhotoInterpValue << std::endl;
338  }
339  }
340 
341  std::size_t found = tagPhotoInterpValue.find( "MONOCHROME2" );
342  if ( found != std::string::npos )
343  {
344  std::cout << "Image is \"MONOCHROME2\" so will not be inverted"
345  << std::endl;
346  flgPreInvert = true; // Actually we pre-invert it
347  }
348 
349  found = tagPhotoInterpValue.find( "MONOCHROME1" );
350  if ( found != std::string::npos )
351  {
352  ModifyTag( dictionary, "0028|0004", "MONOCHROME2" );
353  }
354 
355 
356  // Convert the image to a "FOR PRESENTATION" version by calculating the logarithm and inverting
357 
358  typename CastFilterType::Pointer castFilter = CastFilterType::New();
359  castFilter->SetInput( image );
360  castFilter->UpdateLargestPossibleRegion();
361  typename FloatImageType::Pointer flImage = castFilter->GetOutput();
362 
363  if ( flgPreInvert )
364  {
365  typename InvertFilterType::Pointer invfilter = InvertFilterType::New();
366  invfilter->SetInput( flImage );
367  invfilter->UpdateLargestPossibleRegion();
368  flImage = invfilter->GetOutput();
369  flImage->DisconnectPipeline();
370  }
371 
372  typename LogFilterType::Pointer logfilter = LogFilterType::New();
373  logfilter->SetInput( flImage );
374  logfilter->UpdateLargestPossibleRegion();
375 
376  typename InvertFilterType::Pointer invfilter = InvertFilterType::New();
377  invfilter->SetInput(logfilter->GetOutput());
378  invfilter->UpdateLargestPossibleRegion();
379 
380  flImage = invfilter->GetOutput();
381  flImage->DisconnectPipeline();
382 
383 
384  // Rescale the image
385 
386  typename RescalerType::Pointer intensityRescaler = RescalerType::New();
387 
388  intensityRescaler->SetOutputMinimum(
389  static_cast< typename TImage::PixelType >( imageRangeCalculator->GetMinimum() ) );
390  intensityRescaler->SetOutputMaximum(
391  static_cast< typename TImage::PixelType >( imageRangeCalculator->GetMaximum() ) );
392 
393  std::cout << "Image output range will be: " << intensityRescaler->GetOutputMinimum()
394  << " to " << intensityRescaler->GetOutputMaximum() << std::endl;
395 
396  intensityRescaler->SetInput( flImage );
397 
398  intensityRescaler->UpdateLargestPossibleRegion();
399 
400  image = intensityRescaler->GetOutput();
401  image->DisconnectPipeline();
402 
403 
404 
405  return true; // This is a raw mammogram that has been converted
406 }
407 
408 } // end namespace itk
409 
410 #endif /* __itkCreatePositiveMammogram_h */
itk::MetaDataObject< std::string > MetaDataStringType
Definition: niftkAnonymiseDICOMImages.cxx:52
bool ConvertMammogramFromRawToPresentation(typename TImage::Pointer &image, itk::MetaDataDictionary &dictionary)
Convert a raw DICOM mammogram to a presentation version by log inverting it.
Definition: itkCreatePositiveMammogram.h:213
GLenum GLsizei GLenum GLenum const GLvoid * image
Definition: glew.h:4052
Definition: niftkITKAffineResampleImage.cxx:74
void CreatePositiveMammogram(typename TImage::Pointer &image, itk::MetaDataDictionary &dictionary, bool flgInvert=false)
Create a positive version of a DICOM mammogram.
Definition: itkCreatePositiveMammogram.h:121
itk::MetaDataDictionary DictionaryType
Definition: niftkAnonymiseDICOMImages.cxx:51
GLuint GLuint end
Definition: glew.h:1237
void SetTag(itk::MetaDataDictionary &dictionary, std::string tagID, std::string newTagValue)
Definition: itkCreatePositiveMammogram.h:39
Invert intensity of an image.
Definition: itkInvertIntensityBetweenMaxAndMinImageFilter.h:87
GLsizei const GLfloat * value
Definition: glew.h:1833
void ModifyTag(itk::MetaDataDictionary &dictionary, std::string tagID, std::string newTagValue)
Definition: itkCreatePositiveMammogram.h:82
Computes the vcl_log(x) pixel-wise of non-zero intensities leaving zero-valued pixels unchanged...
Definition: itkLogNonZeroIntensitiesImageFilter.h:57
itk::Image< float, 3 > FloatImageType
Definition: niftkKNDoubleWindowBSI.cxx:56
GLsizei const GLcharARB ** string
Definition: glew.h:5194