图片搜索/匹配PHASH实现改进

发布: 2012-12-09 15:19

phash是一个图片特征抽取算法实现,
该算法相对还比较简单,特征值只是一个64位无符号整数。
在使用PHP扩展程序处理的时候,原版本的扩展只返回资源类型的值,
只能实时做对比处理,无法把它存储起来。

通过阅读它的PHP扩展,发现修改一下代码即能把资源转变为整数返回,
添加一个扩展函数,PHP_FUNCTION(phash_toint);
参数为使用phash_imagehash返回的资源类型值,
实现函数为,
PHP_FUNCTION(phash_toint)
{
zval * h1_res = NULL;
int h1_resid = -1;
ulong64 * h1;
zval * h2_res = NULL;
int h2_resid = -1;
ulong64 * h2;

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &h1_res) == FAILURE) {
return;
}
ZEND_FETCH_RESOURCE(h1, ulong64 *, &h1_res, h1_resid, "ph_image_hash", le_ph_image_hash);

long long int ih1 = *h1;
char rbuf[32] = {0};
sprintf(rbuf, "%lu", ih1);

RETVAL_STRING(rbuf, true);
}

这样可以把图片的特征值存储起来,如存储在关系数据库中,后面可以直接拿来使用。

另外,以使用mysql为例,通过编写一个mysql用户定义函数,
可以在查询的时候直接调用特征匹配算法,把匹配度在一定范围的结果返回,

my_bool ham_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
return 0;
}

void ham_deinit(UDF_INIT *initid)
{
}

long long ham(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
{
ulonglong ih1 = *((ulonglong*) args->args[0]);
ulonglong ih2 = *((ulonglong*) args->args[1]);

ulonglong x = ih1 ^ ih2;
// x = 11611742962838811245UL ^ 10221281696820229275UL;
const ulonglong m1 = 0x5555555555555555ULL;
const ulonglong m2 = 0x3333333333333333ULL;
const ulonglong h01 = 0x0101010101010101ULL;
const ulonglong m4 = 0x0f0f0f0f0f0f0f0fULL;

x -= (x >> 1) & m1;
x = (x & m2) + ((x >> 2) & m2);
x = (x + (x >> 4)) & m4;

return (x * h01)>>56;
}
自定义函数 ham(h1, h2);的两个参数是需要计算的两个图片的特征值,
返回值为特征的相似度,越小越相似,为0的时候为完全相同。
通过编写mysql自定义函数的方式,把这个编译成一个插件,加载到mysql中,
如如下SQL,
select * from t1 where ham(phash_value_field, 34567) < 10;
即可检索出匹配度小于10结果。

参考:
phash主站,http://www.phash.org




原文: http://qtchina.tk/?q=node/701

Powered by zexport