1 /*=========================================================================
2  *
3  *  Copyright Insight Software Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18 #ifndef itkLabelMapOverlayImageFilter_h
19 #define itkLabelMapOverlayImageFilter_h
20 
21 #include "itkLabelMapFilter.h"
22 #include "itkLabelOverlayFunctor.h"
23 #include "itkRGBPixel.h"
24 
25 namespace itk {
26 
27 /** \class LabelMapOverlayImageFilter
28 * \brief Apply a colormap to a label map and superimpose it on an image.
29  *
30  * Apply a colormap to a label map and put it on top of the feature
31  * image. The feature image is typically the image from which the labeling was
32  * produced. Use the SetInput function to set the LabelMap, and the
33  * SetFeatureImage function to set the feature image.
34  *
35  * The set of colors is a good selection of distinct colors. The opacity of
36  * the label map can be defined by the user.
37  * A background label produce a gray pixel with the same intensity
38  * than the input one.
39  *
40  * \author Gaetan Lehmann. Biologie du Developpement et de la Reproduction, INRA de Jouy-en-Josas, France.
41  *
42  * This implementation was taken from the Insight Journal paper:
43  * https://hdl.handle.net/1926/584  or
44  * http://www.insight-journal.org/browse/publication/176
45  *
46  * \sa LabelOverlayImageFilter, LabelOverlayFunctor
47  * \sa LabelMapToRGBImageFilter, LabelMapToBinaryImageFilter, LabelMapToLabelImageFilter
48  * \ingroup ImageEnhancement  MathematicalMorphologyImageFilters
49  * \ingroup ITKImageFusion
50 */
51 template<typename TLabelMap, typename TFeatureImage, typename TOutputImage=Image< RGBPixel< typename TFeatureImage::PixelType >, TFeatureImage::ImageDimension > >
52 class ITK_TEMPLATE_EXPORT LabelMapOverlayImageFilter :
53     public LabelMapFilter<TLabelMap, TOutputImage>
54 {
55 public:
56   ITK_DISALLOW_COPY_AND_ASSIGN(LabelMapOverlayImageFilter);
57 
58   /** Standard class type aliases. */
59   using Self = LabelMapOverlayImageFilter;
60   using Superclass = LabelMapFilter<TLabelMap, TOutputImage>;
61   using Pointer = SmartPointer<Self>;
62   using ConstPointer = SmartPointer<const Self>;
63 
64   /** Some convenient type alias. */
65   using LabelMapType = TLabelMap;
66   using LabelMapPointer = typename LabelMapType::Pointer;
67   using LabelMapConstPointer = typename LabelMapType::ConstPointer;
68   using LabelMapRegionType = typename LabelMapType::RegionType;
69   using LabelMapPixelType = typename LabelMapType::PixelType;
70   using LabelObjectType = typename LabelMapType::LabelObjectType;
71   using LabelType = typename LabelObjectType::LabelType;
72   using LengthType = typename LabelObjectType::LengthType;
73 
74   using FeatureImageType = TFeatureImage;
75   using FeatureImagePointer = typename FeatureImageType::Pointer;
76   using FeatureImageConstPointer = typename FeatureImageType::ConstPointer;
77   using FeatureImageRegionType = typename FeatureImageType::RegionType;
78   using FeatureImagePixelType = typename FeatureImageType::PixelType;
79 
80   using OutputImageType = TOutputImage;
81   using OutputImagePointer = typename OutputImageType::Pointer;
82   using OutputImageConstPointer = typename OutputImageType::ConstPointer;
83   using OutputImageRegionType = typename OutputImageType::RegionType;
84   using OutputImagePixelType = typename OutputImageType::PixelType;
85   using IndexType = typename OutputImageType::IndexType;
86   using SizeType = typename OutputImageType::SizeType;
87   using RegionType = typename OutputImageType::RegionType;
88 
89   using FunctorType = typename Functor::LabelOverlayFunctor<FeatureImagePixelType, LabelMapPixelType, OutputImagePixelType>;
90 
91   /** ImageDimension constants */
92   static constexpr unsigned int InputImageDimension = TLabelMap::ImageDimension;
93   static constexpr unsigned int OutputImageDimension = TOutputImage::ImageDimension;
94   static constexpr unsigned int ImageDimension = TOutputImage::ImageDimension;
95 
96   /** Standard New method. */
97   itkNewMacro(Self);
98 
99   /** Runtime information support. */
100   itkTypeMacro(LabelMapOverlayImageFilter,
101                ImageToImageFilter);
102 
103    /** Set the feature image */
SetFeatureImage(const TFeatureImage * input)104   void SetFeatureImage(const TFeatureImage *input)
105     {
106     // Process object is not const-correct so the const casting is required.
107     this->SetNthInput( 1, const_cast<TFeatureImage *>(input) );
108     }
109 
110   /** Get the feature image */
GetFeatureImage()111   const FeatureImageType * GetFeatureImage()
112     {
113     return static_cast<FeatureImageType*>((this->ProcessObject::GetInput(1)));
114     }
115 
116    /** Set the input image */
SetInput1(const TLabelMap * input)117   void SetInput1(const TLabelMap *input)
118     {
119     this->SetInput( input );
120     }
121 
122   /** Set the feature image */
SetInput2(const TFeatureImage * input)123   void SetInput2(const TFeatureImage *input)
124     {
125     this->SetFeatureImage( input );
126     }
127 
128   /** Set/Get the opacity of the colored label image. The value must be
129    * between 0 and 1
130    */
131   itkSetMacro( Opacity, double );
132   itkGetConstReferenceMacro( Opacity, double );
133 
134   /** Set/Get the overlay functor - defaults to a reasonable set of colors.
135    * This can be used to apply a different colormap.
136    */
SetFunctor(const FunctorType & functor)137   virtual void SetFunctor(const FunctorType& functor)
138   {
139     if ( m_Functor != functor )
140       {
141       m_Functor = functor;
142       this->Modified();
143       }
144   }
GetFunctor()145   FunctorType &       GetFunctor() { return m_Functor; }
GetFunctor()146   const FunctorType & GetFunctor() const { return m_Functor; }
147 
148 protected:
149   LabelMapOverlayImageFilter();
150   ~LabelMapOverlayImageFilter() override = default;
151 
152   /** LabelMapOverlayImageFilter needs the entire input be
153    * available. Thus, it needs to provide an implementation of
154    * GenerateInputRequestedRegion(). */
155   void GenerateInputRequestedRegion() override;
156 
157   /** LabelMapOverlayImageFilter will produce the entire output. */
158   void EnlargeOutputRequestedRegion(DataObject *itkNotUsed(output)) override;
159 
160   void GenerateData() override;
161 
162   void DynamicThreadedGenerateData(const OutputImageRegionType & outputRegionForThread) override;
163 
164   //part of a compile error workaround for GCC 4.8.5-28 (Red Hat) from 20150623
SuperclassDynamicTGD(const OutputImageRegionType & outputRegion)165   void SuperclassDynamicTGD(const OutputImageRegionType & outputRegion)
166   {
167     Superclass::DynamicThreadedGenerateData(outputRegion);
168   }
169 
170   void ThreadedProcessLabelObject( LabelObjectType * labelObject ) override;
171 
172   void GenerateOutputInformation() override;
173 
174   void PrintSelf(std::ostream& os, Indent indent) const override;
175 
176 private:
177   double                    m_Opacity;
178   FunctorType               m_Functor;
179 
180 }; // end of class
181 
182 } // end namespace itk
183 
184 #ifndef ITK_MANUAL_INSTANTIATION
185 #include "itkLabelMapOverlayImageFilter.hxx"
186 #endif
187 
188 #endif
189