首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV图像哈希计算及汉明距离的计算

OpenCV图像哈希计算及汉明距离的计算

作者头像
Pulsar-V
发布2018-04-18 16:34:50
1.7K0
发布2018-04-18 16:34:50
举报
文章被收录于专栏:Pulsar-VPulsar-V

OpenCV均值哈希与感知哈希计算,比对图像相似度,当计算出来的汉明距离越大,图像的相似度越小,汉明距离越小,图像的相似度越大,这种没有基于特征点的图像比对用在快速搜索引擎当中可以有效的进行图像搜索.

离散傅里叶变换的推导 具体代码和OpenCV代码请移步到博客

下面附上Mathmetica代码

设X (n) 是一个长度为M的有限长序列,则定义X (n) 的N点离散傅里叶变换为

X (k) = DFT[x (n)] = 
\!\(\*UnderscriptBox[
OverscriptBox[\(\[Sum]\), \(N - 1\)], \(K = 0\)]\) 
   x (n) Subscript[W, N]^kn , k = 0, 1, ..., N - 1
X (k) 的傅里叶逆变换为
x (n) = IDFT[X (k)] = 
\!\(\*UnderscriptBox[
OverscriptBox[\(\[Sum]\), \(N - 1\)], \(k = 0\)]\)X (k) Subscript[
    W^-kn, N], k = 0, 1, 2, 3, 4, ...., N - 1
式中, Subscript[W, N] = 
 e^(-j*2 \[Pi]/N) N称为DFT变换区间长度,N \[GreaterSlantEqual] 
 M通常称 (1) 式和 (2) 式为离散傅里叶变换对。
下面来证明IDFT[X (k)] 的唯一性
把 (1) 代入 (2) 有
IDFT[X (k)] = (1/N) 
\!\(\*UnderscriptBox[
OverscriptBox[\(\[Sum]\), \(N - 1\)], \(k = 0\)]\)[
\!\(\*UnderscriptBox[
OverscriptBox[\(\[Sum]\), \(N - 1\)], \(m = 0\)]\) 
       x (m) Subscript[W^mk, N]] Subscript[W^-kn, N] =
  
\!\(\*UnderscriptBox[
OverscriptBox[\(\[Sum]\), \(N - 1\)], \(m = 0\)]\)x (m) (1/N) 
\!\(\*UnderscriptBox[
OverscriptBox[\(\[Sum]\), \(N - 1\)], \(k = 0\)]\)Subscript[W^(
     k (m - n)), N]
(1/N) 
\!\(\*UnderscriptBox[
OverscriptBox[\(\[Sum]\), \(N - 1\)], \(k = 0\)]\)Subscript[W^(
   k (m - n)), N] = { 
\!\(\*OverscriptBox[
UnderscriptBox[\(\[Placeholder]\), \(0\ \ \ \ \ \ \ \ \ \ \ \ \ \ m \
\[NotEqual] n + MN, M为整数\)], \(1\ \ \ \ \ \ \ \ \ \ \ \ \ m = n + MN, 
     M为整数\)]\)  
    所以,在变换区间上满足下式
     IDFT[X (k)] = x (n), 0 \[LessSlantEqual] n \[LessSlantEqual] N - 1
      (2) 式定义的离散傅里叶变换是唯一的。

感知哈希

string p_hashCode(Mat src) {
    //第一步,转换颜色空间,简化图像像素
    Mat img, dst;//初始化矩阵IO
    string rst(64, '\0');//初始化哈希值
    double dIdex[64];//初始化矩阵列表
    double mean = 0.0;//初始化均值
    int k = 0;//初始化矩阵行列计数
    //判断图像空间,当图像空间为3位空间的时候转换图像空间为灰度矩阵
    if (src.channels() == 3) {
        cvtColor(src, src, CV_BGR2GRAY);
        img = Mat_<double>(src);
    } else {
        img = Mat_<double>(src);
    }

    // 第二步,缩放尺寸 
    //这里将整个图像缩放到变成一个8*8的图像矩阵,汉明长度为8*8=64个字节长度
    //最快速的去除高频和细节,只保留结构明暗的方法就是缩小尺寸。
    //将图片缩小到8x8的尺寸,总共64个像素。摒弃不同尺寸、比例带来的图片差异。
    resize(img, img, Size(8, 8));

    // 第三步,离散余弦变换,DCT系数求取
    //离散余弦变换(DCT for Discrete Cosine Transform)是与傅里叶变换相关的一种变换      
    //它类似于离散傅里叶变换(DFT for Discrete Fourier Transform),但是只使用实数
    dct(img, dst);

    /* 第四步,求取DCT系数均值(左上角8*8区块的DCT系数)*/
    for (int i = 0; i < 8; ++i) {//迭代矩阵行
        for (int j = 0; j < 8; ++j) {//迭代矩阵列
            //第i行j列的图像灰度值
            dIdex[k] = dst.at<double>(i, j);
            //计算均值,此均值相对于8*8矩阵的总像素点的均值
            mean += dst.at<double>(i, j) / 64;
            k++;
        }
    }

    // 第五步,计算哈希值
    //遍历像素矩阵,当矩阵的灰度值大于均值的时候哈希为1,当矩阵的灰度值小于均值     
    //的时候哈希为2
    for (int i = 0; i < 64; ++i) {
        if (dIdex[i] >= mean) {
            rst[i] = '1';
        } else {
            rst[i] = '0';
        }
    }
    return rst;
}

均值哈希计算

string a_hashCode(Mat src) {
    string rst(64, '\0');
    Mat img;
    if (src.channels() == 3)
        cvtColor(src, img, CV_BGR2GRAY);
    else
        img = src.clone();
     //第一步,缩小尺寸。
     //将图片缩小到8x8的尺寸,总共64个像素
    resize(img, img, Size(8, 8));
    /* 第二步,简化色彩(Color Reduce)。
       将缩小后的图片,转为64级灰度。*/
    uchar *pData;
    for (int i = 0; i < img.rows; i++) {
        //取出矩阵每一行的数据
        pData = img.ptr<uchar>(i);
        for (int j = 0; j < img.cols; j++) {
            //将矩阵每一列的数据除以4
            pData[j] = pData[j] / 4;
        }
    }
    //第三步,计算平均值。
    //计算所有64个像素的灰度平均值.
    int average = mean(img).val[0];
    //第四步,比较像素的灰度。
    //将每个像素的灰度,与平均值进行比较。大于或等于平均值记为1,小于平均值记为0 
    Mat mask = (img >= (uchar) average);
    //第五步,计算哈希值
    int index = 0;
    for (int i = 0; i < mask.rows; i++) {
        pData = mask.ptr<uchar>(i);
        for (int j = 0; j < mask.cols; j++) {
            if (pData[j] == 0)
                rst[index++] = '0';
            else
                rst[index++] = '1';
        }
    }
    return rst;
}

计算汉明距离

/**
汉明距离函数取哈希字符串进行比对,两字符串长度必须相等才能计算准确的距离
*/
int HanmingDistance(string &str1, string &str2) {
    //判断当两个字符串的长度是否相等
    if ((str1.size() != 64) || (str2.size() != 64))
        return -1;
    int difference = 0;
    //遍历字符串比较两个字符串的0与1的不相同的地方,不相同一次就长度增加1从而计   
    //算总距离
    for (int i = 0; i < 64; i++) {
        if (str1[i] != str2[i])
            difference++;
    }
    return difference;
}
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 感知哈希
  • 均值哈希计算
  • 计算汉明距离
相关产品与服务
图像搜索
图像搜索(Image Search)基于腾讯云的图像解决方案,集成了图像检索、超细粒度元素挖掘和图像匹配等技术,通过以图搜图的方式在用户自建图片库中快速检索出与输入图片相同或相似的图片集合,可应用于图片版权保护、电商侵权审核、相似素材查询、同款商品搜索与推荐等场景。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档