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