19 using ImageDataType = uint32_t;
25 class BinaryImage :
public Grid
29 explicit BinaryImage(
const Eigen::Matrix<size_t,-1,1>& size,
const Vector& dx,
const Vector& origin)
30 : BinaryImage(size, dx, origin, Eigen::
Matrix<int,-1,1>::Zero(N))
33 explicit BinaryImage(
const Eigen::Matrix<size_t,-1,1>& size,
const Vector& dx,
const Vector& origin,
const Eigen::Matrix<int,-1,1>& local_shift)
34 : Grid(dx, origin, local_shift), _size(size)
36 assert_release(size.size() == N);
37 assert_release(all_same_size(size, dx, origin, local_shift));
39 _array_offsets[0] = 1;
40 for(Index i = 1 ; i < (Index)N ; i++)
42 _array_offsets[i] = _array_offsets[i-1]*_size[i-1];
44 _data.resize(_array_offsets[i]*_size[i], 0);
48 BinaryImage(
const std::string& file,
bool load_data =
true)
49 : Grid(), _file_name(file)
52 f.open(file, std::ios::binary);
54 throw std::runtime_error(
"Unable to load BinaryImage: " + file);
61 assert(_size.size() == N);
62 assert(all_same_size(_size, _dx, _origin, _local_shift));
64 BinaryImage<N>::_data_start_pos = f.tellg();
74 assert(BinaryImage<N>::_data_start_pos > 0);
77 f.open(_file_name, std::ios::binary);
79 throw std::runtime_error(
"Unable to load BinaryImage: " + _file_name);
84 size_t nb_voxels()
const
86 size_t data_size = _size[0];
87 for(Index i = 1 ; i < _size.size() ; i++) data_size *= _size[i];
91 void load_data(std::ifstream& f)
93 f.seekg(BinaryImage<N>::_data_start_pos, f.beg);
94 size_t data_size = nb_voxels();
98 _data.resize(data_size);
99 for(
size_t i = 0 ; i < data_size ; i++)
100 f.read((
char*)&_data[i],
sizeof(ImageDataType));
101 assert(_data.size() == data_size);
110 bool data_has_been_loaded()
const
112 return !_data.empty() || nb_voxels() == 0;
116 const Eigen::Matrix<size_t,N,1>& size()
const
121 void serialize()
const
123 serialize(_file_name);
126 void serialize(
const std::string& file)
const
130 f.open(file, std::ios::binary);
132 throw std::runtime_error(
"Unable to serialize: " + file);
138 f.write(
reinterpret_cast<const char*
>(_data.data()),
sizeof(ImageDataType)*_data.size());
146 auto g = Grid::to_grid(x);
148 for(
size_t i = 0 ; i < dim() ; i++)
149 if(x[i].
ub() == real_box()[i].
ub())
151 double last = local_indices_box()[i].ub();
152 g[i] = Interval(std::min(g[i].
lb(),last),last);
158 ImageDataType& operator()(
const std::array<int,N>& x)
160 return const_cast<ImageDataType&
>(
static_cast<const BinaryImage<N>&
>(*this).operator()(x));
163 const ImageDataType& operator()(
const std::array<int,N>& x)
const
165 if(*std::min_element(std::begin(x),std::end(x)) < 0)
168 assert(local_indices_box().
contains(to_vector<N>(x)));
169 size_t array_index = _array_offsets[0]*x[0];
170 for(
size_t i = 1 ; i < N ; i++)
171 array_index += _array_offsets[i]*x[i];
173 assert(array_index < _data.size());
174 return _data[array_index];
177 GridBox local_indices_box()
const
179 GridBox b(_size.size());
180 for(Index i = 0 ; i < _size.size() ; i++)
182 b[i] = { 0, _size[i]-1. };
184 assert(b.has_integer_bounds());
188 GridBox absolute_indices_box()
const
190 GridBox i = GridBox(Grid::local_shift().
template cast<double>()) + local_indices_box();
191 assert(i.has_integer_bounds());
197 return to_reals(local_indices_box());
200 void convert_as_integrale_img()
202 static_assert((N == 2 || N == 3) &&
"dim > 3 cases are not handled");
208 if(_computed_as_integrale)
210 _computed_as_integrale =
true;
214 for(
int i = 0 ; i < (int)_size[0] ; i++)
215 for(
int j = 0 ; j < (int)_size[1] ; j++)
217 uint64_t s = (*this)({i-1,j}) + (*
this)({i,j-1}) + (*
this)({i,j}) - (*
this)({i-1,j-1});
218 assert(s < std::numeric_limits<ImageDataType>::max());
219 (*this)({i,j}) = (ImageDataType)s;
223 else if constexpr(N == 3)
225 for(
int i = 0 ; i < (int)_size[0] ; i++)
226 for(
int j = 0 ; j < (int)_size[1] ; j++)
227 for(
int k = 0 ; k < (int)_size[2] ; k++)
229 uint64_t s = (*this)({i-1,j,k}) + (*
this)({i,j-1,k}) + (*
this)({i,j,k-1})
230 + (*
this)({i-1,j-1,k-1}) + (*
this)({i,j,k}) - (*
this)({i-1,j,k-1})
231 - (*
this)({i,j-1,k-1}) - (*
this)({i-1,j-1,k});
232 assert(s < std::numeric_limits<ImageDataType>::max()
233 &&
"integrale value exceeds the maximum value of ImageDataType");
234 (*this)({i,j,k}) = (ImageDataType)s;
239 void contract_indices(GridBox& x)
const
241 assert(x.has_integer_bounds());
242 if(_data.size() == 0 || !x.is_subset(local_indices_box()) || x.is_empty())
245 assert(data_has_been_loaded());
247 if(nb_pixels_in(x) == 0)
255 for(
size_t k = 0 ; k < N ; k++)
260 a = x[k].lb(); b = x[k].ub();
262 int i = std::floor((a+b)/2.);
263 x_[k] = Interval(x[k].
lb(),i);
264 if(nb_pixels_in(x_) == 0)
269 x[k] = Interval(a,x[k].
ub());
271 a = x[k].lb(); b = x[k].ub();
273 int i = std::ceil((a+b)/2.);
274 x_[k] = Interval(i,x[k].
ub());
275 if(nb_pixels_in(x_) == 0)
280 x[k] = Interval(x[k].
lb(),a);
285 for(
size_t k = 0 ; k < N ; k++)
287 int imin = x[k].lb(), imax = x[k].ub();
288 for(
auto i = imin ; i <= imax ; i++)
291 x_[k] = Interval(imin,i);
292 if(nb_pixels_in(x_) > 0)
298 x[k] = Interval(imin,imax);
300 for(
auto i = imax ; i >= imin ; i--)
303 x_[k] = Interval(i,imax);
304 if(nb_pixels_in(x_) > 0)
310 x[k] = Interval(imin,imax);
316 unsigned int nb_pixels_in(
const GridBox& x)
const
318 assert(x.has_integer_bounds());
319 assert(_computed_as_integrale &&
"conversion must be done beforehand");
320 assert(!local_indices_box().
is_empty());
321 assert(!x.is_unbounded());
325 int xmin = x[0].lb(), xmax = x[0].ub();
326 int ymin = x[1].lb(), ymax = x[1].ub();
328 unsigned int n1 = (*this)({xmax, ymax });
329 unsigned int n2 = (*this)({xmax, ymin-1});
330 unsigned int n3 = (*this)({xmin-1, ymax });
331 unsigned int n4 = (*this)({xmin-1, ymin-1});
336 else if constexpr(N == 3)
338 int xmin = x[0].lb(), xmax = x[0].ub();
339 int ymin = x[1].lb(), ymax = x[1].ub();
340 int zmin = x[2].lb(), zmax = x[2].ub();
342 unsigned int n8 = (*this)({xmax, ymax, zmax });
343 unsigned int n5 = (*this)({xmin-1, ymin-1, zmax });
344 unsigned int n6 = (*this)({xmin-1, ymax, zmax });
345 unsigned int n7 = (*this)({xmax, ymin-1, zmax });
346 unsigned int n4 = (*this)({xmax, ymax, zmin-1});
347 unsigned int n1 = (*this)({xmin-1, ymin-1, zmin-1});
348 unsigned int n2 = (*this)({xmin-1, ymax, zmin-1});
349 unsigned int n3 = (*this)({xmax, ymin-1, zmin-1});
351 return (n8+n5-n6-n7)-(n4+n1-n2-n3);
355 static_assert(N >= 2 && N <= 3 &&
"dim > 3 cases are not handled");
360 std::string _file_name;
361 bool _computed_as_integrale =
false;
363 Eigen::Matrix<size_t,N,1> _size, _array_offsets;
364 std::vector<ImageDataType> _data;
365 ImageDataType _zero = 0;
367 inline static std::streampos _data_start_pos = -1;
bool is_empty() const
Checks whether the interval matrix is empty.
Definition codac2_MatrixBase_addons_IntervalMatrixBase.h:56
bool contains(const Matrix< double, RowsAtCompileTime, ColsAtCompileTime > &x) const
Checks if this interval matrix contains the specified matrix x.
Definition codac2_MatrixBase_addons_IntervalMatrixBase.h:408
auto ub() const
Returns a matrix containing the upper bounds of each interval element.
Definition codac2_MatrixBase_addons_IntervalMatrixBase.h:103
auto lb() const
Returns a matrix containing the lower bounds of each interval element.
Definition codac2_MatrixBase_addons_IntervalMatrixBase.h:91
Definition codac2_OctaSym.h:21
Eigen::Matrix< double,-1, 1 > Vector
Alias for a dynamically-sized column vector of doubles.
Definition codac2_Vector.h:24
void serialize(std::ostream &f, const T &x)
Writes the binary representation of a trivially copyable object to the given output stream.
Definition codac2_serialization.h:35
Eigen::Matrix< Interval,-1, 1 > IntervalVector
Alias for a dynamic-size column vector of intervals.
Definition codac2_IntervalVector.h:25
Eigen::Matrix< double,-1,-1 > Matrix
Alias for a dynamic-size matrix of doubles.
Definition codac2_Matrix.h:26
void deserialize(std::istream &f, T &x)
Reads the binary representation of a trivially copyable object from the given input stream.
Definition codac2_serialization.h:55