brainrat-private 6.0.4
slices_d.h
Go to the documentation of this file.
1/* Copyright (C) 2000-2013 CEA
2 *
3 * This software and supporting documentation were developed by
4 * bioPICSEL
5 * CEA/DSV/I²BM/MIRCen/LMN, Batiment 61,
6 * 18, route du Panorama
7 * 92265 Fontenay-aux-Roses
8 * France
9 */
10
11#include <cartobase/object/object.h>
12#include <cartobase/stream/directory.h>
13#include <cartobase/stream/fileutil.h>
14#include <aims/io/channelR.h>
17
18
19//------------------------------------------------------------------------------
20// Utility functions
21//------------------------------------------------------------------------------
22template<class T> bool
23detectSlices(aims::Process & p, const std::string &, aims::Finder &)
24{
25 SlicesDetector & proc = (SlicesDetector &)p;
26
27 // Instanciate detector object
29 1. / proc.fraction,
32 !proc.disable_checks);
33
34// std::vector<Component> components;
35 carto::Object bounds;
36
37// float default_value = (proc.res? INCH / proc.res > 0 : 1.);
38// std::vector<float> vs(default_value, 4);
39
40 carto::VolumeRef<int16_t> vol;
41 //
42 // Read data to use for processing components
43 //
44 aims::ChannelReader<carto::VolumeRef<int16_t> > reader(proc.fileIn);
45 reader.read(vol, proc.c);
46 std::cout << "Original image loaded" << std::endl;
47
48 // Step 1: Detect components
49 std::vector<Component> components = detector.analyze(vol, proc.n, proc.res,
50 proc.lt, proc.ht);
51
52 // Step 2: Convert components to generic object that describes bounding
53 // boxes
54 bounds = detector.boundingBoxes(vol, components);
55
56// // Step 2: sort components
57// // It is necessary to first sort using 2 dimensions because images are 2d
58// if (proc.dimensionsizes.size() == 0) {
59// proc.dimensionsizes.push_back(1);
60// }
61//
62// if (proc.dimensionorders.size() == 0) {
63// proc.dimensionorders.push_back(0);
64// }
65//
66// std::vector<int32_t> columnsizes;
67// columnsizes.push_back(proc.dimensionsizes[0]);
68// columnsizes.push_back(proc.dimensionsizes[1] * proc.dimensionsizes[2]);
69// columnsizes.push_back(1);
70// // std::cout << "First sorting process." << std::endl;
71// components = sortComponent(components, columnsizes);
72// // std::cout << "Second sorting process." << std::endl;
73// components = changeComponentsIndex(components,
74// proc.dimensionsizes,
75// proc.dimensionorders,
76// 1, 1);
77//
78// std::cout << "Last sorting process (according to slice taking)."
79// << std::endl;
80// std::cout << std::endl;
81// writeComponents(components);
82// std::cout << std::endl;
83
84 // Write components in JSON format
85// carto::Object bounds = carto::Object::value(carto::PropertySet());
86// std::vector<carto::Object> b;
87//
88// std::vector<Component>::const_iterator end = components.end(), it;
89// for (it = components.begin(); it != end; ++it) {
90// carto::Object bound = carto::Object::value(carto::PropertySet());
91//
92// std::vector<std::vector<float> > v;
93// std::vector<float> lower_bound(3, 0.);
94// std::vector<float> upper_bound(3, 0.);
95// const Component & c = *it;
96//
97// // Get bounding box coordinates
98// lower_bound[0] = (vs[0] * c.abscissa_x);
99// lower_bound[1] = (vs[1] * c.ordinate_y);
100// lower_bound[2] = (vs[2] * c.coordinate_z);
101// upper_bound[0] = (vs[0] * c.abscissa_X);
102// upper_bound[1] = (vs[1] * c.ordinate_Y);
103// upper_bound[2] = (vs[2] * c.coordinate_Z);
104// v.push_back(lower_bound);
105// v.push_back(upper_bound);
106//
107// bound->setProperty("bounds", v);
108// b.push_back(bound);
109// }
110// bounds->setProperty("bounding_boxes", b);
111
112 aims::Writer<carto::Object> w(proc.fileOut);
113 const std::string format("JSON");
114 return w.write(bounds, false, &format);
115}
116
117template<class T> bool
118individStackSlices(aims::Process & p, const std::string &, aims::Finder &)
119{
120 SlicesStacker & proc = (SlicesStacker &)p;
121
122// #ifdef INDIVID_STACK_SLICES
123 carto::VolumeRef<T> vol;
124
125 std::vector<Component> components;
126
127 if (proc.dimensionsizes.size() == 0) {
128 proc.dimensionsizes.push_back(1);
129 }
130
131 if (proc.dimensionorders.size() == 0) {
132 proc.dimensionorders.push_back(0);
133 }
134
135
136 {
137 // Only allocate data_analysis during analysis step
138 carto::VolumeRef<int16_t> volgrey;
139 //
140 // Read data to use for processing components
141 //
142 if (!proc.fileInP.empty())
143 {
144 aims::ChannelReader<carto::VolumeRef<int16_t> > reader(proc.fileInP);
145 reader.read(volgrey, proc.c);
146 std::cout << "Pre-processed image loaded" << std::endl;
147 }
148 else
149 {
150 aims::ChannelReader<carto::VolumeRef<int16_t> > reader(proc.fileIn);
151 reader.read(volgrey, proc.c);
152 std::cout << "Original image loaded" << std::endl;
153 }
154 // Instanciate detector object
156 1. / proc.fraction,
157 NB_MODES,
158 MAX_HISTO,
159 true);
160
161 // Step 1: Detect components
162 components = detector.analyze(volgrey, proc.n, proc.res,
163 proc.lt, proc.ht);
164 }
165
166 // Step 2: sort components
167 // It is necessary to first sort using 2 dimensions because images are 2d
168 std::vector<int32_t> columnsizes;
169 columnsizes.push_back(proc.dimensionsizes[0]);
170 columnsizes.push_back(proc.dimensionsizes[1] * proc.dimensionsizes[2]);
171 columnsizes.push_back(1);
172 // std::cout << "First sorting process." << std::endl;
173 components = sortComponent(components, columnsizes);
174 // std::cout << "Second sorting process." << std::endl;
175 components = changeComponentsIndex(components,
176 proc.dimensionsizes,
177 proc.dimensionorders,
178 1, 1);
179
180 std::cout << "Last sort processed (according to slice taking) ..."
181 << std::endl;
182
183 std::cout << std::endl;
184 writeComponents(components);
185 std::cout << std::endl;
186
187 // Step 3: reconstruct volume
188 aims::Reader<carto::VolumeRef<T> > fileIn(proc.fileIn);
189 fileIn.read(vol);
190
191 T bg = background<T>(components, vol);
192 std::cout << "Background : " << toString(bg) << std::endl;
193
194 bool result = false;
195 if (proc.nostack)
196 {
197 // Use input file name by default
198 std::string outname = (proc.outName.empty() ? FileUtil::removeExtension(
199 FileUtil::basename(
200 proc.fileIn))
201 : proc.outName);
202
203 result = writeNumberedSlices(proc.dx, proc.dy,
204 proc.res, proc.z,
205 bg,
206 components,
207 vol,
208 proc.fileOut,
209 outname,
210 proc.format,
211 proc.sn);
212 std::cout << "Volume written to output directory. Terminated."
213 << std::endl;
214 }
215 else
216 {
217 result = writeStackedSlices(proc.dx, proc.dy,
218 proc.res, proc.z,
219 bg,
220 components,
221 vol,
222 proc.fileOut,
223 proc.format);
224 std::cout << "Volume written to output file. Terminated." << std::endl;
225 }
226
227 return result;
228// #else
229// std::cout << "!!!WARNING!!! indiviualize and stack processing has been "
230// "disabled at compile time." << std::endl;
231// #endif
232}
233
234
235template<class T>
236void rescale(carto::VolumeRef<T> &in, RescalerInfo & info)
237{
238 if (std::isnan(info.vmin)) {
239 if (! info.usevtypelimits) {
240 info.vmin = (double) in.min();
241 }
242 }
243
244 if (std::isnan(info.vmax)) {
245 if (! info.usevtypelimits) {
246 info.vmax = (double) in.max();
247 }
248 }
249
250 DefaultedRescalerInfo<T, T> defaultedinfo(info);
251
252 int x, y, z, t,
253 dx = in.getSizeX(),
254 dy = in.getSizeY(),
255 dz = in.getSizeZ(),
256 dt = in.getSizeT();
257
258 for (t = 0; t < dt; ++t)
259 {
260 for (z = 0; z < dz; ++z)
261 {
262 for (y = 0; y < dy; ++y)
263 {
264 for (x = 0; x < dx; ++x)
265 in(x, y, z, t) = defaultedinfo.getScaledValue(
266 in(x, y, z, t));
267 }
268 }
269 }
270}
271
272template<class T>
273bool writeStackedSlices(int32_t dx, int32_t dy, int32_t res,
274 float z,
275 T background,
276 std::vector<Component> &cpnt,
277 carto::VolumeRef<T> &data,
278 std::string outputfile,
279 std::string format)
280{
281 int32_t x, y, l;
282
283 const std::string *wf = 0;
284 if (!format.empty())
285 wf = &format;
286
287 Object options = Object::value(Dictionary());
288 //options->setProperty("exact_format", true);
289
290 if (dx == 0)
291 dx = extractMaxima(
294 else if (dx < extractMaxima(
296 * BORDER_LOCAL)
297 {
298 throw dimension_x_error();
299 }
300
301 if (dy == 0)
302 dy = extractMaxima(
305 else if (dy < extractMaxima(
307 * BORDER_LOCAL)
308 {
309 throw dimension_y_error();
310 }
311
312 carto::VolumeRef<T> recons_volume(dx, dy, cpnt.size());
313 std::vector<float> vs(4, 1.);
314 vs[0] = INCH / res;
315 vs[1] = INCH / res;
316 vs[2] = z;
317
318 recons_volume.header().setProperty("voxel_size", vs);
319
320 // Background optimized from histogram analysis
321 recons_volume = background;
322
323 std::cout << "Reconstructing volume ..." << std::endl << std::endl;
324 for (l = 0; l < int32_t(cpnt.size()); ++l)
325 {
326 Point2d shift, size_component;
327
328 size_component[0] = cpnt[l].bounding_hz + 2 * BORDER_LOCAL;
329 size_component[1] = cpnt[l].bounding_vt + 2 * BORDER_LOCAL;
330
331 shift[0] = (dx - size_component[0]) / 2;
332 shift[1] = (dy - size_component[1]) / 2;
333
334 for (y = 0; y < size_component[1] ; ++y)
335 for (x = 0; x < size_component[0] ; ++x)
336 {
337 if (((x + cpnt[l].abscissa_x - BORDER_LOCAL) >= 0)
338 && ((x + cpnt[l].abscissa_x - BORDER_LOCAL) < data.getSizeX())
339 && ((y + cpnt[l].ordinate_y - BORDER_LOCAL) >= 0)
340 && ((y + cpnt[l].ordinate_y - BORDER_LOCAL) < data.getSizeY()))
341 {
342 recons_volume(x + shift[0],
343 y + shift[1],
344 cpnt[l].label_f - 1) = data(
345 x + cpnt[l].abscissa_x - BORDER_LOCAL,
346 y + cpnt[l].ordinate_y - BORDER_LOCAL);
347 }
348 }
349 }
350
351 std::cout << "Stacking process achieved." << std::endl;
352
353 //
354 // Ecriture du fichier
355 //
356 aims::Writer<carto::VolumeRef<T> > volumeWriter(outputfile, options);
357 return volumeWriter.write(recons_volume, false, wf);
358}
359
360template<class T>
361bool writeNumberedSlices(int32_t dx, int32_t dy, int32_t res,
362 float z,
363 T background,
364 std::vector<Component> &cpnt,
365 carto::VolumeRef<T> &data,
366 std::string outputdir,
367 std::string outputname,
368 std::string format,
369 uint8_t slicemin)
370{
371 int32_t x, y, l;
372
373 Directory dir = Directory(outputdir);
374 dir.makedirs();
375
376 std::string dirname = dir.dirname();
377 std::string extension = FileUtil::extension(outputname);
378 std::string wf = (format.empty() && extension.empty() ? "GIS" : format);
379
380 Object options = Object::value(Dictionary());
381 options->setProperty("exact_format", true);
382
383 if (dx == 0)
384 dx = extractMaxima(
387 else if (dx < extractMaxima(
389 * BORDER_LOCAL)
390 {
391 throw dimension_x_error();
392 }
393
394 if (dy == 0)
395 dy = extractMaxima(
398 else if (dy < extractMaxima(
400 * BORDER_LOCAL)
401 {
402 throw dimension_y_error();
403 }
404
405 carto::VolumeRef<T> slice(dx, dy);
406 std::vector<float> vs(4, 1.);
407 vs[0] = INCH / res;
408 vs[1] = INCH / res;
409 vs[2] = z;
410
411 slice.header().setProperty("voxel_size", vs);
412
413 std::cout << "Writing volume slices ..." << std::endl << std::endl;
414
415 for (l=0; l<int32_t(cpnt.size()); ++l)
416 {
417 // Background optimized from histogram analysis
418 slice = background;
419
420 Point2d shift, size_component;
421
422 size_component[0] = cpnt[l].bounding_hz + 2 * BORDER_LOCAL;
423 size_component[1] = cpnt[l].bounding_vt + 2 * BORDER_LOCAL;
424
425 shift[0] = (dx - size_component[0]) / 2;
426 shift[1] = (dy - size_component[1]) / 2;
427
428 for (y = 0; y < size_component[1] ; ++y)
429 for (x = 0; x < size_component[0] ; ++x)
430 {
431 if (((x + cpnt[l].abscissa_x - BORDER_LOCAL) >= 0)
432 && ((x + cpnt[l].abscissa_x - BORDER_LOCAL) < data.getSizeX())
433 && ((y + cpnt[l].ordinate_y - BORDER_LOCAL) >= 0)
434 && ((y + cpnt[l].ordinate_y - BORDER_LOCAL) < data.getSizeY()))
435 {
436 slice(x + shift[0],
437 y + shift[1]) = data(x + cpnt[l].abscissa_x
438 - BORDER_LOCAL,
439 y + cpnt[l].ordinate_y
440 - BORDER_LOCAL);
441 }
442 }
443
444 std::stringstream ss;
445 ss << outputdir << FileUtil::separator()
446 << FileUtil::removeExtension(FileUtil::basename(outputname));
447 ss << "_" << setfill('0') << setw(4) << slicemin + cpnt[l].label_f - 1;
448
449 if (! extension.empty())
450 ss << "." << extension;
451
452 // std::cout << "Writing file : " << ss.str()
453 // << std::endl << std::flush;
454
455 aims::Writer<carto::VolumeRef<T> > sliceWriter(ss.str(), options);
456 if (! sliceWriter.write(slice, false, &wf))
457 return false;
458 }
459
460 return true;
461}
std::vector< Component > analyze(carto::VolumeRef< int16_t > &vol, const int32_t slices_number=6, const int32_t scan_resolution=0, const int32_t threshold_lowerbound=0, const int32_t threshold_upperbound=0)
carto::Object boundingBoxes(const carto::VolumeRef< int16_t > &vol, const std::vector< Component > &components)
float min_size
Definition slices.h:46
bool disable_checks
Definition slices.h:50
int32_t lt
Definition slices.h:48
int32_t res
Definition slices.h:47
std::string fileOut
Definition slices.h:44
float fraction
Definition slices.h:46
int32_t ht
Definition slices.h:48
uint8_t c
Definition slices.h:49
int32_t n
Definition slices.h:47
std::string fileIn
Definition slices.h:43
int32_t lt
Definition slices.h:71
int32_t res
Definition slices.h:70
std::string format
Definition slices.h:65
float fraction
Definition slices.h:68
std::string fileIn
Definition slices.h:60
float z
Definition slices.h:73
bool nostack
Definition slices.h:67
uint8_t c
Definition slices.h:72
float min_size
Definition slices.h:68
int32_t ht
Definition slices.h:71
std::vector< int32_t > dimensionsizes
Definition slices.h:64
std::string fileOut
Definition slices.h:62
int32_t dy
Definition slices.h:71
std::vector< int32_t > dimensionorders
Definition slices.h:64
uint8_t sn
Definition slices.h:69
int32_t dx
Definition slices.h:71
int32_t n
Definition slices.h:70
std::string fileInP
Definition slices.h:61
std::string outName
Definition slices.h:63
std::vector< Component > changeComponentsIndex(std::vector< Component > &components, std::vector< int32_t > dimensionsizes, std::vector< int32_t > dimensionorders, int32_t offset=1, int32_t step=1)
std::vector< int32_t > extractVectorFromComponent(std::vector< Component > cpnt, ContinuityParameterTested param)
#define NB_MODES
Definition slices.h:24
std::vector< Component > sortComponent(std::vector< Component > &cpnt, std::vector< int32_t > dimensionsizes)
@ ComponentSize_vt
Definition slices.h:97
@ ComponentSize_hz
Definition slices.h:96
#define BORDER_GLOBAL
Definition slices.h:34
#define MAX_HISTO
Definition slices.h:26
#define BORDER_LOCAL
Definition slices.h:33
void writeComponents(std::vector< Component > &comp)
int32_t extractMaxima(std::vector< int32_t > vctr)
T background(std::vector< Component > &cpnt, carto::VolumeRef< T > &vol)
Definition slices.h:489
#define INCH
Definition slices.h:23
void rescale(carto::VolumeRef< T > &in, RescalerInfo &info)
Definition slices_d.h:236
bool detectSlices(aims::Process &p, const std::string &, aims::Finder &)
Definition slices_d.h:23
bool writeNumberedSlices(int32_t dx, int32_t dy, int32_t res, float z, T background, std::vector< Component > &cpnt, carto::VolumeRef< T > &data, std::string outputdir, std::string outputname, std::string format, uint8_t slicemin)
Definition slices_d.h:361
bool writeStackedSlices(int32_t dx, int32_t dy, int32_t res, float z, T background, std::vector< Component > &cpnt, carto::VolumeRef< T > &data, std::string outputfile, std::string format)
Definition slices_d.h:273
bool individStackSlices(aims::Process &p, const std::string &, aims::Finder &)
Definition slices_d.h:118