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);
30 rows = MAX(rows, b->y);
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)
71 memcpy(region->c, region->a, sizeof(region->c));
76 for (uns i = 0; i < IMAGE_VEC_F; i++)
78 region->e += region->c[i];
79 a += (u64)region->b[i] * region->b[i];
81 region->e -= a / region->count;
86 prequant_heap_cmp(struct image_sig_region *a, struct image_sig_region *b)
91 #define ASORT_PREFIX(x) prequant_##x
92 #define ASORT_KEY_TYPE u32
93 #define ASORT_ELT(i) val[i]
94 #define ASORT_EXTRA_ARGS , u32 *val
95 #include "lib/arraysort.h"
98 prequant(struct image_sig_block *blocks, uns blocks_count, struct image_sig_region *regions)
100 DBG("Starting pre-quantization");
102 uns regions_count, heap_count, axis, cov;
103 struct image_sig_block *blocks_end = blocks + blocks_count, *block, *block2;
104 struct image_sig_region *heap[IMAGE_REG_MAX + 1], *region, *region2;
106 /* Initialize single region with all blocks */
107 regions_count = heap_count = 1;
109 prequant_init_region(regions);
110 for (block = blocks; block != blocks_end; block++)
111 prequant_add_block(regions, block);
112 prequant_finish_region(regions);
115 while (regions_count < IMAGE_REG_MAX &&
116 regions_count <= DARY_LEN(image_sig_prequant_thresholds) && heap_count)
119 DBG("Step... regions_count=%u heap_count=%u region->count=%u, region->e=%u",
120 regions_count, heap_count, region->count, (uns)region->e);
121 if (region->count < 2 ||
122 region->e < image_sig_prequant_thresholds[regions_count - 1] * region->count)
124 HEAP_DELMIN(struct image_sig_region *, heap, heap_count, prequant_heap_cmp, HEAP_SWAP);
128 /* Select axis to split - the one with maximum covariance */
130 cov = region->count * region->c[0] - region->b[0];
131 for (uns i = 1; i < 6; i++)
133 uns j = region->count * region->c[i] - region->b[i];
140 DBG("Splitting axis %u with covariance %u", axis, cov / region->count);
142 /* Sort values on the split axis */
143 u32 val[region->count];
144 block = region->blocks;
145 for (uns i = 0; i < region->count; i++, block = block->next)
146 val[i] = block->v[axis];
147 prequant_sort(region->count, val);
149 /* Select split value - to minimize error */
150 uns b1 = 0, c1 = 0, b2 = region->b[axis], c2 = region->c[axis];
151 uns i = 0, j = region->count, best_v = 0;
152 u64 best_err = 0xffffffffffffffff;
153 while (i < region->count)
155 u64 err = (u64)i * c1 - (u64)b1 * b1 + (u64)j * c2 - (u64)b2 * b2;
161 uns sqr = isqr(val[i]);
169 uns split_val = best_v;
170 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]);
173 block = region->blocks;
174 region2 = regions + regions_count++;
175 prequant_init_region(region);
176 prequant_init_region(region2);
179 block2 = block->next;
180 if (block->v[axis] < split_val)
181 prequant_add_block(region, block);
183 prequant_add_block(region2, block);
186 prequant_finish_region(region);
187 prequant_finish_region(region2);
188 HEAP_INCREASE(struct image_sig_region *, heap, heap_count, prequant_heap_cmp, HEAP_SWAP, 1);
189 heap[++heap_count] = region2;
190 HEAP_INSERT(struct image_sig_region *, heap, heap_count, prequant_heap_cmp, HEAP_SWAP);
193 DBG("Pre-quantized to %u regions", regions_count);
195 return regions_count;
198 /* Post-quantization - run a few K-mean iterations to improve pre-quantized regions */
201 postquant(struct image_sig_block *blocks, uns blocks_count, struct image_sig_region *regions, uns regions_count)
203 DBG("Starting post-quantization");
205 struct image_sig_block *blocks_end = blocks + blocks_count, *block;
206 struct image_sig_region *regions_end = regions + regions_count, *region;
207 uns error = 0, last_error;
209 /* Initialize regions and initial segmentation error */
210 for (region = regions; region != regions_end; )
212 uns inv = 0xffffffffU / region->count;
213 for (uns i = 0; i < IMAGE_VEC_F; i++)
215 region->a[i] = ((u64)region->b[i] * inv) >> 32;
216 error += region->c[i] - region->a[i] * region->b[i];
221 /* Convergation cycle */
222 for (uns step = 0; step < image_sig_postquant_max_steps; step++)
227 for (region = regions; region != regions_end; region++)
229 region->blocks = NULL;
231 bzero(region->b, sizeof(region->b));
232 bzero(region->c, sizeof(region->c));
235 /* Assign each block to its nearest pivot and accumulate region variables */
236 for (block = blocks; block != blocks_end; block++)
238 struct image_sig_region *best_region = NULL;
240 for (region = regions; region != regions_end; region++)
243 isqr(block->v[0] - region->a[0]) +
244 isqr(block->v[1] - region->a[1]) +
245 isqr(block->v[2] - region->a[2]) +
246 isqr(block->v[3] - region->a[3]) +
247 isqr(block->v[4] - region->a[4]) +
248 isqr(block->v[5] - region->a[5]);
249 if (dist <= best_dist)
252 best_region = region;
255 region = best_region;
257 block->next = region->blocks;
258 region->blocks = block;
259 for (uns i = 0; i < IMAGE_VEC_F; i++)
261 region->b[i] += block->v[i];
262 region->c[i] += isqr(block->v[i]);
266 /* Finish regions, delete empty ones (should appear rarely), compute segmentation error */
269 for (region = regions; region != regions_end; )
272 uns inv = 0xffffffffU / region->count;
273 for (uns i = 0; i < IMAGE_VEC_F; i++)
275 region->a[i] = ((u64)region->b[i] * inv) >> 32;
276 error += region->c[i] - region->a[i] * region->b[i];
283 *region = *regions_end;
286 DBG("last_error=%u error=%u", last_error, error);
288 /* Convergation criteria */
289 if (step >= image_sig_postquant_min_steps)
291 if (error > last_error)
293 u64 dif = last_error - error;
294 if (dif * image_sig_postquant_threshold < last_error * 100)
299 DBG("Post-quantized to %u regions with average square error %u", regions_end - regions, error / blocks_count);
301 return regions_end - regions;
305 image_sig_segmentation(struct image_sig_block *blocks, uns blocks_count, struct image_sig_region *regions)
308 regions_count = prequant(blocks, blocks_count, regions);
310 dump_segmentation(regions, regions_count);
312 regions_count = postquant(blocks, blocks_count, regions, regions_count);
314 dump_segmentation(regions, regions_count);
316 return regions_count;