File: SegmentationUpdateIterator.h

package info (click to toggle)
itksnap 3.6.0-5
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 22,132 kB
  • sloc: cpp: 91,089; ansic: 1,994; sh: 327; makefile: 16
file content (287 lines) | stat: -rw-r--r-- 7,628 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
/*=========================================================================

  Program:   ITK-SNAP
  Module:    $RCSfile: GenericImageData.h,v $
  Language:  C++
  Date:      $Date: 2009/08/29 23:02:43 $
  Version:   $Revision: 1.11 $
  Copyright (c) 2007 Paul A. Yushkevich

  This file is part of ITK-SNAP

  ITK-SNAP is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.

  -----

  Copyright (c) 2003 Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

  -----

  Copyright (c) 2003 Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

  This software is distributed WITHOUT ANY WARRANTY; without even
  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#ifndef __SegmentationUpdateIterator_h_
#define __SegmentationUpdateIterator_h_

#include "SNAPCommon.h"
#include "ImageWrapperTraits.h"
#include "UndoDataManager.h"


/**
 * \class SegmentationUpdate
 * \brief This class handles updates to the segmentation image at a high level.
 */
class SegmentationUpdateIterator
{
public:
  typedef itk::Index<3>                                        IndexType;
  typedef itk::ImageRegion<3>                                  RegionType;
  typedef LabelImageWrapper::ImageType                         LabelImageType;
  typedef itk::ImageRegionIterator<LabelImageType>             LabelIteratorType;

  typedef UndoDataManager<LabelType>::Delta                    UndoDelta;

  enum UpdateType {
    FOREGROUND, BACKGROUND, SKIP
  };

  SegmentationUpdateIterator(LabelImageType *labelImage,
                             const RegionType &region,
                             LabelType active_label,
                             DrawOverFilter draw_over)
    : m_Region(region),
      m_ActiveLabel(active_label),
      m_DrawOver(draw_over),
      m_Iterator(labelImage, region),
      m_ChangedVoxels(0)
  {
    // Create the delta
    m_Delta = new UndoDelta();
    m_Delta->SetRegion(region);

    // Set the voxel delta to zero
    m_VoxelDelta = 0;
  }

  ~SegmentationUpdateIterator()
  {
    if(m_Delta)
      delete m_Delta;
  }

  void operator ++()
  {
    // Encode the current voxel delta
    m_Delta->Encode(m_VoxelDelta);
    m_VoxelDelta = 0;

    // Keep track of changed voxels
    if(m_VoxelDelta != 0)
      m_ChangedVoxels++;

    // Update the internal iterator
    ++m_Iterator;
  }

  const IndexType GetIndex()
  {
    return m_Iterator.GetIndex();
  }

  /**
   * Paint with a specified label - respecting the draw-over mask
   */
  virtual void PaintLabel(LabelType new_label)
  {
    LabelType lOld = m_Iterator.Get();

    if(m_DrawOver.CoverageMode == PAINT_OVER_ALL ||
       (m_DrawOver.CoverageMode == PAINT_OVER_ONE && lOld == m_DrawOver.DrawOverLabel) ||
       (m_DrawOver.CoverageMode == PAINT_OVER_VISIBLE && lOld != 0))
      {
      if(lOld != new_label)
        {
        m_VoxelDelta += new_label - lOld;
        m_Iterator.Set(new_label);
        m_ChangedVoxels++;
        }
      }
  }


  /**
   * Default painting mode - applies active label using the current draw over mask
   */
  void PaintAsForeground()
  {
    this->PaintLabel(m_ActiveLabel);
  }

  /**
   * Similar but clear label is not affected (used in cutplane mode)
   */
  void PaintAsForegroundPreserveClear()
  {
    LabelType lOld = m_Iterator.Get();
    if(lOld == 0)
      return;

    if(m_DrawOver.CoverageMode == PAINT_OVER_ALL ||
       (m_DrawOver.CoverageMode == PAINT_OVER_ONE && lOld == m_DrawOver.DrawOverLabel) ||
       (m_DrawOver.CoverageMode == PAINT_OVER_VISIBLE && lOld != 0))
      {
      if(lOld != m_ActiveLabel)
        {
        m_VoxelDelta += m_ActiveLabel - lOld;
        m_Iterator.Set(m_ActiveLabel);
        m_ChangedVoxels++;
        }
      }
  }



  /**
   * Reverse painting mode - applies clear label over active label (paintbrush RMB click)
   */
  void PaintAsBackground()
  {
    LabelType lOld = m_Iterator.Get();

    if(m_ActiveLabel != 0 && lOld == m_ActiveLabel)
      {
      m_VoxelDelta += 0 - lOld;
      m_Iterator.Set(0);
      m_ChangedVoxels++;
      }
  }

  /**
   * More general method, replaces label with new_label if current label matches target_label,
   * does not take into account Active/DrawOver state
   */
  void ReplaceLabel(LabelType target_label, LabelType new_label)
  {
    LabelType lOld = m_Iterator.Get();

    if(lOld == target_label)
      {
      m_VoxelDelta += new_label - lOld;
      m_Iterator.Set(new_label);
      m_ChangedVoxels++;
      }
  }

  /**
   * A more funky paint method, applies the following test, where X is the
   * label at the voxel
   *
   * if(X != A and X \in DrawOver)
   *   X = B
   */
  void PaintLabelWithExtraProtection(LabelType protect_label, LabelType new_label)
  {
    LabelType lOld = m_Iterator.Get();

    // Test for protection or empty operation
    if(lOld == protect_label || lOld == new_label)
      return;

    // Apply the draw over test
    if(m_DrawOver.CoverageMode == PAINT_OVER_ALL ||
       (m_DrawOver.CoverageMode == PAINT_OVER_ONE && lOld == m_DrawOver.DrawOverLabel) ||
       (m_DrawOver.CoverageMode == PAINT_OVER_VISIBLE && lOld != 0))
      {
      m_VoxelDelta += new_label - lOld;
      m_Iterator.Set(new_label);
      m_ChangedVoxels++;
      }
  }


  bool IsAtEnd()
  {
    return m_Iterator.IsAtEnd();
  }

  /**
   * Call this method at the end of the iteration to finish encoding. This will also set the
   * modified flag of the label image if there were any actual updates.
   */
  void Finalize()
  {
    m_Delta->FinishEncoding();
    if(m_ChangedVoxels > 0)
      m_Iterator.GetImage()->Modified();
  }

  // Keep delta from being deleted
  UndoDelta *RelinquishDelta()
  {
    UndoDelta *delta = m_Delta;
    m_Delta = NULL;
    return delta;
  }

  // Get the number of changed voxels
  unsigned long GetNumberOfChangedVoxels() const
  {
    return m_ChangedVoxels;
  }

  // Get the pointer to the detla
  UndoDelta *GetDelta() const
  {
    return m_Delta;
  }

protected:

  // Name of the segmentation update (for undo tracking)
  std::string m_Title;

  // Region over which update is performed
  RegionType m_Region;

  // Active label for the registration update
  LabelType m_ActiveLabel;

  // Coverage mode
  DrawOverFilter m_DrawOver;

  // RLE encoding of the segmentation update - for storing undo/redo points
  UndoDelta *m_Delta;

  // Iterator used internally
  LabelIteratorType m_Iterator;

  // Delta at the current location
  LabelType m_VoxelDelta;

  // Number of voxels actually modified
  unsigned long m_ChangedVoxels;
};


#endif // SegmentationUpdateIterator