added hausdorf metric

master
Ondřej Hruška 9 years ago
parent bb71551e6b
commit b094ca363a
  1. 59
      main.c
  2. 7
      main.d
  3. 97
      src/vec_match.c
  4. 36
      src/vec_match.h

@ -14,7 +14,7 @@ static float reference[DATA_LEN] = {
static float data[DATA_LEN] = {
//0, 10, 20, 30, 40, 50, 50, 35, 15, 15, 0
0, 15.7, 0, 0, 0.1, 0.2, 0.1, 10, 24, 6, 3, 2, 0.2, 0.4, 0.5, 0
0, 13, 16, 0, 0.1, 0.2, 10, 0, 24, 0, 0, 7, 12, 0.4, 0.5, 0
};
static float ref_p[REF_LEN];
@ -75,37 +75,39 @@ int main(void)
//return 0;
vec_match_cfg_t cfg = {
vec_fuzzymatch_cfg_t cfg = {
.length = DATA_LEN,
.drift_x = 1,
.offset_y = 1,
.abs_threshold = 0.1
};
vec_hausdorff_cfg_t cfg_hdf = {
.length = DATA_LEN,
.max_drift_x = 10,
.cost_x = 10,
.cost_y = 4
};
// example
printf("REF: ");
for (int i = 0; i < DATA_LEN; i++) {
printf("%.1f, ", reference[i]);
printf("%5.1f, ", reference[i]);
}
printf("\n");
printf("MEAS: ");
for (int i = 0; i < DATA_LEN; i++) {
printf("%.1f, ", data[i]);
printf("%5.1f, ", data[i]);
}
printf("\n");
// error metric fields
float env_e, abs_e;
bool ok = vec_match(data, reference, &cfg, &env_e, &abs_e);
printf("%s", ok ? "MATCH OK" : "MATCH FAILED");
printf("\n");
printf("Error rate: ENV %.2f, ABS %.2f\n", env_e, abs_e);
// --- PACK REFERENCE VECTOR ---
float thr;
int ref_pack_len = vec_pack_auto(ref_p, REF_LEN, reference, DATA_LEN, &thr);
@ -113,21 +115,36 @@ int main(void)
printf("Reference packed with zero threshold %.1f to %d items.\n", thr, ref_pack_len);
printf("REF packed: ");
for (int i = 0; i < ref_pack_len; i++) {
printf("%.1f, ", ref_p[i]);
printf("%5.1f, ", ref_p[i]);
}
printf("\n");
pack_walker_t pw;
pw_init(&pw, ref_p, ref_pack_len);
printf("Value #8 = %.1f\n", pw_get(&pw, 8));
printf("Value #7 = %.1f\n", pw_get(&pw, 7));
printf("Value #15 = %.1f\n", pw_get(&pw, 15));
printf("Trying packed match\n");
ok = vec_match_packed(data, ref_p, ref_pack_len, &cfg, &env_e, &abs_e);
printf("%s", ok ? "MATCH OK" : "MATCH FAILED");
// error metric fields
float env_e, abs_e;
bool ok = vec_fuzzymatch(data, reference, &cfg, &env_e, &abs_e);
printf("FUZZY: %s", ok ? "MATCH OK" : "MATCH FAILED");
printf("\n");
printf("Error rate: ENV %.2f, ABS %.2f\n", env_e, abs_e);
ok = vec_fuzzymatch_packed(data, ref_p, ref_pack_len, &cfg, &env_e, &abs_e);
printf("PACKED FUZZY: %s", ok ? "MATCH OK" : "MATCH FAILED");
printf("\n");
printf("Error rate: ENV %.2f, ABS %.2f\n", env_e, abs_e);
// ---- HAUSDORFF ----
float hdif = vec_hausdorff(data, reference, &cfg_hdf);
printf("HAUSDORFF dist: %.2f\n", hdif);
float hdif_p = vec_hausdorff_packed(data, ref_p, ref_pack_len, &cfg_hdf);
printf("HAUSDORFF dist packed: %.2f\n", hdif_p);
}

@ -24,4 +24,9 @@ main.out: src/vec_match.c /usr/include/stdc-predef.h \
/usr/include/bits/huge_valf.h /usr/include/bits/huge_vall.h \
/usr/include/bits/inf.h /usr/include/bits/nan.h \
/usr/include/bits/mathdef.h /usr/include/bits/mathcalls.h \
/usr/include/string.h /usr/include/xlocale.h src/vec_match.h
/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include-fixed/limits.h \
/usr/lib/gcc/x86_64-unknown-linux-gnu/5.3.0/include-fixed/syslimits.h \
/usr/include/limits.h /usr/include/bits/posix1_lim.h \
/usr/include/bits/local_lim.h /usr/include/linux/limits.h \
/usr/include/bits/posix2_lim.h /usr/include/string.h \
/usr/include/xlocale.h src/vec_match.h

@ -4,20 +4,97 @@
#include <stdio.h>
#include <float.h>
#include <math.h>
#include <limits.h>
#include <string.h>
#include "vec_match.h"
#define SQ(a) ((a)*(a))
#define SQ(a) ((a) * (a))
#define IS_FZERO(f) ((f) < 0.0f)
#define F2ZERO(f) roundf(-(f))
#define ZERO2F(z) (0.0f - z)
#define NUM_DIST(a,b) ((a) > (b) ? (a) - (b) : (b) - (a))
bool vec_match_do(const float *data, const float *ref, uint32_t ref_p_len,
const vec_match_cfg_t *cfg,
// ---- HAUSDORFF ----
// real hausdorf should just return the max distance, we sum them all
float vec_hausdorff_do(const float *data,
const float *ref, uint32_t ref_p_len,
const vec_hausdorff_cfg_t *cfg, bool packed)
{
uint32_t a, b;
float f, g; // tmp float
pack_walker_t w; // walker for packed reference
if (packed) {
pw_init(&w, ref, ref_p_len);
}
float dist_sum = 0;
for (uint32_t i = 0; i < cfg->length; i++) {
// bounds for base and peak search
if (i < cfg->max_drift_x) {
a = 0;
} else {
a = i - cfg->max_drift_x;
}
if (i + cfg->max_drift_x >= cfg->length) {
b = cfg->length - 1;
} else {
b = i + cfg->max_drift_x;
}
// get metric for point
float dist = FLT_MAX;
for (uint32_t j = a; j <= b; j++) {
f = packed ? pw_get(&w, j) : ref[j];
// get X dist
g = sqrtf(SQ((f - data[i]) * cfg->cost_y) +
SQ(NUM_DIST(i, j) * cfg->cost_x));
if (dist > g) dist = g;
}
dist_sum += dist;
}
return dist_sum;
}
float vec_hausdorff(const float *data,
const float *ref,
const vec_hausdorff_cfg_t *cfg)
{
return vec_hausdorff_do(data, ref, cfg->length, cfg, false);
}
float vec_hausdorff_packed(const float *data,
const float *ref, uint32_t ref_p_len,
const vec_hausdorff_cfg_t *cfg)
{
return vec_hausdorff_do(data, ref, ref_p_len, cfg, true);
}
// ---- FUZZY MATCH ----
bool vec_fuzzymatch_do(const float *data, const float *ref, uint32_t ref_p_len,
const vec_fuzzymatch_cfg_t *cfg,
float *fuzzy_match_error, float *abs_match_error, bool packed)
{
uint32_t a, b;
@ -94,24 +171,24 @@ bool vec_match_do(const float *data, const float *ref, uint32_t ref_p_len,
bool vec_match(const float *data, const float *ref,
const vec_match_cfg_t *cfg,
bool vec_fuzzymatch(const float *data, const float *ref,
const vec_fuzzymatch_cfg_t *cfg,
float *fuzzy_match_error, float *abs_match_error)
{
return vec_match_do(data, ref, cfg->length, cfg, fuzzy_match_error, abs_match_error, false);
return vec_fuzzymatch_do(data, ref, cfg->length, cfg, fuzzy_match_error, abs_match_error, false);
}
bool vec_match_packed(const float *data, const float *ref, uint32_t ref_p_len,
const vec_match_cfg_t *cfg,
bool vec_fuzzymatch_packed(const float *data, const float *ref, uint32_t ref_p_len,
const vec_fuzzymatch_cfg_t *cfg,
float *fuzzy_match_error, float *abs_match_error)
{
return vec_match_do(data, ref, ref_p_len, cfg, fuzzy_match_error, abs_match_error, true);
return vec_fuzzymatch_do(data, ref, ref_p_len, cfg, fuzzy_match_error, abs_match_error, true);
}
// ---- PACKING UTILS ----

@ -3,13 +3,21 @@
#include <stdint.h>
#include <stdbool.h>
typedef struct {
uint32_t length; // data length (data & ref length must be equal)
uint32_t max_drift_x;
float cost_x; // must be > 1
float cost_y;
} vec_hausdorff_cfg_t;
/* Example: drift_x 1, offset_y 10, abs_threshold 0.1 */
typedef struct {
uint32_t length; // data length (data & ref length must be equal)
uint32_t drift_x; // allowed horizontal drift (Hz drift if values are 1 Hz FFT bins)
float offset_y; // allowed vertical offset (bin amplitude, positive or negative)
float abs_threshold; // absolute threshold (to fix preccision errors, also added to offset_y)
} vec_match_cfg_t;
} vec_fuzzymatch_cfg_t;
typedef struct {
@ -44,6 +52,24 @@ void pw_init(pack_walker_t *wlkr, const float *packed_vec, uint32_t packed_len);
float pw_get(pack_walker_t *w, uint32_t idx);
/**
* Get vector's Hausdorff distance from reference
*
* @param data matched data
* @param ref reference data
* @param cfg config struct
* @return distance metric
*/
float vec_hausdorff(const float *data, const float *ref, const vec_hausdorff_cfg_t *cfg);
/**
* Same as vec_hausdorff(), except the reference vector is packed.
*/
float vec_hausdorff_packed(const float *data, const float *ref_packed,
uint32_t ref_p_len, const vec_hausdorff_cfg_t *cfg);
/**
* Match signal to reference, allowing for some offser and noise
*
@ -54,16 +80,16 @@ float pw_get(pack_walker_t *w, uint32_t idx);
* @param abs_match_error error metric calculated from raw data (can be used if envelope match passes)
* @return envelope match status (match using drift and offset)
*/
bool vec_match(const float *data, const float *ref, const vec_match_cfg_t *cfg,
bool vec_fuzzymatch(const float *data, const float *ref, const vec_fuzzymatch_cfg_t *cfg,
float *fuzzy_match_error, float *abs_match_error);
/**
* Match vector against a packed reference vector (without unpacking).
* Params otherwise the same as vec_match()
* Params otherwise the same as vec_fuzzymatch()
*/
bool vec_match_packed(const float *data, const float *ref_packed, uint32_t ref_p_len,
const vec_match_cfg_t *cfg, float *fuzzy_match_error, float *abs_match_error);
bool vec_fuzzymatch_packed(const float *data, const float *ref_packed, uint32_t ref_p_len,
const vec_fuzzymatch_cfg_t *cfg, float *fuzzy_match_error, float *abs_match_error);
/**

Loading…
Cancel
Save