2 * Image Library -- Image segmentation
4 * (c) 2006 Pavel Charvat <pchar@ucw.cz>
6 * This software may be freely distributed and used according to the terms
7 * of the GNU Lesser General Public License.
12 #include "sherlock/sherlock.h"
15 #include "images/images.h"
16 #include "images/signature.h"
17 #include "images/math.h"
23 dump_segmentation(struct image_sig_region *regions, uns regions_count)
25 uns cols = 0, rows = 0;
26 for (uns i = 0; i < regions_count; i++)
27 for (struct image_sig_block *b = regions[i].blocks; b; b = b->next)
29 cols = MAX(cols, b->x + 1);
30 rows = MAX(rows, b->y + 1);
32 uns size = (cols + 1) * rows;
35 for (uns i = 0; i < regions_count; i++)
37 byte c = (i < 10) ? '0' + i : 'A' - 10 + i;
38 for (struct image_sig_block *b = regions[i].blocks; b; b = b->next)
39 buf[b->x + b->y * (cols + 1)] = c;
41 for (uns i = 0; i < rows; i++)
42 log(L_DEBUG, "%s", &buf[i * (cols + 1)]);
46 /* Pre-quantization - recursively split groups of blocks with large error */
49 prequant_init_region(struct image_sig_region *region)
51 bzero(region, sizeof(*region));
55 prequant_add_block(struct image_sig_region *region, struct image_sig_block *block)
57 block->next = region->blocks;
58 region->blocks = block;
60 for (uns i = 0; i < IMAGE_VEC_F; i++)
62 region->b[i] += block->v[i];
63 region->c[i] += isqr(block->v[i]);
68 prequant_finish_region(struct image_sig_region *region)
70 if (region->count < 2)
78 for (uns i = 0; i < IMAGE_VEC_F; i++)
80 region->e += region->c[i];
81 a += (u64)region->b[i] * region->b[i];
83 region->e -= a / region->count;
84 DBG("Finished region %u", (uns)region->e / region->count);
89 prequant_heap_cmp(struct image_sig_region *a, struct image_sig_region *b)
94 #define ASORT_PREFIX(x) prequant_##x
95 #define ASORT_KEY_TYPE uns
96 #define ASORT_ELT(i) val[i]
97 #define ASORT_EXTRA_ARGS , uns *val
98 #include "lib/arraysort.h"
101 prequant(struct image_sig_block *blocks, uns blocks_count, struct image_sig_region *regions)
103 DBG("Starting pre-quantization");
105 uns regions_count, heap_count, axis;
106 struct image_sig_block *blocks_end = blocks + blocks_count, *block, *block2;
107 struct image_sig_region *heap[IMAGE_REG_MAX + 1], *region, *region2;
109 /* Initialize single region with all blocks */
110 regions_count = heap_count = 1;
112 prequant_init_region(regions);
113 for (block = blocks; block != blocks_end; block++)
114 prequant_add_block(regions, block);
115 prequant_finish_region(regions);
118 while (regions_count < IMAGE_REG_MAX &&
119 regions_count <= DARY_LEN(image_sig_prequant_thresholds) && heap_count)
122 DBG("Step... regions_count=%u heap_count=%u region->count=%u, region->e=%u",
123 regions_count, heap_count, region->count, (uns)region->e);
124 if (region->count < 2 ||
125 region->e < image_sig_prequant_thresholds[regions_count - 1] * blocks_count)
127 HEAP_DELMIN(struct image_sig_region *, heap, heap_count, prequant_heap_cmp, HEAP_SWAP);
131 /* Select axis to split - the one with maximum average quadratic error */
133 u64 cov = (u64)region->count * region->c[0] - (u64)region->b[0] * region->b[0];
134 for (uns i = 1; i < 6; i++)
136 uns j = (u64)region->count * region->c[i] - (u64)region->b[i] * region->b[i];
143 DBG("Splitting axis %u with average quadratic error %u", axis, (uns)(cov / (region->count * region->count)));
145 /* Sort values on the split axis */
146 uns val[256], cnt[256], cval;
147 if (region->count > 64)
149 bzero(cnt, sizeof(cnt));
150 for (block = region->blocks; block; block = block->next)
151 cnt[block->v[axis]]++;
153 for (uns i = 0; i < 256; i++)
163 block = region->blocks;
164 for (uns i = 0; i < region->count; i++, block = block->next)
165 val[i] = block->v[axis];
166 prequant_sort(region->count, val);
169 for (uns i = 1; i < region->count; i++)
170 if (val[i] == val[cval - 1])
180 /* Select split value - to minimize error */
181 uns b1 = val[0] * cnt[0];
182 uns c1 = isqr(val[0]) * cnt[0];
183 uns b2 = region->b[axis] - b1;
184 uns c2 = region->c[axis] - c1;
185 uns i = cnt[0], j = region->count - cnt[0];
186 u64 best_err = c1 - (u64)b1 * b1 / i + c2 - (u64)b2 * b2 / j;
187 uns split_val = val[0];
188 for (uns k = 1; k < cval - 1; k++)
190 uns b0 = val[k] * cnt[k];
191 uns c0 = isqr(val[k]) * cnt[k];
198 u64 err = (u64)c1 - (u64)b1 * b1 / i + (u64)c2 - (u64)b2 * b2 / j;
205 DBG("split_val=%u best_err=%Lu b[axis]=%u c[axis]=%u", split_val, (long long)best_err, region->b[axis], region->c[axis]);
208 block = region->blocks;
209 region2 = regions + regions_count++;
210 prequant_init_region(region);
211 prequant_init_region(region2);
214 block2 = block->next;
215 if (block->v[axis] <= split_val)
216 prequant_add_block(region, block);
218 prequant_add_block(region2, block);
221 prequant_finish_region(region);
222 prequant_finish_region(region2);
223 HEAP_INCREASE(struct image_sig_region *, heap, heap_count, prequant_heap_cmp, HEAP_SWAP, 1);
224 heap[++heap_count] = region2;
225 HEAP_INSERT(struct image_sig_region *, heap, heap_count, prequant_heap_cmp, HEAP_SWAP);
228 DBG("Pre-quantized to %u regions", regions_count);
230 return regions_count;
233 /* Post-quantization - run a few K-mean iterations to improve pre-quantized regions */
236 postquant(struct image_sig_block *blocks, uns blocks_count, struct image_sig_region *regions, uns regions_count)
238 DBG("Starting post-quantization");
240 struct image_sig_block *blocks_end = blocks + blocks_count, *block;
241 struct image_sig_region *regions_end = regions + regions_count, *region;
242 uns error = 0, last_error;
244 /* Initialize regions and initial segmentation error */
245 for (region = regions; region != regions_end; )
247 uns inv = 0xffffffffU / region->count;
248 for (uns i = 0; i < IMAGE_VEC_F; i++)
250 region->a[i] = ((u64)region->b[i] * inv) >> 32;
251 error += region->c[i] - region->a[i] * region->b[i];
256 /* Convergation cycle */
257 for (uns step = 0; step < image_sig_postquant_max_steps; step++)
262 for (region = regions; region != regions_end; region++)
264 region->blocks = NULL;
266 bzero(region->b, sizeof(region->b));
267 bzero(region->c, sizeof(region->c));
270 /* Assign each block to its nearest pivot and accumulate region variables */
271 for (block = blocks; block != blocks_end; block++)
273 struct image_sig_region *best_region = NULL;
275 for (region = regions; region != regions_end; region++)
278 isqr(block->v[0] - region->a[0]) +
279 isqr(block->v[1] - region->a[1]) +
280 isqr(block->v[2] - region->a[2]) +
281 isqr(block->v[3] - region->a[3]) +
282 isqr(block->v[4] - region->a[4]) +
283 isqr(block->v[5] - region->a[5]);
284 if (dist <= best_dist)
287 best_region = region;
290 region = best_region;
292 block->next = region->blocks;
293 region->blocks = block;
294 for (uns i = 0; i < IMAGE_VEC_F; i++)
296 region->b[i] += block->v[i];
297 region->c[i] += isqr(block->v[i]);
301 /* Finish regions, delete empty ones (should appear rarely), compute segmentation error */
304 for (region = regions; region != regions_end; )
307 uns inv = 0xffffffffU / region->count;
308 for (uns i = 0; i < IMAGE_VEC_F; i++)
310 region->a[i] = ((u64)region->b[i] * inv) >> 32;
311 error += region->c[i] - region->a[i] * region->b[i];
318 *region = *regions_end;
321 DBG("last_error=%u error=%u", last_error, error);
323 /* Convergation criteria */
324 if (step >= image_sig_postquant_min_steps)
326 if (error > last_error)
328 u64 dif = last_error - error;
329 if (dif * image_sig_postquant_threshold < (u64)last_error * 100)
334 DBG("Post-quantized to %u regions with average square error %u", regions_end - regions, error / blocks_count);
336 return regions_end - regions;
340 image_sig_segmentation(struct image_sig_data *data)
342 data->regions_count = prequant(data->blocks, data->blocks_count, data->regions);
344 dump_segmentation(data->regions, data->regions_count);
346 data->regions_count = postquant(data->blocks, data->blocks_count, data->regions, data->regions_count);
348 dump_segmentation(data->regions, data->regions_count);