SMIL  0.9.1
DSkeleton.hpp
1 /*
2  * Copyright (c) 2011-2016, Matthieu FAESSEL and ARMINES
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Matthieu FAESSEL, or ARMINES nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 
30 #ifndef _D_SKELETON_HPP
31 #define _D_SKELETON_HPP
32 
33 #include "DMorphoBase.hpp"
34 #include "DHitOrMiss.hpp"
35 
36 namespace smil
37 {
50  template <class T>
51  RES_T skiz(const Image<T> &imIn, Image<T> &imOut)
52  {
53  ASSERT_ALLOCATED(&imIn, &imOut);
54  ASSERT_SAME_SIZE(&imIn, &imOut);
55 
56  ImageFreezer freezer(imOut);
57  Image<T> tmpIm(imIn);
58  inv(imIn, imOut);
59  fullThin(imOut, HMT_hL(6), tmpIm);
60  fullThin(tmpIm, HMT_hM(6), imOut);
61 
62  return RES_OK;
63  }
64 
68  template <class T>
69  RES_T skeleton(const Image<T> &imIn, Image<T> &imOut, const StrElt &se=DEFAULT_SE)
70  {
71  ASSERT_ALLOCATED(&imIn, &imOut);
72  ASSERT_SAME_SIZE(&imIn, &imOut);
73 
74  ImageFreezer freezer(imOut);
75 
76  Image<T> imEro(imIn);
77  Image<T> imTemp(imIn);
78 
79  copy(imIn, imEro);
80  fill(imOut, ImDtTypes<T>::min());
81 
82  bool idempt = false;
83 
84  do
85  {
86  erode(imEro, imEro, se);
87  open(imEro, imTemp, se);
88  sub(imEro, imTemp, imTemp);
89  sup(imOut, imTemp, imTemp);
90  idempt = equ(imTemp, imOut);
91  copy(imTemp, imOut);
92 
93  } while (!idempt);
94  return RES_OK;
95  }
96 
100  template <class T1, class T2>
101  RES_T extinctionValues(const Image<T1> &imIn, Image<T2> &imOut, const StrElt &se=DEFAULT_SE)
102  {
103  ASSERT_ALLOCATED(&imIn, &imOut);
104  ASSERT_SAME_SIZE(&imIn, &imOut);
105 
106  ImageFreezer freezer(imOut);
107 
108  Image<T1> imEro(imIn);
109  Image<T1> imTemp1(imIn);
110  Image<T2> imTemp2(imOut);
111 
112  copy(imIn, imEro);
113  fill(imOut, ImDtTypes<T2>::min());
114 
115  T2 r = 1;
116 
117  bool idempt = false;
118 
119  do
120  {
121  erode(imEro, imEro, se);
122  open(imEro, imTemp1, se);
123  sub(imEro, imTemp1, imTemp1);
124  test(imTemp1, r++, imOut, imTemp2);
125  idempt = equ(imTemp2, imOut);
126  copy(imTemp2, imOut);
127 
128  } while (!idempt);
129  return RES_OK;
130  }
131 
132 
138  template <class T>
139  RES_T zhangSkeleton(const Image<T> &imIn, Image<T> &imOut)
140  {
141  size_t w = imIn.getWidth();
142  size_t h = imIn.getHeight();
143 
144  // Create a copy image with a border to avoid border checks
145  size_t width=w+2, height=h+2;
146  Image<T> tmpIm(width, height);
147  fill(tmpIm, ImDtTypes<T>::min());
148  copy(imIn, tmpIm, 1, 1);
149 
150  typedef typename Image<T>::sliceType sliceType;
151  typedef typename Image<T>::lineType lineType;
152 
153  // lineType tab = tmpIm.getPixels();
154  const sliceType lines = tmpIm.getLines();
155  lineType curLine;
156  lineType curPix;
157 
158  bool ptsDeleted;
159  bool goOn;
160  bool oddIter = false;
161  UINT nbrTrans, nbrNonZero;
162 
163  int iWidth = width;
164  int ngbOffsets[9] = { -iWidth-1, -iWidth, -iWidth+1, 1, iWidth+1, iWidth, iWidth-1, -1, -iWidth-1 };
165 
166  do
167  {
168  oddIter = !oddIter;
169  ptsDeleted = false;
170 
171  for (size_t y=1;y<height-1;y++)
172  {
173  curLine = lines[y];
174  curPix = curLine + 1;
175  for (size_t x=1;x<width;x++,curPix++)
176  {
177  if (*curPix!=0)
178  {
179  goOn = false;
180 
181  // Calculate the number of non-zero neighbors
182  nbrNonZero = 0;
183  for (int n=0;n<8;n++)
184  if (*(curPix+ngbOffsets[n])!=0)
185  nbrNonZero++;
186 
187  if (nbrNonZero>=2 && nbrNonZero<=6)
188  goOn = true;
189 
190  if (goOn)
191  {
192  // Calculate the number of transitions in clockwise direction
193  // from point (-1,-1) back to itself
194  nbrTrans = 0;
195  for (int n=0;n<8;n++)
196  if (*(curPix+ngbOffsets[n])==0)
197  if (*(curPix+ngbOffsets[n+1])!=0)
198  nbrTrans++;
199  if (nbrTrans==1)
200  goOn = true;
201  else goOn = false;
202  }
203 
204  if (goOn)
205  {
206  if (oddIter && (*(curPix+ngbOffsets[1]) * *(curPix+ngbOffsets[3]) * *(curPix+ngbOffsets[5])!=0))
207  goOn = false;
208  else if (oddIter && (*(curPix+ngbOffsets[1]) * *(curPix+ngbOffsets[3]) * *(curPix+ngbOffsets[7])!=0))
209  goOn = false;
210  }
211  if (goOn)
212  {
213  if (oddIter && (*(curPix+ngbOffsets[3]) * *(curPix+ngbOffsets[5]) * *(curPix+ngbOffsets[7])!=0))
214  goOn = false;
215  else if (oddIter && (*(curPix+ngbOffsets[1]) * *(curPix+ngbOffsets[5]) * *(curPix+ngbOffsets[7])!=0))
216  goOn = false;
217  }
218  if (goOn)
219  {
220  *curPix = 0;
221  ptsDeleted = true;
222  }
223  }
224  }
225  }
226 
227  } while(ptsDeleted);
228 
229  copy(tmpIm, 1, 1, imOut);
230 
231  return RES_OK;
232  }
233 
236 } // namespace smil
237 
238 
239 #endif // _D_SKELETON_HPP
240 
RES_T zhangSkeleton(const Image< T > &imIn, Image< T > &imOut)
Zhang 2D skeleton.
Definition: DSkeleton.hpp:139
Definition: DColorConvert.h:38
sliceType getLines() const
Get an array containing the start offset of each line.
Definition: DImage.hpp:114
RES_T sub(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
Subtraction.
Definition: DImageArith.hpp:446
RES_T copy(const Image< T1 > &imIn, size_t startX, size_t startY, size_t startZ, size_t sizeX, size_t sizeY, size_t sizeZ, Image< T2 > &imOut, size_t outStartX=0, size_t outStartY=0, size_t outStartZ=0)
Copy image.
Definition: DImageArith.hpp:114
Definition: DBaseImage.h:235
RES_T equ(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
Equality operator.
Definition: DImageArith.hpp:572
Hexagonal M ([1], [3,4,5])
Definition: DCompositeSE.h:148
RES_T inv(const Image< T > &imIn, Image< T > &imOut)
Invert an image.
Definition: DImageArith.hpp:375
RES_T fill(Image< T > &imOut, const T &value)
Fill an image with a given value.
Definition: DImageArith.hpp:62
RES_T sup(const Image< T > &imIn1, const Image< T > &imIn2, Image< T > &imOut)
Sup of two images.
Definition: DImageArith.hpp:505
size_t getHeight() const
Get image height.
Definition: DBaseImage.h:91
Base structuring element.
Definition: DStructuringElement.h:51
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:87
Definition: DTypes.hpp:78
Main Image class.
Definition: DQVtkViewer.hpp:44
RES_T erode(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE, T borderVal=ImDtTypes< T >::max())
Morphological grayscale erosion.
Definition: DMorphoBase.hpp:101
RES_T extinctionValues(const Image< T1 > &imIn, Image< T2 > &imOut, const StrElt &se=DEFAULT_SE)
Extinction values.
Definition: DSkeleton.hpp:101
RES_T open(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Morphological grayscale opening.
Definition: DMorphoBase.hpp:159
RES_T skiz(const Image< T > &imIn, Image< T > &imOut)
Skiz by influence zones.
Definition: DSkeleton.hpp:51
RES_T fullThin(const Image< T > &imIn, const CompStrEltList &mhtSE, Image< T > &imOut)
Thinning transform (full)
Definition: DHitOrMiss.hpp:197
Hexagonal L ([1,2], [4,5])
Definition: DCompositeSE.h:127
RES_T test(const Image< T1 > &imIn1, const Image< T2 > &imIn2, const Image< T2 > &imIn3, Image< T2 > &imOut)
Test.
Definition: DImageArith.hpp:920
RES_T skeleton(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Morphological skeleton.
Definition: DSkeleton.hpp:69