以图搜图--感知哈希算法

以图搜图的关键技术叫做“感知哈希算法”(Perceptual hash algorithm),用一个特征向量(“指纹”(fingerprint)字符串)来描叙一张图片,然后比较不同图像的指纹,差异越小,说明图像越相似。

1、均值hash算法
实现步骤如下:
(1)缩小尺寸,将图像缩小到8*8大小
(2)将图像灰度级减小到64级
(3)计算8*8图像大小的灰度均值
(4)比较像素的灰度,用8*8图像大小的每一个像素灰度值与均值进行比较,大于均值的为1,小于的为0
(5)将得到的结果排列成一个64位的向量,该向量就是该图的“指纹”,即hash值

如果要判断两张图是否相似,只需要计算这两张图的hash值,然后计算两个hash值的汉明距离(异或运算,不同的位为1),一般来说,汉明距离小于等于5,表示两张图比较相似,如果大于10,就基本不相似。

代码如下:

string Hash(Mat src)
{
    Mat img,img1;
    if (src.channels()==3)
    {
        cvtColor(src,img1,CV_BGR2BGRA);
    }
    else
    {
        img1 = src.clone();
    }

    //第一步,缩小尺寸
    resize(img1, img, Size(8, 8));

    //第二步,灰度级减小到64
    int sum=0;
    for (int i = 0; i < img.rows;i++)
    {
        for (int j = 0; j < img.cols;j++)
        {
            img.at<uchar>(i, j) = (int)img.at<uchar>(i, j)/ 4;
            sum += img.at<uchar>(i, j);
        }
    }

    //第三步,计算均值
    //int average= mean(img).val[0];
    int average = sum / 64;

    //第四步,比较灰度大小
    //第五步,计算hash值

    //Mat mask = img >= (uchar)average;

    string rst1(64, '\0');
    int index1 = 0;
    for (int i = 0; i < img.rows; i++)
    {
        for (int j = 0; j < img.cols; j++)
        {
            if (img.at<uchar>(i, j) >= (uchar)average)
            {
                rst1[index1] = '1';
            }
            else
            {
                rst1[index1] = '0';
            }
            index1++;
        }
    }

    ////第五步,计算hash值
    //string rst(64, '\0');
    //int index = 0;
    //for (int i = 0; i < mask.rows; i++)
    //{
    // for (int j = 0; j < mask.cols; j++)
    // {
    // if (mask.at<uchar>(i,j)==0)
    // {
    // rst[index] = '0';
    // }
    // else
    // rst[index] = '1';
    // index++;
    // }
    //}

    //返回hash值字符串

    return(rst1);
}

2、pHash算法
hash算法计算简单,但是容易受均值的影响,另有一个增强版的算法叫pHash算法,主要区别是在减小原始图像大小的时候,采用离散余弦变换(dct)来获取图像的低频部分。
图像是一个二维信号,其低频信息代表了图像的整体轮廓,高频信息代表了图像的边缘(细节)。
实现步骤如下:
(1)缩小尺寸,将图像缩小到8*8大小
(2)彩色图转灰度图
(3)计算dct变换,求取dct系数均值(左上角8*8区块的dct系数)
(4)比较8*8区块的dct值,大于dct均值的为1,小于的为0
(5)将得到的结果排列成一个64位的向量,该向量就是该图的“指纹”,即hash值
实现代码就不贴了,跟上面的基本一样,opencv自带dct函数,dct(img, dst);

hash算法是不抗旋转和尺度变化的,不过在一定程度上,pHash算法的鲁棒性要高于均值Hash算法,而真正像google和百度的商用的以图搜图功能,是需要对其进行改进并配上其他的算法。
当然,hash算法是可以用来进行目标跟踪的,后面研究了之后再写。
总的来说,就是用一个向量来表示一张图,然后计算向量之间的差异来进行判断。

主要参考:
http://blog.csdn.net/lsjseu/article/details/17692229
http://blog.csdn.net/eternity1118_/article/details/51088019
感谢博主。

    原文作者:哈希算法
    原文地址: https://blog.csdn.net/baidu_30028771/article/details/61618398
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞