原地址:http://blog.csdn.net/guoming0000/article/details/8138223

以前看到一个http://topic.csdn.net/u/20120417/15/edbf86f8-cfec-45c3-93e1-67bd555c684a.html网页,觉得蛮有趣的,方法似乎很简单,早就想用c++实现它,但是搁置很久,今天突然感兴趣实现了下。给一个免费的下载java源代码地址:http://download.csdn.net/detail/yjflinchong/4239243,图片你可以用他们的图片~~

以下程序中的图片自己随便找。

主题内容摘录:

Google "相似图片搜索":你可以用一张图片,搜索互联网上所有与它相似的图片。
打开Google图片搜索页面:
点击使用上传一张angelababy原图:
点击搜索后,Google将会找出与之相似的图片,图片相似度越高就越排在前面。

这种技术的原理是什么?计算机怎么知道两张图片相似呢?

根据Neal Krawetz博士的解释,实现相似图片搜素的关键技术叫做"感知哈希算法"(Perceptualhash algorithm),它的作用是对每张图片生成一个"指纹"(fingerprint)字符串,然后比较不同图片的指纹。结果越接近,就说明图片越相似。
以下是一个最简单的Java实现:
预处理:读取图片
第一步,缩小尺寸。

将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。
第二步,简化色彩。

将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
第三步,计算平均值。
  计算所有64个像素的灰度平均值。
第四步,比较像素的灰度。
  将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
第五步,计算哈希值。
   将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。
  得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。在理论上,这等同于计算"汉明距离"(Hammingdistance)。如果不相同的数据位不超过5,就说明两张图片很相似;如果大于10,就说明这是两张不同的图片。
  你可以将几张图片放在一起,也计算出他们的汉明距离对比,就可以看看两张图片是否相似。
   这种算法的优点是简单快速,不受图片大小缩放的影响,缺点是图片的内容不能变更。如果在图片上加几个文字,它就认不出来了。所以,它的最佳用途是根据缩略图,找出原图。
    实际应用中,往往采用更强大的pHash算法和SIFT算法,它们能够识别图片的变形。只要变形程度不超过25%,它们就能匹配原图。这些算法虽然更复杂,但是原理与上面的简便算法是一样的,就是先将图片转化成Hash字符串,然后再进行比较。

用的OpenCV打开图像(貌似没有opencv寸步难行呢,囧)

  1. // Win32TestPure.cpp : 定义控制台应用程序的入口点。
  2. #include "stdafx.h"
  3. //#include <atlstr.h>//CString, CEdit
  4. #include "opencv2\opencv.hpp"
  5. #include <hash_map>
  6. //----------------------------------------------------
  7. using namespace std;
  8. using namespace cv;
  9. class PhotoFingerPrint
  10. {
  11. public:
  12. int     Distance(string &str1,string &str2);
  13. string  HashValue(Mat &src);        //主要功能函数
  14. void    Insert(Mat &src,string &val);
  15. void    Find(Mat &src);
  16. private:
  17. Mat     m_imgSrc;
  18. hash_map<string,string> m_hashMap;
  19. };
  20. string PhotoFingerPrint::HashValue(Mat &src)
  21. {
  22. string rst(64,'\0');
  23. Mat img;
  24. if(src.channels()==3)
  25. cvtColor(src,img,CV_BGR2GRAY);
  26. else
  27. img=src.clone();
  28. // 第一步,缩小尺寸。
  29. /*将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,
  30. 只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。*/
  31. resize(img,img,Size(8,8));//缩小尺寸
  32. // 第二步,简化色彩。
  33. // 将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。
  34. uchar *pData;
  35. for(int i=0;i<img.rows;i++)
  36. {
  37. pData = img.ptr<uchar>(i);
  38. for(int j=0;j<img.cols;j++)
  39. {
  40. pData[j]=pData[j]/4;   //0~255--->0~63
  41. }
  42. }
  43. // 第三步,计算平均值。
  44. // 计算所有64个像素的灰度平均值。
  45. int average = mean(img).val[0];
  46. // 第四步,比较像素的灰度。
  47. // 将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。
  48. Mat mask= (img>=(uchar)average);//////
  49. // 第五步,计算哈希值。
  50. /* 将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。
  51. 组合的次序并不重要,只要保证所有图片都采用同样次序就行了。
  52. */
  53. int index = 0;
  54. for(int i=0;i<mask.rows;i++)
  55. {
  56. pData = mask.ptr<uchar>(i);
  57. for(int j=0;j<mask.cols;j++)
  58. {
  59. if(pData[j]==0)
  60. rst[index++]='0';
  61. else
  62. rst[index++]='1';
  63. }
  64. }
  65. return rst;
  66. }
  67. void    PhotoFingerPrint::Insert(Mat &src,string &val)
  68. {
  69. string strVal = HashValue(src);
  70. m_hashMap.insert(pair<string,string>(strVal,val));
  71. cout<<"insert one value:"<<strVal<<"   string:"<<val<<endl;
  72. }
  73. void    PhotoFingerPrint::Find(Mat &src)
  74. {
  75. string strVal=HashValue(src);
  76. hash_map<string,string>::iterator it=m_hashMap.find(strVal);
  77. if(it==m_hashMap.end())
  78. {cout<<"no photo---------"<<strVal<<endl;}
  79. else
  80. cout<<"find one , key:  "<<it->first<<"   value:"<<it->second<<endl;
  81. /* return *it;*/
  82. }
  83. int PhotoFingerPrint::Distance(string &str1,string &str2)
  84. {
  85. if((str1.size()!=64)||(str2.size()!=64))
  86. return -1;
  87. int difference = 0;
  88. for(int i=0;i<64;i++)
  89. {
  90. if(str1[i]!=str2[i])
  91. difference++;
  92. }
  93. return difference;
  94. }
  95. int main(int argc, char* argv[] )
  96. {
  97. PhotoFingerPrint pfp;
  98. Mat m1=imread("images\\example3.jpg",0);
  99. Mat m2=imread("images\\example4.jpg",0);
  100. Mat m3=imread("images\\example5.jpg",0);
  101. Mat m4=imread("images\\example6.jpg",0);
  102. Mat m5;
  103. resize(m3,m5,Size(100,100));
  104. string str1 = pfp.HashValue(m1);
  105. string str2 = pfp.HashValue(m2);
  106. string str3 = pfp.HashValue(m3);
  107. string str4 = pfp.HashValue(m4);
  108. pfp.Insert(m1,string("str1\0"));
  109. pfp.Insert(m2,string("str2\0"));
  110. pfp.Insert(m3,string("str3\0"));
  111. pfp.Insert(m4,string("str4\0"));
  112. pfp.Find(m5);
  113. //     cout<<pfp.Distance(str1,str1)<<endl;
  114. //     cout<<pfp.Distance(str1,str2)<<endl;
  115. //     cout<<pfp.Distance(str1,str3)<<endl;
  116. //     cout<<pfp.Distance(str1,str4)<<endl;
  117. return 0;
  118. }

好吧,只有当加入足够多的图像,这个哈希表才有意义。本程序给了一个大致的模型,细节都没有进行推敲(hash_map第一次用)。希望大家提点意见。

[半原创]指纹识别+谷歌图片识别技术之C++代码的更多相关文章

  1. java指纹识别+谷歌图片识别技术_源代码

    主类: import java.awt.image.BufferedImage; import java.util.ArrayList; import java.util.List; public c ...

  2. java指纹识别+谷歌图片识别技术

    http://www.icodeguru.com/3/2451.html http://valseonline.org/thread-124-1-1.html

  3. C# 图片识别技术(支持21种语言,提取图片中的文字)

    图片识别的技术到几天已经很成熟了,只是相关的资料很少,为了方便在此汇总一下(C#实现),方便需要的朋友查阅,也给自己做个记号. 图片识别的用途:很多人用它去破解网站的验证码,用于达到自动刷票或者是批量 ...

  4. 【Machine Learning】KNN算法虹膜图片识别

    K-近邻算法虹膜图片识别实战 作者:白宁超 2017年1月3日18:26:33 摘要:随着机器学习和深度学习的热潮,各种图书层出不穷.然而多数是基础理论知识介绍,缺乏实现的深入理解.本系列文章是作者结 ...

  5. Web指纹识别目的Discuz识别+粗糙的版本演绎

    这个识别程序是本学期在我的职业培训项目.它是做一类似至Zoomeye怪东西,然后使用ES集成,为了让搜索引擎寻找.因此,我们必须首先去网上识别相应的能力Web包裹,如果用户输入的关键词:Discuz ...

  6. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇一:WPF常用知识以及本项目设计总结

    篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...

  7. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇二:基于OneNote难点突破和批量识别

    篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...

  8. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇三:批量处理后的txt文件入库处理

    篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...

  9. 【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇四:关于OneNote入库处理以及审核

    篇一:WPF常用知识以及本项目设计总结:http://www.cnblogs.com/baiboy/p/wpf.html 篇二:基于OneNote难点突破和批量识别:http://www.cnblog ...

随机推荐

  1. 网盘大全, 邮箱大全 good

    网盘推荐 115网盘 注册 百度网盘 注册 微云 注册 360云盘 注册 金山快盘 注册 新浪微盘 注册 和彩云 注册 酷盘 注册 OneDrive 外链 BOX 注册 Dropbox 注册 国内网盘 ...

  2. swift 有些语法还是不支持。

    <pre name="code" class="html">"func hasAnyMatches(list: Int[], condit ...

  3. check————身份证

    -- Access 不支持 Substring 查询,可以替换为 mid 查询. select 序号,姓名,身份证号,性别from 身份表where (len(身份证号)<>15 and ...

  4. EasyUI - DataGrid 组建 - [ 新增功能 ]

    效果: html代码: <div> <!--使用JS加载方式--> <table id="tab"></table> <!-- ...

  5. TCanvas.CopyRect方法中参数CopyMode的意义

    首先看可能取值: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 cmBlackness = BLACKNESS; cmDstInvert = DSTINVERT; cmMer ...

  6. Zend Studio安装和使用

    Zend Studio安装和使用 工欲利其事必先利其器 1.ZendStudio 下载 下载地址:http://www.zend.com.安装就和典型的windows软件安装一样.直接next,nex ...

  7. (升级版)Spark从入门到精通(Scala编程、案例实战、高级特性、Spark内核源码剖析、Hadoop高端)

    本课程主要讲解目前大数据领域最热门.最火爆.最有前景的技术——Spark.在本课程中,会从浅入深,基于大量案例实战,深度剖析和讲解Spark,并且会包含完全从企业真实复杂业务需求中抽取出的案例实战.课 ...

  8. linux-mint下搭建android,angularjs,rails,html5开发环境 - qijie29896的个人空间 - 开源中国社区

    linux-mint下搭建android,angularjs,rails,html5开发环境 - qijie29896的个人空间 - 开源中国社区 http://blog.csdn.net/orzor ...

  9. [Java Performance] 数据库性能最佳实践 - JPA缓存

    JPA缓存(JPA Caching) JPA有两种类型的缓存: EntityManager自身就是一种缓存.事务中从数据库获取的和写入到数据库的数据会被缓存(什么样的数据会被缓存.在后面有介绍).在一 ...

  10. DELPHI 通過窗口句柄或窗口标题得到进程句柄

    DELPHI 通過窗口句柄或窗口标题得到进程句柄2009年05月08日 星期五 10:15procedure TForm1.Button1Click(Sender: TObject);varhWind ...