annotate elbg.c @ 12105:d6e87496883b libavcodec

ARM: set section to .text in 'function' macro This ensures code always goes into the .text section and avoids the need to specify it explicitly after changing sections.
author mru
date Wed, 07 Jul 2010 20:09:41 +0000
parents 25e9cb2b9477
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
1 /*
5219
661eff5542cb Add my last name to copyright headers
vitor
parents: 5122
diff changeset
2 * Copyright (C) 2007 Vitor Sessak <vitor1001@gmail.com>
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
3 *
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
4 * This file is part of FFmpeg.
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
5 *
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
6 * FFmpeg is free software; you can redistribute it and/or
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
7 * modify it under the terms of the GNU Lesser General Public
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
8 * License as published by the Free Software Foundation; either
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
9 * version 2.1 of the License, or (at your option) any later version.
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
10 *
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
11 * FFmpeg is distributed in the hope that it will be useful,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
14 * Lesser General Public License for more details.
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
15 *
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
16 * You should have received a copy of the GNU Lesser General Public
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
17 * License along with FFmpeg; if not, write to the Free Software
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
19 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
20
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
21 /**
11644
7dd2a45249a9 Remove explicit filename from Doxygen @file commands.
diego
parents: 10762
diff changeset
22 * @file
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
23 * Codebook Generator using the ELBG algorithm
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
24 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
25
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
26 #include <string.h>
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
27
9154
aa459306ee59 Use FLG pseudo-random number generator in RoQ and ELBG
vitor
parents: 8718
diff changeset
28 #include "libavutil/lfg.h"
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
29 #include "elbg.h"
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
30 #include "avcodec.h"
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
31
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
32 #define DELTA_ERR_MAX 0.1 ///< Precision of the ELBG algorithm (as percentual error)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
33
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
34 /**
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
35 * In the ELBG jargon, a cell is the set of points that are closest to a
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
36 * codebook entry. Not to be confused with a RoQ Video cell. */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
37 typedef struct cell_s {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
38 int index;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
39 struct cell_s *next;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
40 } cell;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
41
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
42 /**
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
43 * ELBG internal data
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
44 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
45 typedef struct{
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
46 int error;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
47 int dim;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
48 int numCB;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
49 int *codebook;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
50 cell **cells;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
51 int *utility;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
52 int *utility_inc;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
53 int *nearest_cb;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
54 int *points;
9154
aa459306ee59 Use FLG pseudo-random number generator in RoQ and ELBG
vitor
parents: 8718
diff changeset
55 AVLFG *rand_state;
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
56 int *scratchbuf;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
57 } elbg_data;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
58
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
59 static inline int distance_limited(int *a, int *b, int dim, int limit)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
60 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
61 int i, dist=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
62 for (i=0; i<dim; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
63 dist += (a[i] - b[i])*(a[i] - b[i]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
64 if (dist > limit)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
65 return INT_MAX;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
66 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
67
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
68 return dist;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
69 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
70
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
71 static inline void vect_division(int *res, int *vect, int div, int dim)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
72 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
73 int i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
74 if (div > 1)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
75 for (i=0; i<dim; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
76 res[i] = ROUNDED_DIV(vect[i],div);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
77 else if (res != vect)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
78 memcpy(res, vect, dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
79
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
80 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
81
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
82 static int eval_error_cell(elbg_data *elbg, int *centroid, cell *cells)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
83 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
84 int error=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
85 for (; cells; cells=cells->next)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
86 error += distance_limited(centroid, elbg->points + cells->index*elbg->dim, elbg->dim, INT_MAX);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
87
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
88 return error;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
89 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
90
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
91 static int get_closest_codebook(elbg_data *elbg, int index)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
92 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
93 int i, pick=0, diff, diff_min = INT_MAX;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
94 for (i=0; i<elbg->numCB; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
95 if (i != index) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
96 diff = distance_limited(elbg->codebook + i*elbg->dim, elbg->codebook + index*elbg->dim, elbg->dim, diff_min);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
97 if (diff < diff_min) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
98 pick = i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
99 diff_min = diff;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
100 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
101 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
102 return pick;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
103 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
104
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
105 static int get_high_utility_cell(elbg_data *elbg)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
106 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
107 int i=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
108 /* Using linear search, do binary if it ever turns to be speed critical */
9160
678152bdb3a1 Fix bug when elbg->utility_inc[elbg->numCB-1] == 1
vitor
parents: 9154
diff changeset
109 int r = av_lfg_get(elbg->rand_state)%elbg->utility_inc[elbg->numCB-1] + 1;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
110 while (elbg->utility_inc[i] < r)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
111 i++;
7352
c2318e551ff5 When picking a "high utility centroid" do not pick one
vitor
parents: 7351
diff changeset
112
c2318e551ff5 When picking a "high utility centroid" do not pick one
vitor
parents: 7351
diff changeset
113 assert(!elbg->cells[i]);
c2318e551ff5 When picking a "high utility centroid" do not pick one
vitor
parents: 7351
diff changeset
114
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
115 return i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
116 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
117
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
118 /**
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
119 * Implementation of the simple LBG algorithm for just two codebooks
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
120 */
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
121 static int simple_lbg(elbg_data *elbg,
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
122 int dim,
5122
753230e2dcf0 Cygwin compatibility workaround
benoit
parents: 5095
diff changeset
123 int *centroid[3],
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
124 int newutility[3],
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
125 int *points,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
126 cell *cells)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
127 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
128 int i, idx;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
129 int numpoints[2] = {0,0};
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
130 int *newcentroid[2] = {
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
131 elbg->scratchbuf + 3*dim,
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
132 elbg->scratchbuf + 4*dim
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
133 };
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
134 cell *tempcell;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
135
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
136 memset(newcentroid[0], 0, 2 * dim * sizeof(*newcentroid[0]));
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
137
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
138 newutility[0] =
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
139 newutility[1] = 0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
140
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
141 for (tempcell = cells; tempcell; tempcell=tempcell->next) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
142 idx = distance_limited(centroid[0], points + tempcell->index*dim, dim, INT_MAX)>=
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
143 distance_limited(centroid[1], points + tempcell->index*dim, dim, INT_MAX);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
144 numpoints[idx]++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
145 for (i=0; i<dim; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
146 newcentroid[idx][i] += points[tempcell->index*dim + i];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
147 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
148
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
149 vect_division(centroid[0], newcentroid[0], numpoints[0], dim);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
150 vect_division(centroid[1], newcentroid[1], numpoints[1], dim);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
151
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
152 for (tempcell = cells; tempcell; tempcell=tempcell->next) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
153 int dist[2] = {distance_limited(centroid[0], points + tempcell->index*dim, dim, INT_MAX),
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
154 distance_limited(centroid[1], points + tempcell->index*dim, dim, INT_MAX)};
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
155 int idx = dist[0] > dist[1];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
156 newutility[idx] += dist[idx];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
157 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
158
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
159 return newutility[0] + newutility[1];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
160 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
161
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
162 static void get_new_centroids(elbg_data *elbg, int huc, int *newcentroid_i,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
163 int *newcentroid_p)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
164 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
165 cell *tempcell;
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
166 int *min = newcentroid_i;
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
167 int *max = newcentroid_p;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
168 int i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
169
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
170 for (i=0; i< elbg->dim; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
171 min[i]=INT_MAX;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
172 max[i]=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
173 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
174
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
175 for (tempcell = elbg->cells[huc]; tempcell; tempcell = tempcell->next)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
176 for(i=0; i<elbg->dim; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
177 min[i]=FFMIN(min[i], elbg->points[tempcell->index*elbg->dim + i]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
178 max[i]=FFMAX(max[i], elbg->points[tempcell->index*elbg->dim + i]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
179 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
180
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
181 for (i=0; i<elbg->dim; i++) {
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
182 int ni = min[i] + (max[i] - min[i])/3;
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
183 int np = min[i] + (2*(max[i] - min[i]))/3;
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
184 newcentroid_i[i] = ni;
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
185 newcentroid_p[i] = np;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
186 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
187 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
188
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
189 /**
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
190 * Add the points in the low utility cell to its closest cell. Split the high
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
191 * utility cell, putting the separed points in the (now empty) low utility
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
192 * cell.
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
193 *
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
194 * @param elbg Internal elbg data
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
195 * @param indexes {luc, huc, cluc}
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
196 * @param newcentroid A vector with the position of the new centroids
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
197 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
198 static void shift_codebook(elbg_data *elbg, int *indexes,
5122
753230e2dcf0 Cygwin compatibility workaround
benoit
parents: 5095
diff changeset
199 int *newcentroid[3])
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
200 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
201 cell *tempdata;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
202 cell **pp = &elbg->cells[indexes[2]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
203
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
204 while(*pp)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
205 pp= &(*pp)->next;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
206
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
207 *pp = elbg->cells[indexes[0]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
208
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
209 elbg->cells[indexes[0]] = NULL;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
210 tempdata = elbg->cells[indexes[1]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
211 elbg->cells[indexes[1]] = NULL;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
212
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
213 while(tempdata) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
214 cell *tempcell2 = tempdata->next;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
215 int idx = distance_limited(elbg->points + tempdata->index*elbg->dim,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
216 newcentroid[0], elbg->dim, INT_MAX) >
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
217 distance_limited(elbg->points + tempdata->index*elbg->dim,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
218 newcentroid[1], elbg->dim, INT_MAX);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
219
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
220 tempdata->next = elbg->cells[indexes[idx]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
221 elbg->cells[indexes[idx]] = tempdata;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
222 tempdata = tempcell2;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
223 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
224 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
225
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
226 static void evaluate_utility_inc(elbg_data *elbg)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
227 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
228 int i, inc=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
229
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
230 for (i=0; i < elbg->numCB; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
231 if (elbg->numCB*elbg->utility[i] > elbg->error)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
232 inc += elbg->utility[i];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
233 elbg->utility_inc[i] = inc;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
234 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
235 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
236
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
237
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
238 static void update_utility_and_n_cb(elbg_data *elbg, int idx, int newutility)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
239 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
240 cell *tempcell;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
241
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
242 elbg->utility[idx] = newutility;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
243 for (tempcell=elbg->cells[idx]; tempcell; tempcell=tempcell->next)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
244 elbg->nearest_cb[tempcell->index] = idx;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
245 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
246
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
247 /**
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
248 * Evaluate if a shift lower the error. If it does, call shift_codebooks
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
249 * and update elbg->error, elbg->utility and elbg->nearest_cb.
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
250 *
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
251 * @param elbg Internal elbg data
12056
25e9cb2b9477 Fix misspelled parameter names in Doxygen documentation.
diego
parents: 11955
diff changeset
252 * @param idx {luc (low utility cell, huc (high utility cell), cluc (closest cell to low utility cell)}
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
253 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
254 static void try_shift_candidate(elbg_data *elbg, int idx[3])
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
255 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
256 int j, k, olderror=0, newerror, cont=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
257 int newutility[3];
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
258 int *newcentroid[3] = {
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
259 elbg->scratchbuf,
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
260 elbg->scratchbuf + elbg->dim,
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
261 elbg->scratchbuf + 2*elbg->dim
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
262 };
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
263 cell *tempcell;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
264
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
265 for (j=0; j<3; j++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
266 olderror += elbg->utility[idx[j]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
267
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
268 memset(newcentroid[2], 0, elbg->dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
269
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
270 for (k=0; k<2; k++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
271 for (tempcell=elbg->cells[idx[2*k]]; tempcell; tempcell=tempcell->next) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
272 cont++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
273 for (j=0; j<elbg->dim; j++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
274 newcentroid[2][j] += elbg->points[tempcell->index*elbg->dim + j];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
275 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
276
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
277 vect_division(newcentroid[2], newcentroid[2], cont, elbg->dim);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
278
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
279 get_new_centroids(elbg, idx[1], newcentroid[0], newcentroid[1]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
280
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
281 newutility[2] = eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[0]]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
282 newutility[2] += eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[2]]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
283
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
284 newerror = newutility[2];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
285
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
286 newerror += simple_lbg(elbg, elbg->dim, newcentroid, newutility, elbg->points,
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
287 elbg->cells[idx[1]]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
288
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
289 if (olderror > newerror) {
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
290 shift_codebook(elbg, idx, newcentroid);
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
291
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
292 elbg->error += newerror - olderror;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
293
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
294 for (j=0; j<3; j++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
295 update_utility_and_n_cb(elbg, idx[j], newutility[j]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
296
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
297 evaluate_utility_inc(elbg);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
298 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
299 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
300
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
301 /**
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
302 * Implementation of the ELBG block
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
303 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
304 static void do_shiftings(elbg_data *elbg)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
305 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
306 int idx[3];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
307
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
308 evaluate_utility_inc(elbg);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
309
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
310 for (idx[0]=0; idx[0] < elbg->numCB; idx[0]++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
311 if (elbg->numCB*elbg->utility[idx[0]] < elbg->error) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
312 if (elbg->utility_inc[elbg->numCB-1] == 0)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
313 return;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
314
7354
456957d86106 My commit at r14340 was not the right solution. For a monochromatic
vitor
parents: 7353
diff changeset
315 idx[1] = get_high_utility_cell(elbg);
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
316 idx[2] = get_closest_codebook(elbg, idx[0]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
317
7354
456957d86106 My commit at r14340 was not the right solution. For a monochromatic
vitor
parents: 7353
diff changeset
318 if (idx[1] != idx[0] && idx[1] != idx[2])
456957d86106 My commit at r14340 was not the right solution. For a monochromatic
vitor
parents: 7353
diff changeset
319 try_shift_candidate(elbg, idx);
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
320 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
321 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
322
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
323 #define BIG_PRIME 433494437LL
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
324
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
325 void ff_init_elbg(int *points, int dim, int numpoints, int *codebook,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
326 int numCB, int max_steps, int *closest_cb,
9154
aa459306ee59 Use FLG pseudo-random number generator in RoQ and ELBG
vitor
parents: 8718
diff changeset
327 AVLFG *rand_state)
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
328 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
329 int i, k;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
330
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
331 if (numpoints > 24*numCB) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
332 /* ELBG is very costly for a big number of points. So if we have a lot
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
333 of them, get a good initial codebook to save on iterations */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
334 int *temp_points = av_malloc(dim*(numpoints/8)*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
335 for (i=0; i<numpoints/8; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
336 k = (i*BIG_PRIME) % numpoints;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
337 memcpy(temp_points + i*dim, points + k*dim, dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
338 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
339
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
340 ff_init_elbg(temp_points, dim, numpoints/8, codebook, numCB, 2*max_steps, closest_cb, rand_state);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
341 ff_do_elbg(temp_points, dim, numpoints/8, codebook, numCB, 2*max_steps, closest_cb, rand_state);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
342
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
343 av_free(temp_points);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
344
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
345 } else // If not, initialize the codebook with random positions
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
346 for (i=0; i < numCB; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
347 memcpy(codebook + i*dim, points + ((i*BIG_PRIME)%numpoints)*dim,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
348 dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
349
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
350 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
351
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
352 void ff_do_elbg(int *points, int dim, int numpoints, int *codebook,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
353 int numCB, int max_steps, int *closest_cb,
9154
aa459306ee59 Use FLG pseudo-random number generator in RoQ and ELBG
vitor
parents: 8718
diff changeset
354 AVLFG *rand_state)
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
355 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
356 int dist;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
357 elbg_data elbg_d;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
358 elbg_data *elbg = &elbg_d;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
359 int i, j, k, last_error, steps=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
360 int *dist_cb = av_malloc(numpoints*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
361 int *size_part = av_malloc(numCB*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
362 cell *list_buffer = av_malloc(numpoints*sizeof(cell));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
363 cell *free_cells;
10762
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
364 int best_dist, best_idx = 0;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
365
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
366 elbg->error = INT_MAX;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
367 elbg->dim = dim;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
368 elbg->numCB = numCB;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
369 elbg->codebook = codebook;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
370 elbg->cells = av_malloc(numCB*sizeof(cell *));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
371 elbg->utility = av_malloc(numCB*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
372 elbg->nearest_cb = closest_cb;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
373 elbg->points = points;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
374 elbg->utility_inc = av_malloc(numCB*sizeof(int));
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
375 elbg->scratchbuf = av_malloc(5*dim*sizeof(int));
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
376
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
377 elbg->rand_state = rand_state;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
378
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
379 do {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
380 free_cells = list_buffer;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
381 last_error = elbg->error;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
382 steps++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
383 memset(elbg->utility, 0, numCB*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
384 memset(elbg->cells, 0, numCB*sizeof(cell *));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
385
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
386 elbg->error = 0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
387
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
388 /* This loop evaluate the actual Voronoi partition. It is the most
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
389 costly part of the algorithm. */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
390 for (i=0; i < numpoints; i++) {
10762
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
391 best_dist = distance_limited(elbg->points + i*elbg->dim, elbg->codebook + best_idx*elbg->dim, dim, INT_MAX);
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
392 for (k=0; k < elbg->numCB; k++) {
10762
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
393 dist = distance_limited(elbg->points + i*elbg->dim, elbg->codebook + k*elbg->dim, dim, best_dist);
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
394 if (dist < best_dist) {
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
395 best_dist = dist;
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
396 best_idx = k;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
397 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
398 }
10762
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
399 elbg->nearest_cb[i] = best_idx;
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
400 dist_cb[i] = best_dist;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
401 elbg->error += dist_cb[i];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
402 elbg->utility[elbg->nearest_cb[i]] += dist_cb[i];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
403 free_cells->index = i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
404 free_cells->next = elbg->cells[elbg->nearest_cb[i]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
405 elbg->cells[elbg->nearest_cb[i]] = free_cells;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
406 free_cells++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
407 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
408
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
409 do_shiftings(elbg);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
410
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
411 memset(size_part, 0, numCB*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
412
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
413 memset(elbg->codebook, 0, elbg->numCB*dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
414
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
415 for (i=0; i < numpoints; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
416 size_part[elbg->nearest_cb[i]]++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
417 for (j=0; j < elbg->dim; j++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
418 elbg->codebook[elbg->nearest_cb[i]*elbg->dim + j] +=
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
419 elbg->points[i*elbg->dim + j];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
420 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
421
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
422 for (i=0; i < elbg->numCB; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
423 vect_division(elbg->codebook + i*elbg->dim,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
424 elbg->codebook + i*elbg->dim, size_part[i], elbg->dim);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
425
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
426 } while(((last_error - elbg->error) > DELTA_ERR_MAX*elbg->error) &&
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
427 (steps < max_steps));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
428
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
429 av_free(dist_cb);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
430 av_free(size_part);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
431 av_free(elbg->utility);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
432 av_free(list_buffer);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
433 av_free(elbg->cells);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
434 av_free(elbg->utility_inc);
11955
d94cbfa7a170 elbg: remove VLAs
mru
parents: 11644
diff changeset
435 av_free(elbg->scratchbuf);
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
436 }