文档章节

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

Pulsar-V
 Pulsar-V
发布于 2017/07/24 15:16
字数 1323
阅读 801
收藏 18

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;
}

© 著作权归作者所有

Pulsar-V

Pulsar-V

粉丝 61
博文 150
码字总数 135866
作品 1
成都
后端工程师
私信 提问
加载中

评论(1)

Stronger飞
Stronger飞
创造性
图像检索的三种python实现(直方图/OpenCV/哈希法)

简介: 本文介绍了图像检索的三种实现方式,均用python完成,其中前两种基于直方图比较,哈希法基于像素分布。 检索方式是:提前导入图片库作为检索范围,给出待检索的图片,将其与图片库中的...

漫步当下
2018/07/09
0
0
7行Python代码的人脸识别

版权声明:本文为半吊子子全栈工匠(wirelesscom,同公众号)原创文章,未经允许不得转载。 https://blog.csdn.net/wirelesscom/article/details/64120516 随着去年alphago 的震撼表现,AI 再...

abel_cao
01/17
0
0
深刻了解OPENCV

OpenCV是Intel资助的开源计算机视觉库。它由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法。 OpenCV 拥有包括 300 多个C/C++函数的跨平台的中、高层 API。...

红薯
2008/12/10
3.3K
3
【译文】16个OpenCV功能开启你的计算机视觉之旅(附Python代码)

原文标题:16 OpenCV Functions to Start your Computer Vision journey (with Python code) 原文链接:https://www.analyticsvidhya.com/blog/2019/03/opencv-functions-computer-vision-p......

等花花不开
04/23
0
0
使用OpenCV和Python拼接图像

写在前面 首先这是一篇英文博客的翻译,先放上链接:https://www.pyimagesearch.com/2018/12/17/image-stitching-with-opencv-and-python/ 翻译是靠谷歌翻译和自己的理解,个别地方翻译有点问...

W_Tortoise
2018/12/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

只需一步,在Spring Boot中统一Restful API返回值格式与统一处理异常

统一返回值 在前后端分离大行其道的今天,有一个统一的返回值格式不仅能使我们的接口看起来更漂亮,而且还可以使前端可以统一处理很多东西,避免很多问题的产生。 比较通用的返回值格式如下:...

晓月寒丶
昨天
59
0
区块链应用到供应链上的好处和实际案例

区块链可以解决供应链中的很多问题,例如记录以及追踪产品。那么使用区块链应用到各产品供应链上到底有什么好处?猎头悬赏平台解优人才网小编给大家做个简单的分享: 使用区块链的最突出的优...

猎头悬赏平台
昨天
28
0
全世界到底有多少软件开发人员?

埃文斯数据公司(Evans Data Corporation) 2019 最新的统计数据(原文)显示,2018 年全球共有 2300 万软件开发人员,预计到 2019 年底这个数字将达到 2640万,到 2023 年达到 2770万。 而来自...

红薯
昨天
65
0
Go 语言基础—— 通道(channel)

通过通信来共享内存(Java是通过共享内存来通信的) 定义 func service() string {time.Sleep(time.Millisecond * 50)return "Done"}func AsyncService() chan string {retCh := mak......

刘一草
昨天
58
0
Apache Flink 零基础入门(一):基础概念解析

Apache Flink 的定义、架构及原理 Apache Flink 是一个分布式大数据处理引擎,可对有限数据流和无限数据流进行有状态或无状态的计算,能够部署在各种集群环境,对各种规模大小的数据进行快速...

Vincent-Duan
昨天
60
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部