00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <fvutils/statistical/histogram.h>
00026 #include <fvutils/statistical/histogram_file.h>
00027 #include <fvutils/statistical/histogram_block.h>
00028
00029 #include <core/exceptions/software.h>
00030
00031 #include <iostream>
00032 #include <fstream>
00033 #include <vector>
00034 #include <cstdlib>
00035 #include <algorithm>
00036 #include <cstring>
00037
00038 using namespace std;
00039 using namespace fawkes;
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 Histogram::Histogram(unsigned int width, unsigned int height,
00054 unsigned int depth, unsigned int num_undos)
00055 {
00056 if ( (width == 0) || (height == 0) || (depth == 0) ) {
00057 throw Exception("Width or height or depth is zero.");
00058 }
00059
00060 this->width = width;
00061 this->height = height;
00062 this->depth = depth;
00063 this->undo_num = num_undos;
00064 this->undo_current = 0;
00065
00066 if (depth == 1) {
00067 dimension = 2;
00068 } else {
00069 dimension = 3;
00070 }
00071
00072 histogram_block = new HistogramBlock(FIREVISION_HISTOGRAM_TYPE_32, H_UNKNOWN,
00073 width, height, depth);
00074 histogram = (unsigned int*) histogram_block->data_ptr();
00075
00076 histogram_size = width * height * depth * sizeof(unsigned int);
00077
00078 undo_overlay = (unsigned int **)malloc(undo_num * sizeof(unsigned int *));
00079 for (unsigned int i = 0; i < undo_num; ++i) {
00080 undo_overlay[i] = (unsigned int *)malloc(histogram_size);
00081 }
00082
00083 undo_num_vals = (unsigned int *)malloc(undo_num * sizeof(unsigned int));
00084
00085 reset();
00086 }
00087
00088
00089
00090
00091
00092 Histogram::Histogram(HistogramBlock* block)
00093 {
00094 width = block->width();
00095 height = block->height();
00096 depth = block->depth();
00097
00098 if (depth == 1) {
00099 dimension = 2;
00100 } else {
00101 dimension = 3;
00102 }
00103
00104 undo_num = 1;
00105 undo_current = 0;
00106
00107 histogram_block = block;
00108 histogram = (unsigned int*) histogram_block->data_ptr();
00109 histogram_size = width * height * depth * sizeof(unsigned int);
00110
00111 undo_overlay = (unsigned int **)malloc(undo_num * sizeof(unsigned int *));
00112 for (unsigned int i = 0; i < undo_num; ++i) {
00113 undo_overlay[i] = (unsigned int *)malloc(histogram_size);
00114 }
00115
00116 undo_num_vals = (unsigned int *)malloc(undo_num * sizeof(unsigned int));
00117 }
00118
00119
00120
00121 Histogram::~Histogram()
00122 {
00123 delete histogram_block;
00124 for (unsigned int i = 0; i < undo_num; ++i) {
00125 free(undo_overlay[i]);
00126 }
00127 free(undo_overlay);
00128 free(undo_num_vals);
00129 }
00130
00131
00132
00133
00134
00135 void
00136 Histogram::operator+=(point_t *p)
00137 {
00138 if ( dimension != 2 ) {
00139 throw Exception("Trying to add 2-dim data to 3-dim histogram");
00140 }
00141
00142 if (p->x >= width || p->y >= height) {
00143 throw OutOfBoundsException("Point lies outside of histogram range");
00144 }
00145
00146 unsigned int index = p->y * width + p->x;
00147 histogram[index] += 1;
00148 undo_overlay[undo_current][index] += 1;
00149 ++number_of_values;
00150 undo_num_vals[undo_current] += 1;
00151 }
00152
00153
00154
00155
00156
00157 void
00158 Histogram::operator+=(point_t p)
00159 {
00160 if ( dimension != 2 ) {
00161 throw Exception("Trying to add 2-dim data to 3-dim histogram");
00162 }
00163
00164 if (p.x >= width || p.y >= height) {
00165 throw OutOfBoundsException("Point lies outside of histogram range");
00166 }
00167
00168 unsigned int index = p.y * width + p.x;
00169 histogram[index] += 1;
00170 undo_overlay[undo_current][index] += 1;
00171 ++number_of_values;
00172 undo_num_vals[undo_current] += 1;
00173 }
00174
00175
00176
00177
00178
00179 unsigned int *
00180 Histogram::get_histogram()
00181 {
00182 return histogram;
00183 }
00184
00185
00186
00187
00188
00189 HistogramBlock *
00190 Histogram::get_histogram_block()
00191 {
00192 return histogram_block;
00193 }
00194
00195
00196
00197
00198
00199
00200
00201 void
00202 Histogram::get_dimensions(unsigned int& width, unsigned int& height, unsigned int& depth)
00203 {
00204 width = this->width;
00205 height = this->height;
00206 depth = this->depth;
00207 }
00208
00209
00210
00211
00212
00213
00214 unsigned int
00215 Histogram::get_value(unsigned int x, unsigned int y)
00216 {
00217 return histogram_block->get_value(x, y);
00218 }
00219
00220
00221
00222
00223
00224
00225
00226 unsigned int
00227 Histogram::get_value(unsigned int x, unsigned int y, unsigned int z)
00228 {
00229 return histogram_block->get_value(x, y, z);
00230 }
00231
00232
00233
00234
00235
00236
00237
00238 void
00239 Histogram::set_value(unsigned int x, unsigned int y, unsigned int value)
00240 {
00241 unsigned int old_value = histogram_block->get_value(x, y);
00242 histogram_block->set_value(x, y, value);
00243 number_of_values += value - old_value;
00244
00245 unsigned int index = y * width + x;
00246 if ( value > old_value ) {
00247
00248 undo_overlay[undo_current][index] += value - old_value;
00249 } else {
00250 if ( (old_value - value) < undo_overlay[undo_current][index] ) {
00251 undo_overlay[undo_current][index] -= (old_value - value);
00252 } else {
00253
00254
00255 undo_overlay[undo_current][index] = 0;
00256 }
00257 }
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267 void
00268 Histogram::set_value(unsigned int x, unsigned int y, unsigned int z, unsigned int value)
00269 {
00270 unsigned int old_value = histogram_block->get_value(x, y, z);
00271 histogram_block->set_value(x, y, z, value);
00272
00273 number_of_values += value - old_value;
00274 unsigned int index = z * width * height + y * width + x;
00275 if ( value > old_value ) {
00276
00277 undo_overlay[undo_current][index] += value - old_value;
00278 } else {
00279 if ( (old_value - value) < undo_overlay[undo_current][index] ) {
00280 undo_overlay[undo_current][index] -= (old_value - value);
00281 } else {
00282
00283
00284 undo_overlay[undo_current][index] = 0;
00285 }
00286 }
00287 }
00288
00289
00290
00291
00292
00293
00294
00295 void
00296 Histogram::inc_value(unsigned int x, unsigned int y, unsigned int z)
00297 {
00298 unsigned int old_value = histogram_block->get_value(x, y, z);
00299 histogram_block->set_value(x, y, z, ++old_value);
00300
00301 ++number_of_values;
00302
00303 unsigned int index = z * width * height + y * width + x;
00304 undo_overlay[undo_current][index] = 1;
00305 }
00306
00307
00308
00309
00310
00311
00312
00313
00314 void
00315 Histogram::add(unsigned int x, unsigned int y, unsigned int z, unsigned int value)
00316 {
00317 unsigned int cur_value = histogram_block->get_value(x, y, z);
00318 histogram_block->set_value(x, y, z, cur_value + value);
00319
00320 number_of_values += value;
00321
00322 unsigned int index = z * width * height + y * width + x;
00323 undo_overlay[undo_current][index] = value;
00324 }
00325
00326
00327
00328
00329
00330
00331
00332
00333 void
00334 Histogram::sub(unsigned int x, unsigned int y, unsigned int z, unsigned int value)
00335 {
00336 unsigned int cur_value = histogram_block->get_value(x, y, z);
00337 if (value < cur_value) {
00338 set_value(x, y, z, cur_value - value);
00339 } else {
00340 set_value(x, y, z, 0);
00341 }
00342
00343 number_of_values -= value;
00344
00345 unsigned int index = z * width * height + y * width + x;
00346 if ( value < undo_overlay[undo_current][index] )
00347 {
00348 undo_overlay[undo_current][index] -= value;
00349 }
00350 else
00351 {
00352 undo_overlay[undo_current][index] = 0;
00353 }
00354 }
00355
00356
00357
00358 void
00359 Histogram::reset()
00360 {
00361 histogram_block->reset();
00362
00363 number_of_values = 0;
00364 for (unsigned int i = 0; i < undo_num; ++i) {
00365 switch_undo( i );
00366 reset_undo();
00367 }
00368 switch_undo( 0 );
00369 }
00370
00371
00372
00373
00374
00375 void
00376 Histogram::print_to_stream(std::ostream &s)
00377 {
00378 for (unsigned int z = 0; z < depth; ++z) {
00379 for (unsigned int y = 0; y < height; ++y) {
00380 for (unsigned int x = 0; x < width; ++x) {
00381
00382 cout << histogram_block->get_value(x, y, z) << " ";
00383 }
00384 }
00385 cout << endl;
00386 }
00387 cout << endl;
00388 }
00389
00390
00391
00392
00393
00394
00395 void
00396 Histogram::save(const char *filename, bool formatted_output)
00397 {
00398 HistogramFile histogram_file;
00399 histogram_file.set_owns_blocks(false);
00400 histogram_file.add_histogram_block(histogram_block);
00401 histogram_file.write(filename);
00402
00403 cout << "Histogram: Saved histogram in file \"" << filename << "\"." << endl;
00404 }
00405
00406
00407
00408
00409
00410 bool
00411 Histogram::load(const char *filename)
00412 {
00413 HistogramFile histogram_file;
00414 histogram_file.read(filename);
00415
00416 if ( histogram_file.num_blocks() != 1 )
00417 {
00418 printf("load() aborted: file contains more than one histogram");
00419 return false;
00420 }
00421
00422 histogram_block = (HistogramBlock*) histogram_file.blocks().front();
00423 histogram = (unsigned int*) histogram_block->data_ptr();
00424 histogram_size = width * height * depth * sizeof(unsigned int);
00425
00426 for (unsigned int i = 0; i < undo_num; ++i) {
00427 free(undo_overlay[i]);
00428 }
00429 free(undo_overlay);
00430
00431 undo_overlay = (unsigned int **)malloc(undo_num * sizeof(unsigned int *));
00432 for (unsigned int i = 0; i < undo_num; ++i) {
00433 undo_overlay[i] = (unsigned int *)malloc(histogram_size);
00434 }
00435
00436 return true;
00437 }
00438
00439
00440
00441 void
00442 Histogram::reset_undo()
00443 {
00444 memset(undo_overlay[undo_current], 0, histogram_size);
00445 undo_num_vals[undo_current] = 0;
00446 }
00447
00448
00449
00450 void
00451 Histogram::undo()
00452 {
00453 for (unsigned int z = 0; z < depth; ++z) {
00454 for (unsigned int y = 0; y < height; ++y) {
00455 for (unsigned int x = 0; x < width; ++x) {
00456 unsigned int index = z * width * height + y * width + x;
00457 histogram[index] -= undo_overlay[undo_current][index];
00458 }
00459 }
00460 }
00461 number_of_values -= undo_num_vals[undo_current];
00462 reset_undo();
00463 }
00464
00465
00466
00467
00468
00469
00470 unsigned int
00471 Histogram::switch_undo( unsigned int undo_id )
00472 {
00473 unsigned int undo_last = undo_current;
00474
00475 if (undo_id >= undo_num) {
00476 cout << "Histogram::resetUndo: ID out of range" << endl;
00477 } else {
00478 undo_current = undo_id;
00479 }
00480
00481 return undo_last;
00482 }
00483
00484
00485
00486
00487
00488 unsigned int
00489 Histogram::get_num_undos()
00490 {
00491 return undo_num;
00492 }
00493
00494
00495
00496
00497
00498 unsigned int
00499 Histogram::get_median()
00500 {
00501 vector< unsigned int > *values = new vector< unsigned int >( width * height * depth);
00502
00503 values->clear();
00504 for (unsigned int z = 0; z < depth; ++z) {
00505 for (unsigned int y = 0; y < height; ++y) {
00506 for (unsigned int x = 0; x < width; ++x) {
00507 values->push_back( histogram_block->get_value(x, y, z) );
00508 }
00509 }
00510 }
00511
00512 sort(values->begin(), values->end());
00513
00514 unsigned int median = values->at( values->size() / 2 );
00515
00516 delete values;
00517
00518 return median;
00519 }
00520
00521
00522
00523
00524
00525 unsigned int
00526 Histogram::get_average()
00527 {
00528 unsigned int sum = 0;
00529 unsigned int num = 0;
00530 for (unsigned int z = 0; z < depth; ++z) {
00531 for (unsigned int y = 0; y < height; ++y) {
00532 for (unsigned int x = 0; x < width; ++x) {
00533 if ( histogram[z * width * height + y * width + x ] ) {
00534 sum += histogram_block->get_value(x, y, z);
00535 num++;
00536 }
00537 }
00538 }
00539 }
00540
00541 return (sum / num);
00542 }
00543
00544
00545
00546
00547
00548 unsigned int
00549 Histogram::get_sum() const
00550 {
00551 unsigned int sum = 0;
00552 for (unsigned int z = 0; z < depth; ++z) {
00553 for (unsigned int y = 0; y < height; ++y) {
00554 for (unsigned int x = 0; x < width; ++x) {
00555 if ( histogram[z * width * height + y * width + x ] ) {
00556 sum += histogram_block->get_value(x, y, z);
00557 }
00558 }
00559 }
00560 }
00561
00562 return sum;
00563 }