annotate elbg.c @ 11864:7204cb7dd601 libavcodec

Quant changes only once per MB so move the corresponding scale factor assignment out of the block decoding loop. Indeo4 doesn't use any scale table but the quant level itself as scale. Therefore access scale table only if its pointer != NULL.
author maxim
date Thu, 10 Jun 2010 17:31:12 +0000
parents 7dd2a45249a9
children d94cbfa7a170
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;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
56 } elbg_data;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
57
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
58 static inline int distance_limited(int *a, int *b, int dim, int limit)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
59 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
60 int i, dist=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
61 for (i=0; i<dim; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
62 dist += (a[i] - b[i])*(a[i] - b[i]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
63 if (dist > limit)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
64 return INT_MAX;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
65 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
66
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
67 return dist;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
68 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
69
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
70 static inline void vect_division(int *res, int *vect, int div, int dim)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
71 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
72 int i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
73 if (div > 1)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
74 for (i=0; i<dim; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
75 res[i] = ROUNDED_DIV(vect[i],div);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
76 else if (res != vect)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
77 memcpy(res, vect, dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
78
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 static int eval_error_cell(elbg_data *elbg, int *centroid, cell *cells)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
82 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
83 int error=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
84 for (; cells; cells=cells->next)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
85 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
86
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
87 return error;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
88 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
89
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
90 static int get_closest_codebook(elbg_data *elbg, int index)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
91 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
92 int i, pick=0, diff, diff_min = INT_MAX;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
93 for (i=0; i<elbg->numCB; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
94 if (i != index) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
95 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
96 if (diff < diff_min) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
97 pick = i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
98 diff_min = diff;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
99 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
100 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
101 return pick;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
102 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
103
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
104 static int get_high_utility_cell(elbg_data *elbg)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
105 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
106 int i=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
107 /* 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
108 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
109 while (elbg->utility_inc[i] < r)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
110 i++;
7352
c2318e551ff5 When picking a "high utility centroid" do not pick one
vitor
parents: 7351
diff changeset
111
c2318e551ff5 When picking a "high utility centroid" do not pick one
vitor
parents: 7351
diff changeset
112 assert(!elbg->cells[i]);
c2318e551ff5 When picking a "high utility centroid" do not pick one
vitor
parents: 7351
diff changeset
113
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
114 return i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
115 }
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 * Implementation of the simple LBG algorithm for just two codebooks
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
119 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
120 static int simple_lbg(int dim,
5122
753230e2dcf0 Cygwin compatibility workaround
benoit
parents: 5095
diff changeset
121 int *centroid[3],
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
122 int newutility[3],
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
123 int *points,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
124 cell *cells)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
125 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
126 int i, idx;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
127 int numpoints[2] = {0,0};
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
128 int newcentroid[2][dim];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
129 cell *tempcell;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
130
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
131 memset(newcentroid, 0, sizeof(newcentroid));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
132
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
133 newutility[0] =
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
134 newutility[1] = 0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
135
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
136 for (tempcell = cells; tempcell; tempcell=tempcell->next) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
137 idx = distance_limited(centroid[0], points + tempcell->index*dim, dim, INT_MAX)>=
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
138 distance_limited(centroid[1], points + tempcell->index*dim, dim, INT_MAX);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
139 numpoints[idx]++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
140 for (i=0; i<dim; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
141 newcentroid[idx][i] += points[tempcell->index*dim + i];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
142 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
143
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
144 vect_division(centroid[0], newcentroid[0], numpoints[0], dim);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
145 vect_division(centroid[1], newcentroid[1], numpoints[1], dim);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
146
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
147 for (tempcell = cells; tempcell; tempcell=tempcell->next) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
148 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
149 distance_limited(centroid[1], points + tempcell->index*dim, dim, INT_MAX)};
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
150 int idx = dist[0] > dist[1];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
151 newutility[idx] += dist[idx];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
152 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
153
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
154 return newutility[0] + newutility[1];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
155 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
156
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
157 static void get_new_centroids(elbg_data *elbg, int huc, int *newcentroid_i,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
158 int *newcentroid_p)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
159 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
160 cell *tempcell;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
161 int min[elbg->dim];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
162 int max[elbg->dim];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
163 int i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
164
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
165 for (i=0; i< elbg->dim; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
166 min[i]=INT_MAX;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
167 max[i]=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
168 }
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 (tempcell = elbg->cells[huc]; tempcell; tempcell = tempcell->next)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
171 for(i=0; i<elbg->dim; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
172 min[i]=FFMIN(min[i], elbg->points[tempcell->index*elbg->dim + i]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
173 max[i]=FFMAX(max[i], elbg->points[tempcell->index*elbg->dim + i]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
174 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
175
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 newcentroid_i[i] = min[i] + (max[i] - min[i])/3;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
178 newcentroid_p[i] = min[i] + (2*(max[i] - min[i]))/3;
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
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
182 /**
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
183 * 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
184 * utility cell, putting the separed points in the (now empty) low utility
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
185 * cell.
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
186 *
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
187 * @param elbg Internal elbg data
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
188 * @param indexes {luc, huc, cluc}
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
189 * @param newcentroid A vector with the position of the new centroids
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
190 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
191 static void shift_codebook(elbg_data *elbg, int *indexes,
5122
753230e2dcf0 Cygwin compatibility workaround
benoit
parents: 5095
diff changeset
192 int *newcentroid[3])
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
193 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
194 cell *tempdata;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
195 cell **pp = &elbg->cells[indexes[2]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
196
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
197 while(*pp)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
198 pp= &(*pp)->next;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
199
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
200 *pp = elbg->cells[indexes[0]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
201
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
202 elbg->cells[indexes[0]] = NULL;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
203 tempdata = elbg->cells[indexes[1]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
204 elbg->cells[indexes[1]] = NULL;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
205
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
206 while(tempdata) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
207 cell *tempcell2 = tempdata->next;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
208 int idx = distance_limited(elbg->points + tempdata->index*elbg->dim,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
209 newcentroid[0], elbg->dim, INT_MAX) >
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
210 distance_limited(elbg->points + tempdata->index*elbg->dim,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
211 newcentroid[1], elbg->dim, INT_MAX);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
212
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
213 tempdata->next = elbg->cells[indexes[idx]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
214 elbg->cells[indexes[idx]] = tempdata;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
215 tempdata = tempcell2;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
216 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
217 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
218
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
219 static void evaluate_utility_inc(elbg_data *elbg)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
220 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
221 int i, inc=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
222
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
223 for (i=0; i < elbg->numCB; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
224 if (elbg->numCB*elbg->utility[i] > elbg->error)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
225 inc += elbg->utility[i];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
226 elbg->utility_inc[i] = inc;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
227 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
228 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
229
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
230
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
231 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
232 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
233 cell *tempcell;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
234
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
235 elbg->utility[idx] = newutility;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
236 for (tempcell=elbg->cells[idx]; tempcell; tempcell=tempcell->next)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
237 elbg->nearest_cb[tempcell->index] = idx;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
238 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
239
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
240 /**
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
241 * Evaluate if a shift lower the error. If it does, call shift_codebooks
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
242 * and update elbg->error, elbg->utility and elbg->nearest_cb.
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
243 *
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
244 * @param elbg Internal elbg data
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
245 * @param indexes {luc (low utility cell, huc (high utility cell), cluc (closest cell to low utility cell)}
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
246 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
247 static void try_shift_candidate(elbg_data *elbg, int idx[3])
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
248 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
249 int j, k, olderror=0, newerror, cont=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
250 int newutility[3];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
251 int newcentroid[3][elbg->dim];
7353
3d9cdb5a4f01 Do declaration and initialization separately in elbg.c
vitor
parents: 7352
diff changeset
252 int *newcentroid_ptrs[3];
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
253 cell *tempcell;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
254
7353
3d9cdb5a4f01 Do declaration and initialization separately in elbg.c
vitor
parents: 7352
diff changeset
255 newcentroid_ptrs[0] = newcentroid[0];
3d9cdb5a4f01 Do declaration and initialization separately in elbg.c
vitor
parents: 7352
diff changeset
256 newcentroid_ptrs[1] = newcentroid[1];
3d9cdb5a4f01 Do declaration and initialization separately in elbg.c
vitor
parents: 7352
diff changeset
257 newcentroid_ptrs[2] = newcentroid[2];
3d9cdb5a4f01 Do declaration and initialization separately in elbg.c
vitor
parents: 7352
diff changeset
258
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
259 for (j=0; j<3; j++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
260 olderror += elbg->utility[idx[j]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
261
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
262 memset(newcentroid[2], 0, elbg->dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
263
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
264 for (k=0; k<2; k++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
265 for (tempcell=elbg->cells[idx[2*k]]; tempcell; tempcell=tempcell->next) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
266 cont++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
267 for (j=0; j<elbg->dim; j++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
268 newcentroid[2][j] += elbg->points[tempcell->index*elbg->dim + j];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
269 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
270
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
271 vect_division(newcentroid[2], newcentroid[2], cont, elbg->dim);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
272
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
273 get_new_centroids(elbg, idx[1], newcentroid[0], newcentroid[1]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
274
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
275 newutility[2] = eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[0]]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
276 newutility[2] += eval_error_cell(elbg, newcentroid[2], elbg->cells[idx[2]]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
277
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
278 newerror = newutility[2];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
279
5122
753230e2dcf0 Cygwin compatibility workaround
benoit
parents: 5095
diff changeset
280 newerror += simple_lbg(elbg->dim, newcentroid_ptrs, newutility, elbg->points,
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
281 elbg->cells[idx[1]]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
282
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
283 if (olderror > newerror) {
5122
753230e2dcf0 Cygwin compatibility workaround
benoit
parents: 5095
diff changeset
284 shift_codebook(elbg, idx, newcentroid_ptrs);
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
285
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
286 elbg->error += newerror - olderror;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
287
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
288 for (j=0; j<3; j++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
289 update_utility_and_n_cb(elbg, idx[j], newutility[j]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
290
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
291 evaluate_utility_inc(elbg);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
292 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
293 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
294
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
295 /**
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
296 * Implementation of the ELBG block
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
297 */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
298 static void do_shiftings(elbg_data *elbg)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
299 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
300 int idx[3];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
301
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
302 evaluate_utility_inc(elbg);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
303
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
304 for (idx[0]=0; idx[0] < elbg->numCB; idx[0]++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
305 if (elbg->numCB*elbg->utility[idx[0]] < elbg->error) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
306 if (elbg->utility_inc[elbg->numCB-1] == 0)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
307 return;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
308
7354
456957d86106 My commit at r14340 was not the right solution. For a monochromatic
vitor
parents: 7353
diff changeset
309 idx[1] = get_high_utility_cell(elbg);
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
310 idx[2] = get_closest_codebook(elbg, idx[0]);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
311
7354
456957d86106 My commit at r14340 was not the right solution. For a monochromatic
vitor
parents: 7353
diff changeset
312 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
313 try_shift_candidate(elbg, idx);
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
314 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
315 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
316
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
317 #define BIG_PRIME 433494437LL
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
318
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
319 void ff_init_elbg(int *points, int dim, int numpoints, int *codebook,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
320 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
321 AVLFG *rand_state)
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
322 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
323 int i, k;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
324
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
325 if (numpoints > 24*numCB) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
326 /* 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
327 of them, get a good initial codebook to save on iterations */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
328 int *temp_points = av_malloc(dim*(numpoints/8)*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
329 for (i=0; i<numpoints/8; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
330 k = (i*BIG_PRIME) % numpoints;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
331 memcpy(temp_points + i*dim, points + k*dim, dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
332 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
333
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
334 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
335 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
336
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
337 av_free(temp_points);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
338
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
339 } else // If not, initialize the codebook with random positions
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
340 for (i=0; i < numCB; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
341 memcpy(codebook + i*dim, points + ((i*BIG_PRIME)%numpoints)*dim,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
342 dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
343
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
344 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
345
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
346 void ff_do_elbg(int *points, int dim, int numpoints, int *codebook,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
347 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
348 AVLFG *rand_state)
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
349 {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
350 int dist;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
351 elbg_data elbg_d;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
352 elbg_data *elbg = &elbg_d;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
353 int i, j, k, last_error, steps=0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
354 int *dist_cb = av_malloc(numpoints*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
355 int *size_part = av_malloc(numCB*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
356 cell *list_buffer = av_malloc(numpoints*sizeof(cell));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
357 cell *free_cells;
10762
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
358 int best_dist, best_idx = 0;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
359
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
360 elbg->error = INT_MAX;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
361 elbg->dim = dim;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
362 elbg->numCB = numCB;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
363 elbg->codebook = codebook;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
364 elbg->cells = av_malloc(numCB*sizeof(cell *));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
365 elbg->utility = av_malloc(numCB*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
366 elbg->nearest_cb = closest_cb;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
367 elbg->points = points;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
368 elbg->utility_inc = av_malloc(numCB*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
369
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
370 elbg->rand_state = rand_state;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
371
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
372 do {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
373 free_cells = list_buffer;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
374 last_error = elbg->error;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
375 steps++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
376 memset(elbg->utility, 0, numCB*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
377 memset(elbg->cells, 0, numCB*sizeof(cell *));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
378
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
379 elbg->error = 0;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
380
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
381 /* This loop evaluate the actual Voronoi partition. It is the most
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
382 costly part of the algorithm. */
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
383 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
384 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
385 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
386 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
387 if (dist < best_dist) {
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
388 best_dist = dist;
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
389 best_idx = k;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
390 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
391 }
10762
a4842fc20ac8 Small ELBG optimization: use last pixel as a initial guess for the codebook
vitor
parents: 9160
diff changeset
392 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
393 dist_cb[i] = best_dist;
5095
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
394 elbg->error += dist_cb[i];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
395 elbg->utility[elbg->nearest_cb[i]] += dist_cb[i];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
396 free_cells->index = i;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
397 free_cells->next = elbg->cells[elbg->nearest_cb[i]];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
398 elbg->cells[elbg->nearest_cb[i]] = free_cells;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
399 free_cells++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
400 }
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
401
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
402 do_shiftings(elbg);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
403
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
404 memset(size_part, 0, numCB*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
405
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
406 memset(elbg->codebook, 0, elbg->numCB*dim*sizeof(int));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
407
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
408 for (i=0; i < numpoints; i++) {
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
409 size_part[elbg->nearest_cb[i]]++;
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
410 for (j=0; j < elbg->dim; j++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
411 elbg->codebook[elbg->nearest_cb[i]*elbg->dim + j] +=
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
412 elbg->points[i*elbg->dim + j];
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
413 }
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 < elbg->numCB; i++)
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
416 vect_division(elbg->codebook + i*elbg->dim,
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
417 elbg->codebook + i*elbg->dim, size_part[i], elbg->dim);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
418
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
419 } while(((last_error - elbg->error) > DELTA_ERR_MAX*elbg->error) &&
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
420 (steps < max_steps));
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
421
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
422 av_free(dist_cb);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
423 av_free(size_part);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
424 av_free(elbg->utility);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
425 av_free(list_buffer);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
426 av_free(elbg->cells);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
427 av_free(elbg->utility_inc);
ed41cfae128d Codebook generator using the ELBG algorithm
benoit
parents:
diff changeset
428 }