为什么aHash比dHash更好用

Why does aHash work better than dHash?

本文关键字:更好 dHash aHash 为什么      更新时间:2023-10-16

我对aHash和dHash有一些问题:http://www.hackerfactor.com/blog/?/archives/529-Kind-of-Like-That.html

我用了C++和OpenCV

问题是dHash比aHash工作得更差。虽然理论上应该更好。例如:我选择了一张图片,对其进行了一些操作,并计算了原始图像和修改图像哈希之间的汉明距离。结果就在那里

这是哈希的函数

__int64 calcImageHash(IplImage* src, bool show_results)
{
    if(!src){
        return 0;
    }
    IplImage *res=0, *gray=0, *bin =0;
    res = cvCreateImage( cvSize(8, 8), src->depth, src->nChannels);
    gray = cvCreateImage( cvSize(8, 8), IPL_DEPTH_8U, 1);
    bin = cvCreateImage( cvSize(8, 8), IPL_DEPTH_8U, 1);
    cvResize(src, res);
    cvCvtColor(res, gray, CV_BGR2GRAY);
    CvScalar average = cvAvg(gray);
    printf("[i] average: %.2f n", average.val[0]);
    cvThreshold(gray, bin, average.val[0], 255, CV_THRESH_BINARY);
    __int64 hash = 0;
    int i=0;
    for( int y=0; y<bin->height; y++ ) {
        uchar* ptr = (uchar*) (bin->imageData + y * bin->widthStep);
        for( int x=0; x<bin->width; x++ ) {
            if(ptr[x]){
                hash |= (__int64)1<<i;
            }
            i++;
        }
    }
    printf("[i] hash: %I64X n", hash);
    cvReleaseImage(&res);
    cvReleaseImage(&gray);
    cvReleaseImage(&bin);
    return hash;
}

和 dHash 的函数

__int64 calcImageHash(IplImage* src, bool show_results)
{
    if(!src)
    {
        return 0;
    }
    IplImage *res=0, *gray=0;
    res = cvCreateImage( cvSize(9,8), src->depth, src->nChannels);
    gray = cvCreateImage( cvSize(9,8), IPL_DEPTH_8U, 1);
    cvResize(src, res);
    cvCvtColor(res, gray, COLOR_BGR2GRAY);
    __int64 hash = 0;
    int i=0;
    cout<<gray->height;
    for( int y=0; y<gray->height; y++ ) {
        uchar* ptr = (uchar*) (gray->imageData + y* gray->widthStep);
        for( int x=0; x<gray->width-1; x++ ) {
            if( ptr[x+1] > ptr[x] ){
                hash |= (__int64)1<<i;
            }
            i++;
        }
    }
    printf("[i] hash: %I64X n", hash, "n");
    std::cout<<endl;
    cvReleaseImage(&res);
    cvReleaseImage(&gray);
    return hash;
}

以防万一有人也遇到这种情况,我注意到 dhash 在插图和一些艺术品方面有一个特定的弱点。

更具体地说,对于任何对比度非常低或包含大面积纯色的图像,它都倾向于随机性。我正在处理一系列艺术照片,对于草图、线条绘制或艺术品本身由纯色通道框住的地方,这个问题尤其明显。

为什么

会发生这种情况有点明显:固体区域很容易随机看到一个片段比相邻的片段略亮,即使是轻微的有损压缩伪影。但我对它的大小感到有些惊讶:简单地将图像缩放 50% 通常会导致肉眼无法区分的图像,但会产生接近随机性的 dhash 差异。

我已经看到了一些改进,通过比较不是关于>= 与 <,而是添加一些任意的偏差,例如需要>= (b + 15(。这里的原因是纯色相对丰富,但线性梯度(这将再次导致相同的病理(相对罕见。如果这仍然是一个问题,也可以使偏差随机但与位置相关,即"在 (x=3, y=5( 处加 12,在 x=20, y=5 处减去 3(。大量图像具有匹配图案的概率将远低于纯色和明确规定的渐变。