SMIL  1.0.4
DBlob.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''
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #ifndef _D_BLOB_HPP
31 #define _D_BLOB_HPP
32 
33 #include "Core/include/private/DImage.hpp"
34 #include <map>
35 
36 namespace smil
37 {
63  struct PixelSequence {
64  size_t offset;
65  size_t size;
66  PixelSequence() : offset(0), size(0)
67  {
68  }
69  ~PixelSequence()
70  {
71  }
72  PixelSequence(size_t off, size_t siz) : offset(off), size(siz)
73  {
74  }
75  };
76 
82  struct Blob {
83  vector<PixelSequence> sequences;
84  typedef vector<PixelSequence>::iterator sequences_iterator;
85  typedef vector<PixelSequence>::const_iterator sequences_const_iterator;
86  typedef vector<PixelSequence>::const_reverse_iterator
87  sequences_const_reverse_iterator;
88  };
89 
97  template <class T>
98  map<T, Blob> computeBlobs(const Image<T> &imIn, bool onlyNonZero = true)
99  {
100  map<T, Blob> blobs;
101 
102  ASSERT(CHECK_ALLOCATED(&imIn), RES_ERR_BAD_ALLOCATION, blobs);
103 
104  typename ImDtTypes<T>::sliceType lines = imIn.getLines();
105  typename ImDtTypes<T>::lineType pixels;
106  size_t npix = imIn.getWidth();
107  size_t nlines = imIn.getLineCount();
108 
109  T curVal;
110 
111  for (size_t l = 0; l < nlines; l++) {
112  size_t curSize = 0;
113  size_t curStart = l * npix;
114 
115  pixels = lines[l];
116  curVal = pixels[0];
117  if (curVal != 0 || !onlyNonZero)
118  curSize++;
119 
120  for (size_t i = 1; i < npix; i++) {
121  if (pixels[i] == curVal)
122  curSize++;
123  else {
124  if (curVal != 0 || !onlyNonZero)
125  blobs[curVal].sequences.push_back(PixelSequence(curStart, curSize));
126  curStart = i + l * npix;
127  curSize = 1;
128  curVal = pixels[i];
129  }
130  }
131  if (curVal != 0 || !onlyNonZero)
132  blobs[curVal].sequences.push_back(PixelSequence(curStart, curSize));
133  }
134 
135  return blobs;
136  }
137 
150  template <class labelT, class T>
151  RES_T drawBlobs(map<labelT, Blob> &blobs, Image<T> &imOut,
152  T blobsValue = ImDtTypes<T>::max(), bool fillFirst = true,
153  T defaultValue = T(0))
154  {
155  ASSERT_ALLOCATED(&imOut);
156 
157  ImageFreezer freeze(imOut);
158 
159  if (fillFirst)
160  ASSERT(fill(imOut, defaultValue) == RES_OK);
161 
162  typename ImDtTypes<T>::lineType pixels = imOut.getPixels();
163  size_t pixCount = imOut.getPixelCount();
164  bool allBlobsFit = true;
165 
166  typename map<labelT, Blob>::const_iterator blob_it;
167  for (blob_it = blobs.begin(); blob_it != blobs.end(); blob_it++) {
168  // Verify that the blob can fit in the image
169  Blob::sequences_const_reverse_iterator last =
170  blob_it->second.sequences.rbegin();
171  if ((*last).offset + (*last).size > pixCount) {
172  allBlobsFit = false;
173  } else {
174  Blob::sequences_const_iterator it = blob_it->second.sequences.begin();
175  Blob::sequences_const_iterator it_end = blob_it->second.sequences.end();
176 
177  T outVal = blobsValue != defaultValue ? blobsValue : blob_it->first;
178  for (; it != it_end; it++) {
179  typename ImDtTypes<T>::lineType line = pixels + (*it).offset;
180  for (size_t i = 0; i < it->size; i++)
181  line[i] = outVal;
182  }
183  }
184  }
185  imOut.modified();
186 
187  ASSERT(allBlobsFit, "Some blobs are outside the image", RES_ERR);
188 
189  return RES_OK;
190  }
191 
202  template <class labelT, class T>
203  RES_T drawBlobs(map<labelT, Blob> &blobs, map<labelT, T> &lut,
204  Image<T> &imOut, bool fillFirst = true, T defaultValue = T(0))
205  {
206  ASSERT_ALLOCATED(&imOut);
207 
208  ImageFreezer freeze(imOut);
209 
210  if (fillFirst)
211  ASSERT(fill(imOut, defaultValue) == RES_OK);
212 
213  typename ImDtTypes<T>::lineType pixels = imOut.getPixels();
214  size_t pixCount = imOut.getPixelCount();
215  bool allBlobsFit = true;
216 
217  typename map<labelT, Blob>::const_iterator blob_it;
218  for (blob_it = blobs.begin(); blob_it != blobs.end(); blob_it++) {
219  // Verify that the blob can fit in the image
220  Blob::sequences_const_reverse_iterator last =
221  blob_it->second.sequences.rbegin();
222  if ((*last).offset + (*last).size > pixCount) {
223  allBlobsFit = false;
224  } else {
225  Blob::sequences_const_iterator it = blob_it->second.sequences.begin();
226  Blob::sequences_const_iterator it_end = blob_it->second.sequences.end();
227 
228  typename map<labelT, T>::const_iterator valIt =
229  lut.find(blob_it->first);
230  T outVal = valIt != lut.end() ? valIt->second : defaultValue;
231  for (; it != it_end; it++) {
232  typename ImDtTypes<T>::lineType line = pixels + (*it).offset;
233  for (size_t i = 0; i < it->size; i++)
234  line[i] = outVal;
235  }
236  }
237  }
238  imOut.modified();
239 
240  ASSERT(allBlobsFit, "Some blobs are outside the image", RES_ERR);
241 
242  return RES_OK;
243  }
244 
255  template <class labelT>
256  int getBlobIDFromOffset(map<labelT, Blob> &blobs, size_t offset)
257  {
258  int id = 0;
259 
260  typename map<labelT, Blob>::const_iterator blob_it;
261  typedef typename Blob::sequences_const_iterator seqit_t;
262 
263  for (blob_it = blobs.begin(); blob_it != blobs.end(); blob_it++) {
264  seqit_t it_end = blob_it->second.sequences.end();
265 
266  for(seqit_t it = blob_it->second.sequences.begin(); it != it_end; it++)
267  {
268  if (offset >= it->offset && offset < it->offset + it->size)
269  id = blob_it->first;
270  }
271  if (id > 0)
272  break;
273  }
274 
275  return id;
276  }
277 
289  template <class labelT, class T>
290  int getBlobIDFromOffset(Image<T> imIn, map<labelT, Blob> &blobs, int x, int y, int z = 0)
291  {
292  int id = 0;
293 
294  size_t offset = imIn.getOffsetFromCoords(x, y, z);
295 
296  typename map<labelT, Blob>::const_iterator blob_it;
297  typedef typename Blob::sequences_const_iterator seqit_t;
298 
299  for (blob_it = blobs.begin(); blob_it != blobs.end(); blob_it++) {
300  seqit_t it_end = blob_it->second.sequences.end();
301 
302  for(seqit_t it = blob_it->second.sequences.begin(); it != it_end; it++)
303  {
304  if (offset >= it->offset && offset < it->offset + it->size)
305  id = blob_it->first;
306  }
307  if (id > 0)
308  break;
309  }
310 
311  return id;
312  }
313 
316 } // namespace smil
317 
318 #endif // _D_BASE_MEASURE_OPERATIONS_HPP
size_t getOffsetFromCoords(size_t x, size_t y, size_t z=0) const
Get an offset for given x,y(,z) coordinates.
Definition: DBaseImage.h:263
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:80
size_t getLineCount() const
Get the number of lines.
Definition: DBaseImage.h:165
Definition: DBaseImage.h:386
Main Image class.
Definition: DImage.hpp:57
sliceType getLines() const
Get an array containing the start offset of each line.
Definition: DImage.hpp:111
RES_T fill(Image< T > &imOut, const T &value)
fill() - Fill an image with a given value.
Definition: DImageArith.hpp:1456
int getBlobIDFromOffset(Image< T > imIn, map< labelT, Blob > &blobs, int x, int y, int z=0)
getBlobIDFromOffset() - get the blob ID which contains a pixel (or voxel) given its coordinates
Definition: DBlob.hpp:290
map< T, Blob > computeBlobs(const Image< T > &imIn, bool onlyNonZero=true)
Create a map of blobs from a labeled image.
Definition: DBlob.hpp:98
RES_T drawBlobs(map< labelT, Blob > &blobs, map< labelT, T > &lut, Image< T > &imOut, bool fillFirst=true, T defaultValue=T(0))
Represent Blobs in an image with a lookup map.
Definition: DBlob.hpp:203
List of offset and size of line contiguous pixels.
Definition: DBlob.hpp:82
Definition: DTypes.hpp:88
Start offset and length of pixels in an image.
Definition: DBlob.hpp:63