From e93b0de38ac8b8d9e15d7af5594b1286a81a2c65 Mon Sep 17 00:00:00 2001 From: Pavel Charvat Date: Sun, 27 Aug 2006 15:40:28 +0200 Subject: [PATCH] - detection of textured images - playing with thresholds --- cf/images | 4 +- images/Makefile | 2 +- images/config.c | 2 + images/image-sim-test.c | 10 ++++- images/sig-init.c | 13 +++++-- images/sig-txt.c | 85 +++++++++++++++++++++++++++++++++++++++++ images/signature.h | 14 ++++++- 7 files changed, 120 insertions(+), 10 deletions(-) create mode 100644 images/sig-txt.c diff --git a/cf/images b/cf/images index 7772e858..9e533985 100644 --- a/cf/images +++ b/cf/images @@ -12,11 +12,13 @@ ImageSig { 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 ###################################################### diff --git a/images/Makefile b/images/Makefile index 3283e44b..839a5f2d 100644 --- a/images/Makefile +++ b/images/Makefile @@ -6,7 +6,7 @@ PROGS+=$(addprefix $(o)/images/,image-tool image-dup-test image-sim-test) 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 diff --git a/images/config.c b/images/config.c index 7b02cbfb..a6e69a19 100644 --- a/images/config.c +++ b/images/config.c @@ -19,6 +19,7 @@ uns *image_sig_prequant_thresholds; 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{ @@ -28,6 +29,7 @@ static struct cf_section sig_config = { 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 } }; diff --git a/images/image-sim-test.c b/images/image-sim-test.c index 8116206f..021dd7e6 100644 --- a/images/image-sim-test.c +++ b/images/image-sim-test.c @@ -235,7 +235,10 @@ main(int argc, char **argv) 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); @@ -248,7 +251,10 @@ main(int argc, char **argv) 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); diff --git a/images/sig-init.c b/images/sig-init.c index 5b0b33f9..6c5e75e5 100644 --- a/images/sig-init.c +++ b/images/sig-init.c @@ -25,6 +25,7 @@ image_sig_init(struct image_thread *thread, struct image_sig_data *data, struct { 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; @@ -157,9 +158,9 @@ image_sig_preprocess(struct image_sig_data *data) 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; } } @@ -185,6 +186,7 @@ image_sig_finish(struct image_sig_data *data, struct image_signature *sig) 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; @@ -308,7 +310,10 @@ compute_image_signature(struct image_thread *thread, struct image_signature *sig 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; diff --git a/images/sig-txt.c b/images/sig-txt.c new file mode 100644 index 00000000..3673c118 --- /dev/null +++ b/images/sig-txt.c @@ -0,0 +1,85 @@ +/* + * Image Library -- Detection of textured images + * + * (c) 2006 Pavel Charvat + * + * 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 + +#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."); +} diff --git a/images/signature.h b/images/signature.h index aeb64967..8c332cf3 100644 --- a/images/signature.h +++ b/images/signature.h @@ -5,6 +5,7 @@ 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 @@ -24,11 +25,14 @@ struct image_region { 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; @@ -51,6 +55,7 @@ struct image_sig_block { 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 */ }; @@ -72,6 +77,7 @@ struct image_sig_data { u32 rows; u32 full_cols; u32 full_rows; + u32 flags; u32 area; u32 valid; u32 blocks_count; @@ -92,6 +98,10 @@ void image_sig_cleanup(struct image_sig_data *data); 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) -- 2.39.2