source: GTP/trunk/Lib/Geom/shared/GTGeometry/src/libs/vmi/src/metrics.cpp @ 2090

Revision 2090, 10.9 KB checked in by gumbau, 17 years ago (diff)
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <memory.h>
4#include <math.h>
5
6#define LOG2 (double)0.69314718055994530941723212145818
7#define log2(x) (log((x))/LOG2)
8
9#include "../include/metrics.h"
10#include "../include/histogram.h"
11#include "../include/global.h"
12
13using namespace VMI;
14
15GLdouble VMI::computeMeanProjAreaNoBG(GLuint **histogram, GLuint numCameras, int t) {
16    GLuint i;
17    GLdouble mean_proj_area = 0.0;
18
19    for (i=0; i<numCameras; i++) {
20        mean_proj_area += histogram[i][t];
21    }
22
23    return (mean_proj_area / (GLdouble)numCameras);
24}
25
26GLdouble VMI::computeMeanProjArea(GLuint **histogram, GLuint numCameras, int t) {
27        GLuint i;
28        GLdouble mean_proj_area = 0.0, total_proj_area, resolution = width * height;
29
30        for (i=0; i<numCameras; i++) {
31                total_proj_area = resolution - histogram[i][0];
32
33                mean_proj_area += histogram[i][t] / total_proj_area;
34        }
35
36        return (mean_proj_area / (GLdouble)numCameras);
37}
38///////////////////////////////////////////////////////////////////////////////
39// Mutual Information
40GLdouble VMI::computeMI(Mesh *mesh, GLuint **histogram, GLuint numCameras, GLuint cam) {
41    GLdouble I = 0.0, pov, po, total_proj_area = width * height;
42    GLuint i;
43   
44    for (i=0; i<mesh->numTriangles; i++) {
45       
46        if (mesh->triangles[i].enable == TRUE) {
47           
48            pov = (GLdouble)histogram[cam][i + 1] / total_proj_area;
49           
50            po = computeMeanProjAreaNoBG(histogram, numCameras, i + 1) / total_proj_area;
51           
52            if ((pov > 0.0) && (po > 0.0))
53                I += (pov * log2(pov / po));
54        }
55    }
56
57    // take into account the background
58    pov = (GLdouble)histogram[cam][0] / total_proj_area;
59   
60    po = computeMeanProjAreaNoBG(histogram, numCameras, 0) / total_proj_area;
61   
62    if ((pov > 0.0) && (po > 0.0))
63        I += (pov * log2(pov / po));
64   
65    return (I / numCameras);
66}
67
68GLdouble VMI::decMI(GLdouble I, GLuint **histogram, GLuint numCameras, GLuint cam, Change *c) {
69    GLdouble newI = I * numCameras,
70             pov = 0.0, po;
71    GLsizei total_proj_area = width * height;
72    GLint i, t;
73
74    // decrease entropy of deleted triangles
75    for (i=0; i<c->numDel; i++) {
76       
77        t = c->deleted[i].id;
78        // projected pixels of triangle t is at t + 1 position
79        pov = (GLdouble)histogram[cam][t + 1] / total_proj_area;
80       
81        po = computeMeanProjAreaNoBG(histogram, numCameras, t + 1) / total_proj_area;
82       
83        if ((pov > 0.0) && (po > 0.0))
84            newI -= (pov * log2(pov / po));
85    }
86
87    // decrease entropy of modified triangles
88    for (i=0; i<c->numMod; i++) {
89       
90        t = c->modified[i].id;
91        // projected pixels of triangle t is at t + 1 position
92        pov = (GLdouble)histogram[cam][t + 1] / total_proj_area;
93       
94        po = computeMeanProjAreaNoBG(histogram, numCameras, t + 1) / total_proj_area;
95       
96        if ((pov > 0.0) && (po > 0.0))
97            newI -= (pov * log2(pov / po));
98    }
99
100    // take into account the background
101    pov = (GLdouble)histogram[cam][0] / total_proj_area;
102   
103    po = computeMeanProjAreaNoBG(histogram, numCameras, 0) / total_proj_area;
104   
105    if ((pov > 0.0) && (po > 0.0))
106        newI -= (pov * log2(pov / po));
107
108    return (newI / numCameras);
109}
110
111GLdouble VMI::incMI(GLdouble I, GLuint **histogram, GLuint numCameras, GLuint cam, Change *c) {
112    GLdouble newI = I * numCameras,
113             pov = 0.0, po;
114    GLsizei total_proj_area = width * height;
115    GLuint i, t;
116
117    // increase entropy of modified triangles
118    for (i=0; i<(GLuint)c->numMod; i++) {
119       
120        t = c->modified[i].id;
121        // projected pixels of triangle t is at t + 1 position
122        pov = (GLdouble)histogram[cam][t + 1] / total_proj_area;
123       
124        po = computeMeanProjAreaNoBG(histogram, numCameras, t + 1) / total_proj_area;
125       
126        if ((pov > 0.0) && (po > 0.0))
127            newI += (pov * log2(pov / po));
128    }
129
130    // take into account the background
131    pov = (GLdouble)histogram[cam][0] / total_proj_area;
132   
133    po = computeMeanProjAreaNoBG(histogram, numCameras, 0) / total_proj_area;
134   
135    if ((pov > 0.0) && (po > 0.0))
136        newI += (pov * log2(pov / po));
137
138    return (newI / numCameras);
139}
140///////////////////////////////////////////////////////////////////////////////
141// Kullback-Leibler divergence
142GLdouble VMI::computeKL(Mesh *mesh, GLuint *histogram) {
143    GLdouble I = 0.0,
144             total_real_area = 0.0, pi, tri_area;
145    GLsizei  total_proj_area = (width * height) - histogram[0];
146    GLuint   i;
147
148    // Compute total real area of all triangles
149    for (i=0; i<mesh->numTriangles; i++) {
150        if (mesh->triangles[i].enable == TRUE) {
151            total_real_area += mesh->triangles[i].area;
152        }
153    }
154
155    for (i=0; i<mesh->numTriangles; i++) { // don't take into account the background
156       
157        if (mesh->triangles[i].enable == TRUE) {
158            pi = (GLdouble)histogram[i + 1] / total_proj_area;
159           
160            tri_area = mesh->triangles[i].area;
161           
162            if ((pi > 0.0) && (tri_area != 0.0))
163                I += (pi * log2((pi * total_real_area) / tri_area));
164        }
165    }
166
167    return I;
168}
169
170// Hellinger divergence (square root)
171GLdouble VMI::computeHE(Mesh *mesh, GLuint *histogram) {
172    GLdouble I = 0.0, temp,
173             total_real_area = 0.0, pi, qi;
174    GLsizei  total_proj_area = (width * height) - histogram[0];
175    GLuint i;
176   
177    // Compute total real area of all triangles
178    for (i=0; i<mesh->numTriangles; i++) {
179        if (mesh->triangles[i].enable == TRUE) {
180            total_real_area += mesh->triangles[i].area;
181        }
182    }
183
184    // sqrt( 1/2 * \Sum_i (sqrt(p_i) - sqrt(q_i))^2)
185    for (i=0; i<mesh->numTriangles; i++) { // + 1 because the first is the background
186        if (mesh->triangles[i].enable == TRUE) {
187            pi = (GLdouble)histogram[i + 1] / total_proj_area;
188           
189            qi = mesh->triangles[i].area / total_real_area;
190           
191            if ((pi > 0.0) && (qi > 0.0)) {
192               
193                temp = sqrt(pi) - sqrt(qi);
194               
195                I += (temp * temp);
196            }
197        }
198    }
199
200    return sqrt(I / 2.0);
201
202}
203
204// Chi-Square divergence (square root)
205GLdouble VMI::computeCS(Mesh *mesh, GLuint *histogram) {
206    GLdouble I = 0.0,
207             total_real_area = 0.0, pi, qi;
208    GLsizei  total_proj_area = (width * height) - histogram[0];
209    GLuint i;
210   
211    /// Compute total real area of all triangles
212    for (i=0; i<mesh->numTriangles; i++) {
213        if (mesh->triangles[i].enable == TRUE) {
214            total_real_area += mesh->triangles[i].area;
215        }
216    }
217
218    // sqrt( \Sum_i ((p_i/A) - (p'_i/A'))^2 / (p'_i/A')))
219    for (i=0; i<mesh->numTriangles; i++) { // + 1 because the first is the background
220        if (mesh->triangles[i].enable == TRUE) {
221            pi = (GLdouble)histogram[i + 1] / total_proj_area;
222           
223            qi = mesh->triangles[i].area / total_real_area;
224           
225            if ((qi > 0.0) && (pi > 0.0))
226                I += (((pi - qi) * (pi - qi)) / qi);
227        }
228    }
229
230    return sqrt(I);
231}
232///////////////////////////////////////////////////////////////////////////////
233GLdouble VMI::computeEntropy(GLuint **histogram, GLuint numCameras, GLuint k) {
234        GLdouble H = 0.0, POk, pi,
235                                         total_proj_area, resolution = width * height, pv = 1.0 / (GLdouble)numCameras;
236        GLuint i;
237
238        for (i=0; i<numCameras; i++) {
239
240                total_proj_area = resolution - histogram[i][0];
241
242                POk = computeMeanProjArea(histogram, numCameras, k + 1);
243
244                if (POk > 0.0)
245                        pi = (pv * ((double)histogram[i][k + 1]) / total_proj_area ) / POk;
246                else pi = 0.0;
247
248                if (pi > 0.0)
249                        H += (pi * log2(pi));
250        }
251
252        return -H;
253}
254
255GLdouble VMI::computeMixedEntropy(GLdouble *mixed, GLuint numCameras) {
256    GLdouble H = 0.0, pi;
257    GLuint i;
258   
259    for (i=0; i<numCameras; i++) {
260       
261        pi = mixed[i];
262       
263        if (pi > 0.0)
264            H += (pi * log2(pi));
265    }
266   
267    return -H;
268}
269///////////////////////////////////////////////////////////////////////////////
270// Jensen-Shannon divergence
271GLdouble VMI::computeJS(GLuint **histogram, GLuint numCameras, GLuint j, GLuint k) {
272        GLdouble js, Wj = 0.0, Wk = 0.0, POj, POk, pj, pk, total_proj_area,
273                                         resolution = width * height, pv = 1.0 / (GLdouble)numCameras,
274                                         *mixing = (GLdouble *)malloc(numCameras * sizeof(GLdouble));
275        GLuint i;
276
277        POj = computeMeanProjArea(histogram, numCameras, j + 1);
278        POk = computeMeanProjArea(histogram, numCameras, k + 1);
279
280        //printf("%f %f\n", POj, POk);
281
282        // weights
283        if ((POj + POk) > 0.0) {
284                Wj = POj / (POj + POk);
285                Wk = POk / (POj + POk);
286        }
287
288        //printf("%f %f\n", Wj, Wk);
289
290        // Compute mixing distribution
291        for (i=0; i<numCameras; i++) {
292
293                total_proj_area = resolution - histogram[i][0];
294
295                if (POj > 0.0) pj = (pv * ((double)histogram[i][j + 1] / total_proj_area)) / POj;
296                else pj = 0.0;
297
298                if (POk > 0.0) pk = (pv * ((double)histogram[i][k + 1] / total_proj_area)) / POk;
299                else pk = 0.0;
300
301                mixing[i] = (Wj * pj) + (Wk * pk);
302        }
303
304        js = /*(POj + POk) * */(computeMixedEntropy(mixing, numCameras)
305                        - (Wj * computeEntropy(histogram, numCameras, j))
306                        - (Wk * computeEntropy(histogram, numCameras, k)));
307
308        free(mixing);
309
310        return js;
311}
312///////////////////////////////////////////////////////////////////////////////
313void VMI::getProjectedAreas(GLuint **histogram, GLuint numCameras) {
314
315    renderScene(histogram, numCameras);
316}
317
318void VMI::getProjectedAreasWin(GLuint **histogram, GLuint numCameras, Change *c) {
319
320    renderSceneWin(histogram, numCameras, c);
321}
322
323void VMI::resetProjectedAreas(GLuint **histogram, GLuint numCameras) {
324    GLuint i = 0;
325
326    // Reset the projected areas for all cameras
327    for (i=0; i<numCameras; i++)
328        resetSWHistogram(histogram[i], mesh->numTriangles);
329}
330
331GLdouble *VMI::initIs(GLuint numCameras) {
332    GLdouble *initialIs;
333
334     // Allocating memory for the metric
335    initialIs = (GLdouble *)malloc(sizeof(GLdouble) * numCameras);
336   
337    if (initialIs == NULL) {
338        fprintf(stderr, "Error allocating memory\n");
339        exit(1);
340    }
341
342    // Set metric to 0.0
343    memset(initialIs, 0, sizeof(GLdouble) * numCameras);
344
345    return initialIs;
346}
347
348void VMI::computeCameraIs(GLuint **histogram, GLuint numCameras, GLdouble *mis) {
349    GLuint i = 0;
350    GLdouble meanI = 0.0;
351
352    for (i=0;i <numCameras; i++) {
353       
354#ifdef KL // Kullback-Leibler
355        mis[i] = computeKL(mesh, histogram[i]);
356#endif
357#ifdef MI // Mutual Information
358        mis[i] = computeMI(mesh, histogram, numCameras, i);
359#endif
360#ifdef HE // Hellinger
361        mis[i] = computeHE(mesh, histogram[i]);
362#endif
363#ifdef CS // Chi-Square
364        mis[i] = computeCS(mesh, histogram[i]);
365#endif
366       
367        meanI += mis[i];
368    }
369#ifndef MI
370    meanI /= numCameras;
371#endif
372    //printIs(mis, numCameras);
373    printf("I0= %f\n", meanI);
374}
375
376void VMI::printIs(GLdouble *mis, GLuint numCameras) {
377    GLuint i;
378
379    printf("\n");
380    for (i=0; i<numCameras; i++) {
381   
382        printf("Camera %d  I = %f\n", i, mis[i]);
383    }
384}
Note: See TracBrowser for help on using the repository browser.