Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
textons.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2016, Hann Woei Ho, Guido de Croon
3 *
4 * This file is part of Paparazzi.
5 *
6 * Paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * Paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Paparazzi; see the file COPYING. If not, write to
18 * the Free Software Foundation, 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
20 */
21
32#include <stdlib.h>
33#include <stdio.h>
36#include "mcu_periph/sys_time.h"
37#include "generated/airframe.h"
38
39float ** **dictionary;
43
44#define MAX_N_TEXTONS 255
45
46// initial settings:
47#ifndef TEXTONS_RUN
48#define TEXTONS_RUN 1
49#endif
51
52#ifndef TEXTONS_FPS
53#define TEXTONS_FPS 30
54#endif
56
57#ifndef TEXTONS_LOAD_DICTIONARY
58#define TEXTONS_LOAD_DICTIONARY 1
59#endif
61
62#ifndef TEXTONS_REINITIALIZE_DICTIONARY
63#define TEXTONS_REINITIALIZE_DICTIONARY 0
64#endif
66
67#ifndef TEXTONS_ALPHA
68#define TEXTONS_ALPHA 0
69#endif
71
72#ifndef TEXTONS_N_TEXTONS
73#define TEXTONS_N_TEXTONS 20
74#endif
76
77#ifndef TEXTONS_N_SAMPLES
78#define TEXTONS_N_SAMPLES 250
79#endif
81
82#ifndef TEXTONS_PATCH_SIZE
83#define TEXTONS_PATCH_SIZE 6
84#endif
86
87#ifndef TEXTONS_N_LEARNING_SAMPLES
88#define TEXTONS_N_LEARNING_SAMPLES 5000
89#endif
91
92#ifndef TEXTONS_FULL_SAMPLING
93#define TEXTONS_FULL_SAMPLING 0
94#endif
96
97#ifndef TEXTONS_BORDER_WIDTH
98#define TEXTONS_BORDER_WIDTH 0
99#endif
101
102#ifndef TEXTONS_BORDER_HEIGHT
103#define TEXTONS_BORDER_HEIGHT 0
104#endif
106
107#ifndef TEXTONS_DICTIONARY_NUMBER
108#define TEXTONS_DICTIONARY_NUMBER 0
109#endif
111
112#ifndef TEXTONS_DICTIONARY_PATH
113#define TEXTONS_DICTIONARY_PATH /data/ftp/internal_000
114#endif
115
117
130
131// status variables
133float alpha = 0.0;
134
135// File pointer for saving the dictionary
137
143struct image_t *texton_func(struct image_t *img, UNUSED uint8_t p);
145{
146 // whether to execute the function:
147 if (!running) { return img; }
148
149 if (img->buf_size == 0) { return img; }
150
151 // extract frame from img struct:
152 uint8_t *frame = (uint8_t *)img->buf;
153
154 // if patch size odd, correct:
155 if (patch_size % 2 == 1) { patch_size++; }
156
157 // check whether we have to reinitialize the dictionary:
159 // set all vars to trigger a reinitialization and learning phase of the dictionary:
162 load_dictionary = 0;
163 learned_samples = 0;
164 alpha_uint = 10;
165 // reset reinitialize_dictionary
167 }
168
169 // if dictionary not initialized:
170 if (dictionary_ready == 0) {
171 if (load_dictionary == 0) {
172
173 printf("Learned samples: %d / %d\n", learned_samples, n_learning_samples);
174
175 // Train the dictionary:
177
178 // After a number of samples, stop learning:
180 // Save the dictionary:
182 // stop learning:
184 // lower learning rate
185 alpha = 0.0;
186 printf("Enough learning!\n");
187 alpha_uint = 0;
188 // set learned samples back to 0
189 learned_samples = 0;
190 }
191 } else {
192 // Load the dictionary:
194 }
195 } else {
196 if (alpha_uint > 0) {
197
198 // printf("Learning, frame time = %d\n", img->ts.tv_sec * 1000 + img->ts.tv_usec / 1000);
199
201
203 // Save the dictionary:
205 // reset learned_samples:
206 learned_samples = 0;
207 }
208 } else {
209 // Extract distributions
211 }
212
213 // printf("N textons = %d\n", n_samples_image);
214 // printf("Entropy texton distribution = %f\n", get_entropy(texton_distribution, n_textons));
215 }
216
217 return img; // Colorfilter did not make a new image
218}
219
228{
229 int i, j, w, s, texton, c; // iterators
230 int x, y; // image coordinates
231 float error_texton; // distance between an image patch and a texton
232
233 uint8_t *buf;
234
235 // ***********************
236 // DICTIONARY LEARNING
237 // ***********************
238
240 // **************
241 // INITIALISATION
242 // **************
243
244 printf("Intializing dictionary!\n");
245
246 // in the first image, we initialize the textons to random patches in the image
247 for (w = 0; w < n_textons; w++) {
248 // select a coordinate
249 x = rand() % (width - patch_size);
250 y = rand() % (height - patch_size);
251
252 //printf("(x,y) = (%d,%d), (w,h) = (%d,%d), ps = %d\n", x, y, width, height, patch_size);
253 // take the sample
254 for (i = 0; i < patch_size; i++) {
255 buf = frame + (width * 2 * (i + y)) + 2 * x;
256 for (j = 0; j < patch_size; j++) {
257 // put it in a texton
258 printf("Setting dictionary:\n");
259 // U/V component
260
261 dictionary[w][i][j][0] = (float) * buf;
262 buf += 1;
263 // Y1/Y2 component
264 dictionary[w][i][j][1] = (float) * buf;
265 buf += 1;
266 printf("Done!\n");
267 }
268 }
269 }
271 } else {
272 // ********
273 // LEARNING
274 // ********
275 printf("Learning!");
276 alpha = ((float) alpha_uint) / 255.0;
277
278 float *texton_distances, * **patch;
279 texton_distances = (float *)calloc(n_textons, sizeof(float));
280 patch = (float ** *)calloc(patch_size, sizeof(float **));
281
282 for (i = 0; i < patch_size; i++) {
283 patch[i] = (float **)calloc(patch_size, sizeof(float *));
284 for (j = 0; j < patch_size; j++) {
285 patch[i][j] = (float *)calloc(2, sizeof(float));
286 }
287 }
288
289 // Extract and learn from n_samples_image per image
290 for (s = 0; s < (int) n_samples_image; s++) {
291 // select a random sample from the image
292 x = rand() % (width - patch_size);
293 y = rand() % (height - patch_size);
294
295 // reset texton_distances
296 for (texton = 0; texton < n_textons; texton++) {
298 }
299
300 // extract sample
301 for (i = 0; i < patch_size; i++) {
302 buf = frame + (width * 2 * (i + y)) + 2 * x;
303 for (j = 0; j < patch_size; j++) {
304 // U/V component
305 patch[i][j][0] = (float) * buf;
306 buf += 1;
307 // Y1/Y2 component
308 patch[i][j][1] = (float) * buf;
309 buf += 1;
310 }
311 }
312
313 // determine distances to the textons:
314 for (i = 0; i < patch_size; i++) {
315 for (j = 0; j < patch_size; j++) {
316 for (c = 0; c < 2; c++) {
317 // determine the distance to textons
318 for (texton = 0; texton < n_textons; texton++) {
319 texton_distances[texton] += (patch[i][j][c] - dictionary[texton][i][j][c])
320 * (patch[i][j][c] - dictionary[texton][i][j][c]);
321 }
322 }
323 }
324 }
325
326 // search the closest texton
327 int assignment = 0;
328 float min_dist = texton_distances[0];
329 for (texton = 1; texton < n_textons; texton++) {
333 }
334 }
335
336 // move the neighbour closer to the input
337 for (i = 0; i < patch_size; i++) {
338 for (j = 0; j < patch_size; j++) {
339 for (c = 0; c < 2; c++) {
340 error_texton = patch[i][j][c] - dictionary[assignment][i][j][c];
342 }
343 }
344 }
345
346 // Augment the number of learned samples:
348 }
349
350 // Free the allocated memory:
351 for (i = 0; i < patch_size; i++) {
352 for (j = 0; j < patch_size; j++) {
353 free(patch[i][j]);
354 }
355 free(patch[i]);
356 }
357 free(patch);
359 }
360
361 // Free the buffer
362 buf = NULL;
363 free(buf);
364}
365
373{
374 int i, j, texton, c; // iterators
375 int x, y; // coordinates
376 int n_extracted_textons = 0;
377
378 uint8_t *buf;
379
380 // ************************
381 // EXECUTION
382 // ************************
383
384 // Allocate memory for texton distances and image patch:
385 float *texton_distances, * **patch;
386 texton_distances = (float *)calloc(n_textons, sizeof(float));
387 patch = (float ** *)calloc(patch_size, sizeof(float **));
388 for (i = 0; i < patch_size; i++) {
389 patch[i] = (float **)calloc(patch_size, sizeof(float *));
390 for (j = 0; j < patch_size; j++) {
391 patch[i][j] = (float *)calloc(2, sizeof(float));
392 }
393 }
394
395 int finished = 0;
396 x = 0;
397 y = 0;
398 while (!finished) {
399 if (!FULL_SAMPLING) {
400 x = border_width + rand() % (width - patch_size - 2 * border_width);
401 y = border_height + rand() % (height - patch_size - 2 * border_height);
402 }
403
404 // reset texton_distances
405 for (texton = 0; texton < n_textons; texton++) {
407 }
408
409 // extract sample
410 for (i = 0; i < patch_size; i++) {
411 buf = frame + (width * 2 * (i + y)) + 2 * x;
412 for (j = 0; j < patch_size; j++) {
413 // U/V component
414 patch[i][j][0] = (float) * buf;
415 buf += 1;
416 // Y1/Y2 component
417 patch[i][j][1] = (float) * buf;
418 buf += 1;
419 }
420 }
421
422 // determine distances:
423 for (i = 0; i < patch_size; i++) {
424 for (j = 0; j < patch_size; j++) {
425 for (c = 0; c < 2; c++) {
426 // determine the distance to words
427 for (texton = 0; texton < n_textons; texton++) {
428 texton_distances[texton] += (patch[i][j][c] - dictionary[texton][i][j][c])
429 * (patch[i][j][c] - dictionary[texton][i][j][c]);
430 }
431 }
432 }
433 }
434
435 // determine the nearest neighbour
436 // search the closest centroid
437 int assignment = 0;
438 float min_dist = texton_distances[0];
439 for (texton = 1; texton < n_textons; texton++) {
443 }
444 }
445
446 // put the assignment in the histogram
449
451 finished = 1;
452 } else {
453 // FULL_SAMPLING is actually a sampling that covers the image:
454 y += patch_size;
455 // True full sampling would require:
456 // y++;
457
458 if (y > height - patch_size) {
459 if (!FULL_SAMPLING) {
460 x += patch_size;
461 } else {
462 x++;
463 }
464 y = 0;
465 }
466 if (x > width - patch_size) {
467 finished = 1;
468 }
469 }
470 }
471
472 // Normalize distribution:
473 if (n_extracted_textons > 0) { // should always be the case
474 for (i = 0; i < n_textons; i++) {
476 }
477 }
478 // printf("\n");
479
480
481 // free memory:
482 for (i = 0; i < patch_size; i++) {
483 for (j = 0; j < patch_size; j++) {
484 free(patch[i][j]);
485 }
486 free(patch[i]);
487 }
488 free(patch);
490
491 buf = NULL;
492 free(buf);
493
494} // EXECUTION
495
496
497
502{
503 //save a dictionary
504 char filename[512];
505
506 // Check for available files
508
510
511 if (dictionary_logger == NULL) {
512 printf("Filename: %s\n", filename);
513 perror("Error while opening the file.\n");
514 } else {
515 // (over-)write dictionary
516 for (uint8_t i = 0; i < n_textons; i++) {
517 for (uint8_t j = 0; j < patch_size; j++) {
518 for (uint8_t k = 0; k < patch_size; k++) {
519 fprintf(dictionary_logger, "%f\n", dictionary[i][j][k][0]);
520 fprintf(dictionary_logger, "%f\n", dictionary[i][j][k][1]);
521 }
522 }
523 }
525 }
526
527}
528
533{
534 char filename[512];
536
537 if ((dictionary_logger = fopen(filename, "r"))) {
538 // Load the dictionary:
539 for (int i = 0; i < n_textons; i++) {
540 for (int j = 0; j < patch_size; j++) {
541 for (int k = 0; k < patch_size; k++) {
542 if (fscanf(dictionary_logger, "%f\n", &dictionary[i][j][k][0]) == EOF) { break; }
543 if (fscanf(dictionary_logger, "%f\n", &dictionary[i][j][k][1]) == EOF) { break; }
544 }
545 }
546 }
547
550 } else {
551 // If the given dictionary does not exist, we start learning one:
552 printf("Texton dictionary %d does not exist, we start learning one.\n", dictionary_number);
553 load_dictionary = 0;
554 learned_samples = 0;
556 }
557}
558
562void textons_init(void)
563{
564 printf("Textons init\n");
565 texton_distribution = (float *)calloc(MAX_N_TEXTONS, sizeof(float));
567 learned_samples = 0;
569 dictionary = (float ** **)calloc(MAX_N_TEXTONS, sizeof(float ** *));
570 for (int w = 0; w < MAX_N_TEXTONS; w++) {
571 dictionary[w] = (float ** *) calloc(patch_size, sizeof(float **));
572 for (int i = 0; i < patch_size; i++) {
573 dictionary[w][i] = (float **) calloc(patch_size, sizeof(float *));
574 for (int j = 0; j < patch_size; j++) {
575 dictionary[w][i][j] = (float *) calloc(2, sizeof(float));
576 }
577 }
578 }
579
581}
582
583void textons_stop(void)
584{
587}
588
594float get_entropy(float *p_dist, int D)
595{
596 float entropy = 0.0f;
597 int i;
598 for (i = 0; i < D; i++) {
599 if (p_dist[i] > 0) {
600 entropy -= p_dist[i] * log2(p_dist[i]);
601 }
602 }
603
604 return entropy;
605}
static uint8_t frame[20]
#define UNUSED(x)
struct video_listener * cv_add_to_device(struct video_config_t *device, cv_function func, uint16_t fps, uint8_t id)
Definition cv.c:46
Computer vision framework for onboard processing.
void * buf
Image buffer (depending on the image_type)
Definition image.h:54
uint16_t w
Image width.
Definition image.h:46
static float p[2][2]
static uint32_t s
uint16_t foo
Definition main_demo5.c:58
PRINT_CONFIG_VAR(ONELOOP_ANDI_FILT_CUTOFF)
Architecture independent timing functions.
void save_texton_dictionary(void)
Save the texton dictionary.
Definition textons.c:501
struct video_listener * listener
Definition textons.c:116
void load_texton_dictionary(void)
Load a texton dictionary.
Definition textons.c:532
#define TEXTONS_FPS
Definition textons.c:53
float * texton_distribution
Definition textons.c:42
#define TEXTONS_ALPHA
Definition textons.c:68
#define TEXTONS_PATCH_SIZE
Definition textons.c:83
uint8_t patch_size
Definition textons.c:123
uint32_t n_learning_samples
Definition textons.c:124
uint8_t load_dictionary
Definition textons.c:119
uint8_t n_textons
Definition textons.c:122
#define TEXTONS_DICTIONARY_NUMBER
Definition textons.c:108
uint8_t FULL_SAMPLING
Definition textons.c:126
#define TEXTONS_N_TEXTONS
Definition textons.c:73
void DictionaryTrainingYUV(uint8_t *frame, uint16_t width, uint16_t height)
Function that performs one pass for dictionary training.
Definition textons.c:227
uint8_t dictionary_ready
Definition textons.c:132
static FILE * dictionary_logger
Definition textons.c:136
uint32_t n_samples_image
Definition textons.c:125
uint32_t learned_samples
Definition textons.c:40
float get_entropy(float *p_dist, int D)
Function that calculates a base-2 Shannon entropy for a probability distribution.
Definition textons.c:594
#define TEXTONS_DICTIONARY_PATH
Definition textons.c:113
uint8_t dictionary_initialized
Definition textons.c:41
float **** dictionary
Definition textons.c:39
uint8_t alpha_uint
Definition textons.c:121
#define MAX_N_TEXTONS
Definition textons.c:44
#define TEXTONS_LOAD_DICTIONARY
Definition textons.c:58
uint8_t reinitialize_dictionary
Definition textons.c:120
float alpha
Definition textons.c:133
#define TEXTONS_BORDER_HEIGHT
Definition textons.c:103
void textons_stop(void)
Definition textons.c:583
void textons_init(void)
Initialize.
Definition textons.c:562
void DistributionExtraction(uint8_t *frame, uint16_t width, uint16_t height)
Function that extracts a texton histogram from an image.
Definition textons.c:372
uint32_t border_width
Definition textons.c:127
uint32_t border_height
Definition textons.c:128
#define TEXTONS_N_LEARNING_SAMPLES
Definition textons.c:88
#define TEXTONS_BORDER_WIDTH
Definition textons.c:98
uint8_t dictionary_number
Definition textons.c:129
#define TEXTONS_RUN
Definition textons.c:48
#define TEXTONS_N_SAMPLES
Definition textons.c:78
#define TEXTONS_REINITIALIZE_DICTIONARY
Definition textons.c:63
struct image_t * texton_func(struct image_t *img, UNUSED uint8_t p)
Main texton processing function that first either loads or learns a dictionary and then extracts the ...
Definition textons.c:144
uint8_t running
Definition textons.c:118
#define TEXTONS_FULL_SAMPLING
Definition textons.c:93
Takes an image and represents the texture and colors in the image with a texton histogram.
static float D
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.