-
Notifications
You must be signed in to change notification settings - Fork 0
/
ip_lib.h
344 lines (286 loc) · 12.1 KB
/
ip_lib.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
/**
* CIMP - C Image Manipulation Program
* (https://github.com/EPMatt/cimp)
*
* (C) 2020
*
* Ina Popescu (https://github.com/ina-pps)
* Matteo Agnoletto (https://github.com/EPMatt)
* Lorenzo Donatelli (https://github.com/whitedemond)
*
* For licensing conditions related to this project, see LICENSE
*
*/
/*
Laboratorio di programmazione A.A. 2019/2020
Sebastiano Vascon
*/
#ifndef IP_LIB_H
#define IP_LIB_H
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <assert.h>
#include "bmp.h"
#define FLT_MAX 3.402823466e+38F /* max value */
#define FLT_MIN 1.175494351e-38F /* min positive value */
#define PI 3.141592654
typedef struct
{
float min;
float max;
float mean;
} stats;
typedef struct
{
unsigned int w; /* <- larghezza */
unsigned int h; /* <- altezza */
unsigned int k; /* <- canali */
stats *stat; /* <- statistiche per canale */
float ***data; /* <- matrice 3D di valori float */
} ip_mat;
/* HELPERS */
/* le funzioni, i tipi e le costanti sono pensate per utilizzo interno alla libreria */
/* valori massimi e minimi, in virgola mobile, che un pixel può assumere */
#define MAX_PIXEL_FLOAT 255.0
#define MIN_PIXEL_FLOAT 0.0
/* costanti utilizzati nel richiamare la funzione ip_mat_puts */
#define NO_COMPUTE_STATS 0
#define COMPUTE_STATS 1
/* tipo canale: matrice di float */
typedef struct
{
float **data;
unsigned int h;
unsigned int w;
} channel_t;
/* data una ip_mat, ottieni una struttura canale, con riferimento al ch-esimo canale */
channel_t get_channel(ip_mat const *a, unsigned int ch);
/*
* posiziona il contenuto del canale source nel canale dest, posizionando la cella 0,0 del canale source alla posizione row,col del canale dest
* copia il contenuto di source fino a raggiungere il limite del canale dest, e soltanto se row,col sono indici validi per il canale dest
* */
void channel_puts(channel_t const dest, channel_t const source, unsigned int row, unsigned int col);
/*
* posiziona il contenuto della matrice source nella matrice dest, partendo dalla posizione specificata
* per tutti i canali di source (massimo il numero di canali di dest) posiziona la cella 0,0 del canale di source alla posizione row,col del canale di dest
* copia il contenuto di source fino a raggiungere il limite del canale di dest, e soltanto se row,col sono indici validi per la matrice dest
* */
void ip_mat_puts(ip_mat *dest, ip_mat const *source, unsigned int row, unsigned int col, int do_compute_stats);
/**
* restituisce un messaggio di errore nel caso in cui la matrice passata sia NULL
**/
void not_null_ip_mat(ip_mat const *a);
/*funzione aux min che trova il minimo di un determinato canale k, riceve in input una ip_mat a e un canale k e restituisce un float che è il minimo */
float min(ip_mat *a, unsigned int k);
/*funzione aux che mi calcola il valore massimo di un determinato canale k*/
float max(ip_mat *a, unsigned int k);
/*mean è la funzione aux che mi permette di calcolare la media degli elementi che si trovano in un determinato canale k*/
float mean(ip_mat *a, unsigned int k);
/* restringi il valore fornito all'interno del range low...high, estremi inclusi */
float restrict_val(float val, float low, float high);
/**
* Calcola la media per il pixel (i,j) sui k canali della matrice passata come parametro.
*
* */
float mean_pixel_channel(ip_mat *a, unsigned int i, unsigned int j);
/**
* Controlla se due ip_mat hanno le stesse dimensioni oppure no
* esce dal programma nel momento in cui una delle dimensioni é diversa
*/
void equal_dimension(ip_mat *a, ip_mat *b);
/* calcola la somma di prodotti tra il kernel fornito e il canale fornito, partendo dalla posizione (start_h,start_w) del canale */
float convolve_channel(channel_t ch, channel_t filter, unsigned int start_h, unsigned int start_w);
/* END HELPERS */
/**** PARTE 1: TIPO DI DATI ip_mat E MEMORIA ****/
/* Inizializza una ip_mat con dimensioni h w e k. Ogni elemento è inizializzato a v.
* Inoltre crea un vettore di stats per contenere le statische sui singoli canali.
* */
ip_mat *ip_mat_create(unsigned int h, unsigned int w, unsigned int k, float v);
/* Libera la memoria (data, stat e la struttura)
*
* se la variabile "a" è NULL non fa nulla.
*
* */
void ip_mat_free(ip_mat *a);
/* Restituisce il valore in posizione i,j,k */
float get_val(ip_mat *a, unsigned int i, unsigned int j, unsigned int k);
/* Setta il valore in posizione i,j,k a v*/
void set_val(ip_mat *a, unsigned int i, unsigned int j, unsigned int k, float v);
/* Calcola il valore minimo, il massimo e la media per ogni canale
* e li salva dentro la struttura ip_mat stats
* */
void compute_stats(ip_mat *t);
/* Inizializza una ip_mat con dimensioni w h e k.
* Ogni elemento è generato da una gaussiana con media mean e deviazione std */
void ip_mat_init_random(ip_mat *t, float mean, float std);
/* Crea una copia di una ip_mat e lo restituisce in output */
ip_mat *ip_mat_copy(ip_mat *in);
/* Restituisce una sotto-matrice, ovvero la porzione individuata da:
* t->data[row_start...row_end][col_start...col_end][0...k]
* La terza dimensione la riportiamo per intero, stiamo in sostanza prendendo un sottoinsieme
* delle righe e delle colonne.
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
* */
ip_mat *ip_mat_subset(ip_mat *t, unsigned int row_start, unsigned int row_end, unsigned int col_start, unsigned int col_end);
/* Concatena due ip_mat su una certa dimensione.
* Ad esempio:
* ip_mat_concat(ip_mat * a, ip_mat * b, 0);
* produrrà un nuovo ip_mat di dimensioni:
* out.h = a.h + b.h
* out.w = a.w = b.w
* out.k = a.k = b.k
*
* ip_mat_concat(ip_mat * a, ip_mat * b, 1);
* produrrà un nuovo ip_mat di dimensioni:
* out.h = a.h = b.h
* out.w = a.w + b.w
* out.k = a.k = b.k
*
* ip_mat_concat(ip_mat * a, ip_mat * b, 2);
* produrrà un nuovo ip_mat di dimensioni:
* out.h = a.h = b.h
* out.w = a.w = b.w
* out.k = a.k + b.k
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
* */
ip_mat *ip_mat_concat(ip_mat *a, ip_mat *b, int dimensione);
/**** PARTE 1: OPERAZIONI MATEMATICHE FRA IP_MAT ****/
/* Esegue la somma di due ip_mat (tutte le dimensioni devono essere identiche).
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
*/
ip_mat *ip_mat_sum(ip_mat *a, ip_mat *b);
/* Esegue la sottrazione di due ip_mat (tutte le dimensioni devono essere identiche)
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
*/
ip_mat *ip_mat_sub(ip_mat *a, ip_mat *b);
/* Moltiplica un ip_mat per uno scalare c. Si moltiplica c per tutti gli elementi di "a"
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
*/
ip_mat *ip_mat_mul_scalar(ip_mat *a, float c);
/* Aggiunge ad un ip_mat uno scalare c e lo restituisce in un nuovo tensore in output.
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
*/
ip_mat *ip_mat_add_scalar(ip_mat *a, float c);
/* Calcola la media di due ip_mat a e b. La media si calcola per coppie delle due matrici aventi gli stessi indici
* C[i][j][k]= (A[i][j][k]+B[i]j[k])/2
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
*/
ip_mat *ip_mat_mean(ip_mat *a, ip_mat *b);
/**** PARTE 2: SEMPLICI OPERAZIONI SU IMMAGINI ****/
/* Converte un'immagine RGB ad una immagine a scala di grigio.
* Quest'operazione viene fatta calcolando la media per ogni pixel sui 3 canali
* e creando una nuova immagine avente per valore di un pixel su ogni canale la media appena calcolata.
* Avremo quindi che tutti i canali saranno uguali.
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
* */
ip_mat *ip_mat_to_gray_scale(ip_mat *in);
/* Effettua la fusione (combinazione convessa) di due immagini.
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
*
* Le variabili "a" e "b" devono avere le stesse dimensioni
*/
ip_mat *ip_mat_blend(ip_mat *a, ip_mat *b, float alpha);
/* Operazione di brightening: aumenta la luminosità dell'immagine
* aggiunge ad ogni pixel un certo valore
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
*/
ip_mat *ip_mat_brighten(ip_mat *a, float bright);
/* Operazione di corruzione con rumore gaussiano:
* Aggiunge del rumore gaussiano all'immagine, il rumore viene enfatizzato
* per mezzo della variabile amount.
*
* out = a + gauss_noise*amount
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
* */
ip_mat *ip_mat_corrupt(ip_mat *a, float amount);
/**** PARTE 3: CONVOLUZIONE E FILTRI *****/
/* Effettua la convoluzione di un ip_mat "a" con un ip_mat "f".
* La funzione restituisce un ip_mat delle stesse dimensioni di "a".
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
*/
ip_mat *ip_mat_convolve(ip_mat *a, ip_mat *f);
/* Aggiunge un padding all'immagine. Il padding verticale è pad_h mentre quello
* orizzontale è pad_w.
* L'output sarà un'immagine di dimensioni:
* out.h = a.h + 2*pad_h;
* out.w = a.w + 2*pad_w;
* out.k = a.k
* con valori nulli sui bordi corrispondenti al padding e l'immagine "a" riportata
* nel centro.
*
* I parametri della funzione non subiscono modiche, il risultato viene salvato e restituito in output
* all'interno di una nuova ip_mat.
*/
ip_mat *ip_mat_padding(ip_mat *a, unsigned int pad_h, unsigned int pad_w);
/* Crea un filtro di sharpening */
ip_mat *create_sharpen_filter();
/* Crea un filtro per rilevare i bordi */
ip_mat *create_edge_filter();
/* Crea un filtro per aggiungere profondità */
ip_mat *create_emboss_filter();
/* Crea un filtro medio per la rimozione del rumore */
ip_mat *create_average_filter(unsigned int h, unsigned int w, unsigned int k);
/* Crea un filtro gaussiano per la rimozione del rumore */
ip_mat *create_gaussian_filter(unsigned int h, unsigned int w, unsigned int k, float sigma);
/* Effettua una riscalatura dei dati tale che i valori siano in [0,new_max].
* Utilizzate il metodo compute_stat per ricavarvi il min, max per ogni canale.
*
* I valori sono scalati tramite la formula (valore-min)/(max - min)
*
* Si considera ogni indice della terza dimensione indipendente, quindi l'operazione
* di scalatura va ripetuta per ogni "fetta" della matrice 3D.
* Successivamente moltiplichiamo per new_max gli elementi della matrice in modo da ottenere un range
* di valori in [0,new_max].
*
* Il risultato dell'operazione si salva in t
* */
void rescale(ip_mat *t, float new_max);
/* Nell'operazione di clamping i valori <low si convertono in low e i valori >high in high.
*
* Il risultato dell'operazione si salva in t
* */
void clamp(ip_mat *t, float low, float high);
/**** METODI GIA' IMPLEMENTATI ****/
/* Genera dei numeri casuali con distribuzione Normale
* https://en.wikipedia.org/wiki/Box%E2%80%93Muller_transform
* caratterizzata da media = mu e deviazione = std
* */
float get_normal_random(float media, float std);
/* Converte una Bitmap in una ip_mat*/
ip_mat *bitmap_to_ip_mat(Bitmap *img);
/* Converte una ip_mat in una bitmap*/
Bitmap *ip_mat_to_bitmap(ip_mat *t);
/* Visualizza i dati stampando in ordine le matrici rispetto
* la terza dimensione.
* Prima stamperemo t->data[...][...][0] poi t->data[...][...][1] ...
* */
void ip_mat_show(ip_mat *t);
/* Visualizza a video le statistiche per ogni canale.
* */
void ip_mat_show_stats(ip_mat *t);
#endif /*IP_LIB_H*/