mirror of
https://github.com/simon987/fastimagehash.git
synced 2025-04-10 14:16:49 +00:00
Add mhash
This commit is contained in:
parent
ff1deac6f1
commit
356c8e4c64
@ -63,6 +63,17 @@ static void BM_ahash(benchmark::State &state) {
|
|||||||
free(buf);
|
free(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void BM_mhash(benchmark::State &state) {
|
||||||
|
size_t size;
|
||||||
|
void *buf = load_test_file(&size);
|
||||||
|
|
||||||
|
for (auto _ : state) {
|
||||||
|
mhash_mem(buf, tmp, size, state.range());
|
||||||
|
}
|
||||||
|
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
|
||||||
static void BM_multi(benchmark::State &state) {
|
static void BM_multi(benchmark::State &state) {
|
||||||
size_t size;
|
size_t size;
|
||||||
void *buf = load_test_file(&size);
|
void *buf = load_test_file(&size);
|
||||||
@ -83,6 +94,7 @@ BENCHMARK(BM_phash)->ArgName("size")->Arg(8);
|
|||||||
BENCHMARK(BM_whash)->ArgName("size")->Arg(8);
|
BENCHMARK(BM_whash)->ArgName("size")->Arg(8);
|
||||||
BENCHMARK(BM_dhash)->ArgName("size")->Arg(8);
|
BENCHMARK(BM_dhash)->ArgName("size")->Arg(8);
|
||||||
BENCHMARK(BM_ahash)->ArgName("size")->Arg(8);
|
BENCHMARK(BM_ahash)->ArgName("size")->Arg(8);
|
||||||
|
BENCHMARK(BM_mhash)->ArgName("size")->Arg(8);
|
||||||
BENCHMARK(BM_multi)->ArgName("size")->Arg(8);
|
BENCHMARK(BM_multi)->ArgName("size")->Arg(8);
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,6 +31,17 @@ double median(double *arr, size_t len) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__always_inline
|
||||||
|
double median(uchar *arr, size_t len) {
|
||||||
|
std::sort(arr, arr + len);
|
||||||
|
|
||||||
|
if (len % 2 == 0) {
|
||||||
|
return (double)(arr[(len / 2) - 1] + arr[len / 2]) / 2;
|
||||||
|
} else {
|
||||||
|
return arr[(len + 1 / 2)];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void hash_to_hex_string(const uchar *h, char *out, int hash_size) {
|
void hash_to_hex_string(const uchar *h, char *out, int hash_size) {
|
||||||
int hash_len = hash_size * hash_size / 4;
|
int hash_len = hash_size * hash_size / 4;
|
||||||
|
|
||||||
@ -121,6 +132,42 @@ int ahash_mem(void *buf, uchar *out, size_t buf_len, int hash_size) {
|
|||||||
return FASTIMAGEHASH_OK;
|
return FASTIMAGEHASH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int mhash_file(const char *filepath, uchar *out, int hash_size) {
|
||||||
|
size_t size;
|
||||||
|
void *buf = load_file_in_mem(filepath, &size);
|
||||||
|
|
||||||
|
if (buf == nullptr) {
|
||||||
|
return FASTIMAGEHASH_READ_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = mhash_mem(buf, out, size, hash_size);
|
||||||
|
free(buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mhash_mem(void *buf, uchar *out, size_t buf_len, int hash_size) {
|
||||||
|
Mat im;
|
||||||
|
try {
|
||||||
|
im = imdecode(Mat(1, buf_len, CV_8UC1, buf), IMREAD_GRAYSCALE);
|
||||||
|
resize(im, im, Size(hash_size, hash_size), 0, 0, INTER_AREA);
|
||||||
|
} catch (Exception &e) {
|
||||||
|
return FASTIMAGEHASH_DECODE_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
uchar *pixel = im.ptr(0);
|
||||||
|
const int endPixel = im.cols * im.rows;
|
||||||
|
|
||||||
|
uchar sorted[im.cols * im.rows];
|
||||||
|
memcpy(sorted, pixel, endPixel);
|
||||||
|
double med = median(sorted, endPixel);
|
||||||
|
|
||||||
|
for (int i = 0; i < endPixel; i++) {
|
||||||
|
set_bit_at(out, i, pixel[i] > med);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FASTIMAGEHASH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int dhash_file(const char *filepath, uchar *out, int hash_size) {
|
int dhash_file(const char *filepath, uchar *out, int hash_size) {
|
||||||
size_t size;
|
size_t size;
|
||||||
void *buf = load_file_in_mem(filepath, &size);
|
void *buf = load_file_in_mem(filepath, &size);
|
||||||
@ -298,12 +345,13 @@ int phash_mem(void *buf, uchar *out, size_t buf_len, const int hash_size, int hi
|
|||||||
|
|
||||||
multi_hash_t *multi_hash_create(int hash_size) {
|
multi_hash_t *multi_hash_create(int hash_size) {
|
||||||
auto multi_hash = (multi_hash_t *) malloc(sizeof(multi_hash_t));
|
auto multi_hash = (multi_hash_t *) malloc(sizeof(multi_hash_t));
|
||||||
auto data = (uchar *) malloc((hash_size + 1) * 4);
|
auto data = (uchar *) malloc((hash_size + 1) * 5);
|
||||||
|
|
||||||
multi_hash->ahash = data;
|
multi_hash->ahash = data;
|
||||||
multi_hash->phash = data + (hash_size + 1);
|
multi_hash->phash = data + (hash_size + 1);
|
||||||
multi_hash->dhash = data + (hash_size + 1) * 2;
|
multi_hash->dhash = data + (hash_size + 1) * 2;
|
||||||
multi_hash->whash = data + (hash_size + 1) * 3;
|
multi_hash->whash = data + (hash_size + 1) * 3;
|
||||||
|
multi_hash->mhash = data + (hash_size + 1) * 4;
|
||||||
|
|
||||||
return multi_hash;
|
return multi_hash;
|
||||||
}
|
}
|
||||||
@ -336,7 +384,7 @@ int multi_hash_mem(void *buf, multi_hash_t *out, size_t buf_len,
|
|||||||
return FASTIMAGEHASH_DECODE_ERR;
|
return FASTIMAGEHASH_DECODE_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat ahash_im;
|
Mat ahash_im; // Also used for mhash!
|
||||||
Mat dhash_im;
|
Mat dhash_im;
|
||||||
Mat phash_im;
|
Mat phash_im;
|
||||||
Mat whash_im;
|
Mat whash_im;
|
||||||
@ -383,8 +431,15 @@ int multi_hash_mem(void *buf, multi_hash_t *out, size_t buf_len,
|
|||||||
|
|
||||||
uchar *pixel = ahash_im.ptr(0);
|
uchar *pixel = ahash_im.ptr(0);
|
||||||
int endPixel = ahash_im.cols * ahash_im.rows;
|
int endPixel = ahash_im.cols * ahash_im.rows;
|
||||||
|
|
||||||
|
// mhash
|
||||||
|
uchar mhash_sorted [ahash_im.cols * ahash_im.rows];
|
||||||
|
mempcpy(mhash_sorted, pixel, endPixel);
|
||||||
|
double m_median = median(mhash_sorted, endPixel);
|
||||||
|
|
||||||
for (int i = 0; i < endPixel; i++) {
|
for (int i = 0; i < endPixel; i++) {
|
||||||
set_bit_at(out->ahash, i, pixel[i] > avg);
|
set_bit_at(out->ahash, i, pixel[i] > avg);
|
||||||
|
set_bit_at(out->mhash, i, pixel[i] > m_median);
|
||||||
}
|
}
|
||||||
|
|
||||||
//dhash
|
//dhash
|
||||||
|
@ -13,6 +13,7 @@ typedef struct multi_hash {
|
|||||||
uchar *phash;
|
uchar *phash;
|
||||||
uchar *dhash;
|
uchar *dhash;
|
||||||
uchar *whash;
|
uchar *whash;
|
||||||
|
uchar *mhash;
|
||||||
} multi_hash_t;
|
} multi_hash_t;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -31,12 +32,10 @@ void hash_to_hex_string_reversed(const uchar *h, char *out, int hash_size);
|
|||||||
|
|
||||||
void hash_to_hex_string(const uchar *h, char *out, int hash_size);
|
void hash_to_hex_string(const uchar *h, char *out, int hash_size);
|
||||||
|
|
||||||
/**
|
int mhash_mem(void *buf, uchar *out, size_t buf_len, int hash_size);
|
||||||
*
|
|
||||||
* @param buf
|
int mhash_file(const char *filepath, uchar *out, int hash_size);
|
||||||
* @param buf_len
|
|
||||||
* @param hash_size
|
|
||||||
*/
|
|
||||||
int ahash_mem(void *buf, uchar *out, size_t buf_len, int hash_size);
|
int ahash_mem(void *buf, uchar *out, size_t buf_len, int hash_size);
|
||||||
|
|
||||||
int ahash_file(const char *filepath, uchar *out, int hash_size);
|
int ahash_file(const char *filepath, uchar *out, int hash_size);
|
||||||
|
12
imhash.c
12
imhash.c
@ -14,7 +14,7 @@ int main(int argc, char *argv[]) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int do_phash = 0, do_ahash = 0, do_whash = 0, do_dhash = 0;
|
int do_phash = 0, do_ahash = 0, do_whash = 0, do_dhash = 0, do_mhash = 0;
|
||||||
|
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
if (strcmp(argv[i], "--phash") == 0) {
|
if (strcmp(argv[i], "--phash") == 0) {
|
||||||
@ -25,6 +25,8 @@ int main(int argc, char *argv[]) {
|
|||||||
do_whash = 1;
|
do_whash = 1;
|
||||||
} else if (strcmp(argv[i], "--dhash") == 0) {
|
} else if (strcmp(argv[i], "--dhash") == 0) {
|
||||||
do_dhash = 1;
|
do_dhash = 1;
|
||||||
|
} else if (strcmp(argv[i], "--mhash") == 0) {
|
||||||
|
do_mhash = 1;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
uchar hash[9];
|
uchar hash[9];
|
||||||
@ -54,6 +56,12 @@ int main(int argc, char *argv[]) {
|
|||||||
printf("%s\tw:%s\n", argv[i], hashstr);
|
printf("%s\tw:%s\n", argv[i], hashstr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (do_mhash) {
|
||||||
|
if (mhash_file(argv[i], hash, 8) == 0) {
|
||||||
|
hash_to_hex_string_reversed(hash, hashstr, 8);
|
||||||
|
printf("%s\tm:%s\n", argv[i], hashstr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
multi_hash_t *m = multi_hash_create(8);
|
multi_hash_t *m = multi_hash_create(8);
|
||||||
multi_hash_file(argv[i], m, 8, 4, 0);
|
multi_hash_file(argv[i], m, 8, 4, 0);
|
||||||
@ -66,6 +74,8 @@ int main(int argc, char *argv[]) {
|
|||||||
printf("%s\tmd:%s\n", argv[i], hashstr);
|
printf("%s\tmd:%s\n", argv[i], hashstr);
|
||||||
hash_to_hex_string_reversed(m->whash, hashstr, 8);
|
hash_to_hex_string_reversed(m->whash, hashstr, 8);
|
||||||
printf("%s\tmw:%s\n", argv[i], hashstr);
|
printf("%s\tmw:%s\n", argv[i], hashstr);
|
||||||
|
hash_to_hex_string_reversed(m->mhash, hashstr, 8);
|
||||||
|
printf("%s\tmm:%s\n", argv[i], hashstr);
|
||||||
|
|
||||||
multi_hash_destroy(m);
|
multi_hash_destroy(m);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user