MinWidth 16
MinHeight 16
-PreQuantThresholds 9 100 1000 1000 2000 4000 8000 10000 10000 20000 20000 40000 40000 40000 40000
+PreQuantThresholds 9 100 400 1000 2000 2000 4000 4000 4000 8000 8000 8000 10000 10000 10000
PostQuantMinSteps 2
PostQuantMaxSteps 10
PostQuantThreshold 2
+TexturedThreshold 0.32
+
}
######## Duplicates finder ######################################################
CONFIGS+=images
-LIBIMAGES_MODS=math config image scale color alpha io-main dup-init dup-cmp sig-dump sig-init sig-seg sig-cmp object
+LIBIMAGES_MODS=math config image scale color alpha io-main dup-init dup-cmp sig-dump sig-init sig-seg sig-txt sig-cmp object
LIBIMAGES_LIBS=-lm
uns image_sig_postquant_min_steps;
uns image_sig_postquant_max_steps;
uns image_sig_postquant_threshold;
+double image_sig_textured_threshold;
static struct cf_section sig_config = {
CF_ITEMS{
CF_UNS("PostQuantMinSteps", &image_sig_postquant_min_steps),
CF_UNS("PostQuantMaxSteps", &image_sig_postquant_max_steps),
CF_UNS("PostQuantThreshold", &image_sig_postquant_threshold),
+ CF_DOUBLE("TexturedThreshold", &image_sig_textured_threshold),
CF_END
}
};
TRY(image_sig_init(&it, &data, img1));
image_sig_preprocess(&data);
if (data.valid)
- image_sig_segmentation(&data);
+ {
+ image_sig_segmentation(&data);
+ image_sig_detect_textured(&data);
+ }
if (segmentation_name_1)
write_segmentation(&data, segmentation_name_1);
image_sig_finish(&data, &sig1);
TRY(image_sig_init(&it, &data, img2));
image_sig_preprocess(&data);
if (data.valid)
- image_sig_segmentation(&data);
+ {
+ image_sig_segmentation(&data);
+ image_sig_detect_textured(&data);
+ }
if (segmentation_name_2)
write_segmentation(&data, segmentation_name_2);
image_sig_finish(&data, &sig2);
{
ASSERT((image->flags & IMAGE_PIXEL_FORMAT) == COLOR_SPACE_RGB);
data->image = image;
+ data->flags = 0;
data->cols = (image->cols + 3) >> 2;
data->rows = (image->rows + 3) >> 2;
data->full_cols = image->cols >> 2;
block->v[3] = fast_sqrt_u16(isqr(t[8]) + isqr(t[9]) + isqr(t[12]) + isqr(t[13]));
block->v[4] = fast_sqrt_u16(isqr(t[2]) + isqr(t[3]) + isqr(t[6]) + isqr(t[7]));
block->v[5] = fast_sqrt_u16(isqr(t[10]) + isqr(t[11]) + isqr(t[14]) + isqr(t[15]));
- sum[3] += block->v[3] * block->area;
- sum[4] += block->v[4] * block->area;
- sum[5] += block->v[5] * block->area;
+ sum[3] += block->v[3] * block->area / 2;
+ sum[4] += block->v[4] * block->area / 2;
+ sum[5] += block->v[5] * block->area / 2;
}
}
for (uns i = 0; i < IMAGE_VEC_F; i++)
sig->vec.f[i] = data->f[i];
sig->len = data->regions_count;
+ sig->flags = data->flags;
if (!sig->len)
return;
return 0;
image_sig_preprocess(&data);
if (data.valid)
- image_sig_segmentation(&data);
+ {
+ image_sig_segmentation(&data);
+ image_sig_detect_textured(&data);
+ }
image_sig_finish(&data, sig);
image_sig_cleanup(&data);
return 1;
--- /dev/null
+/*
+ * Image Library -- Detection of textured images
+ *
+ * (c) 2006 Pavel Charvat <pchar@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#define LOCAL_DEBUG
+
+#include "sherlock/sherlock.h"
+#include "images/images.h"
+#include "images/signature.h"
+#include "images/math.h"
+
+#include <string.h>
+
+#define MAX_CELLS_COLS 4
+#define MAX_CELLS_ROWS 4
+
+void
+image_sig_detect_textured(struct image_sig_data *data)
+{
+ uns cols = data->cols;
+ uns rows = data->rows;
+ uns cell_cols = MIN(cols, MAX_CELLS_COLS);
+ uns cell_rows = MIN(rows, MAX_CELLS_ROWS);
+ uns cell_x[MAX_CELLS_COLS + 1];
+ uns cell_y[MAX_CELLS_ROWS + 1];
+ uns i, j;
+ u32 cnt[IMAGE_REG_MAX];
+
+ DBG("Detecting textured image... cols=%u rows=%u cell_cols=%u cell_rows=%u", cols, rows, cell_cols, cell_rows);
+
+ /* Compute cells boundaries */
+ for (i = 1, j = 0; i < cell_cols; i++)
+ cell_x[i] = fast_div_u32_u8(j += cols, cell_cols);
+ cell_x[0] = 0;
+ cell_x[cell_cols] = cols;
+ for (i = 1, j = 0; i < cell_rows; i++)
+ cell_y[i] = fast_div_u32_u8(j += rows, cell_rows);
+ cell_y[0] = 0;
+ cell_y[cell_rows] = rows;
+
+ /* Preprocess blocks */
+ for (uns i = 0; i < data->regions_count; i++)
+ for (struct image_sig_block *block = data->regions[i].blocks; block; block = block->next)
+ block->region = i;
+
+ /* Process cells */
+ double e = 0;
+ for (uns j = 0; j < cell_rows; j++)
+ for (uns i = 0; i < cell_cols; i++)
+ {
+ uns cell_area = 0;
+ bzero(cnt, data->regions_count * sizeof(u32));
+ struct image_sig_block *b1 = data->blocks + cell_x[i] + cell_y[i] * cols, *b2;
+ for (uns y = cell_y[j]; y < cell_y[j + 1]; y++, b1 += cols)
+ {
+ b2 = b1;
+ for (uns x = cell_x[i]; x < cell_x[i + 1]; x++, b2++)
+ {
+ cnt[b2->region]++;
+ cell_area++;
+ }
+ }
+ for (uns k = 0; k < data->regions_count; k++)
+ {
+ int a = data->blocks_count * cnt[k] - cell_area * data->regions[k].count;
+ e += (double)a * a / ((double)isqr(data->regions[k].count) * cell_area);
+ }
+ }
+
+ DBG("Coefficient=%g", (double)e / (data->regions_count * data->blocks_count));
+
+ /* Threshold */
+ if (e <= image_sig_textured_threshold * data->regions_count * data->blocks_count)
+ {
+ data->flags |= IMAGE_SIG_TEXTURED;
+ DBG("Image is textured.");
+ }
+ else
+ DBG("Image is not textured.");
+}
extern uns image_sig_min_width, image_sig_min_height;
extern uns *image_sig_prequant_thresholds;
extern uns image_sig_postquant_min_steps, image_sig_postquant_max_steps, image_sig_postquant_threshold;
+extern double image_sig_textured_threshold;
#define IMAGE_VEC_F 6
#define IMAGE_REG_F IMAGE_VEC_F
u16 wb; /* normalized weight */
} PACKED;
+#define IMAGE_SIG_TEXTURED 0x1
+
/* Image signature (10 + len * 16 bytes) */
struct image_signature {
byte len; /* Number of regions */
- byte df; /* average f dist */
- u16 dh; /* average h dist */
+ byte flags; /* IMAGE_SIG_xxx */
+ byte df; /* Average f dist */
+ u16 dh; /* Average h dist */
struct image_vector vec; /* Combination of all regions... simple signature */
struct image_region reg[IMAGE_REG_MAX];/* Feature vector for every region */
} PACKED;
struct image_sig_block *next; /* linked list */
u32 x, y; /* block position */
byte area; /* block area in pixels (usually 16) */
+ byte region; /* region index */
byte v[IMAGE_VEC_F]; /* feature vector */
};
u32 rows;
u32 full_cols;
u32 full_rows;
+ u32 flags;
u32 area;
u32 valid;
u32 blocks_count;
void image_sig_segmentation(struct image_sig_data *data);
+/* sig-txt.c */
+
+void image_sig_detect_textured(struct image_sig_data *data);
+
/* sig-cmp.c */
#define IMAGE_SIG_DIST_SCALE (3 + 3 + 8 + 16)