精华内容
下载资源
问答
  • 本文给大家分享的是使用Python实现图片相似度识别的总结,代码实用pil模块比较两个图片的相似度,根据实际实用,代码虽短但效果不错,还是非常靠谱的。
  • 利用python进行识别相似图片

    万次阅读 2016-12-15 17:16:22
    利用python进行识别相似图片(一) 文章简介 在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系。 当然了,图像识别这个...

    转自:https://segmentfault.com/a/1190000004467183

    利用python进行识别相似图片(一)

    文章简介

    在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系。

    当然了,图像识别这个话题作为计算机科学的一个分支,不可能就在本文简单几句就说清,所以 本文只作基本算法的科普向 。

    如有错误,请多包涵和多多指教。

    参考的文章和图片来源会在底部一一列出。

    以及本篇文章所用的代码都会在底下给出github地址。

    安装相关库

    python用作图像处理的相关库主要有 openCV (C++编写,提供了python语言的接口), PIL ,但由于PIL很早就停了,所以不支持python3.x,所以建议使用基于PIL的 pillow ,本文也是在python3.4和pillow的环境下进行实验。

    至于opencv,在做人脸识别的时候会用到,但本文不会涉及到, 在本专栏的后续中会谈及openCV的人脸识别和基于此的python图片爬虫,有兴趣的朋友可以关注本专栏。

    相关背景

    要识别两张相似图像,我们从感性上来谈是怎么样的一个过程?首先我们会区分这两张相片的类型,例如是风景照,还是人物照。风景照中,是沙漠还是海洋,人物照中,两个人是不是都是国字脸,还是瓜子脸(还是倒瓜子脸……哈哈……)。

    那么从机器的角度来说也是这样的,先识别图像的特征,然后再相比。

    很显然,在没有经过训练的计算机(即建立模型),那么计算机很难区分什么是海洋,什么是沙漠。但是计算机很容易识别到图像的像素值。

    因此,在图像识别中, 颜色特征 是最为常用的。(其余常用的特征还有 纹理特征、 形状特征 和 空间关系特征 等)

    其中又分为

    • 直方图

    • 颜色集

    • 颜色矩

    • 聚合向量

    • 相关图

    直方图计算法

    这里先用直方图进行简单讲述。

    先借用一下 恋花蝶 的图片,

    从肉眼来看,这两张图片大概也有八成是相似的了。

    在python中可以依靠 Image 对象的 histogram() 方法获取其直方图数据,但这个方法返回的结果是一个列表,如果想得到下图可视化数据,需要另外使用 matplotlib ,这里因为主要介绍算法思路, matplotlib 的使用这里不做介绍。

    是的,我们可以明显的发现,两张图片的直方图是近似重合的。所以利用直方图判断两张图片的是否相似的方法就是,计算其直方图的重合程度即可。

    计算方法如下:

    其中gi和si是分别指两条曲线的第i个点。

    最后计算得出的结果就是就是其相似程度。

    不过,这种方法有一个明显的弱点,就是他是按照颜色的全局分布来看的,无法描述颜色的局部分布和色彩所处的位置。

    也就是假如一张图片以蓝色为主,内容是一片蓝天,而另外一张图片也是蓝色为主,但是内容却是妹子穿了蓝色裙子,那么这个算法也很可能认为这两张图片的相似的。

    缓解这个弱点有一个方法就是利用 Image 的 crop 方法把图片等分,然后再分别计算其相似度,最后综合考虑。

    图像指纹与汉明距离

    在介绍下面其他判别相似度的方法前,先补充一些概念。第一个就是 图像指纹

    图像指纹和人的指纹一样,是身份的象征,而图像指纹简单点来讲, 就是将图像按照一定的哈希算法,经过运算后得出的一组二进制数字。

    说到这里,就可以顺带引出 汉明距离 的概念了。

    假如一组二进制数据为 101 ,另外一组为 111 ,那么显然把第一组的第二位数据 0 改成 1 就可以变成第二组数据 111 ,所以两组数据的汉明距离就为 1

    简单点说,汉明距离就是 一组二进制数据变成另一组数据所需的步骤数 ,显然,这个数值可以 衡量两张图片的差异 ,汉明距离越小,则代表相似度越高。汉明距离为0,即代表两张图片完全一样。

    如何计算得到汉明距离,请看下面三种哈希算法

    平均哈希法(aHash)

    此算法是基于比较灰度图每个像素与平均值来实现的

    一般步骤

    • 1.缩放图片,可利用 Image 对象的 resize(size) 改变,一般大小为8*8,64个像素值。

    • 2.转化为灰度图转灰度图的算法。

      • 1.浮点算法:Gray=Rx0.3+Gx0.59+Bx0.11

      • 2.整数方法:Gray=(Rx30+Gx59+Bx11)/100

      • 3.移位方法:Gray =(Rx76+Gx151+Bx28)>>8;

      • 4.平均值法:Gray=(R+G+B)/3;

      • 5.仅取绿色:Gray=G;

    在 python 中,可用 Image 的对象的方法 convert('L') 直接转换为灰度图

    • 3.计算平均值:计算进行灰度处理后图片的所有像素点的平均值。

    • 4.比较像素灰度值:遍历灰度图片每一个像素,如果大于平均值记录为1,否则为0.

    • 5.得到信息指纹:组合64个bit位,顺序随意保持一致性。

    最后比对两张图片的指纹,获得汉明距离即可。

    感知哈希算法(pHash)

    平均哈希算法过于严格,不够精确,更适合搜索缩略图,为了获得更精确的结果可以选择感知哈希算法,它采用的是DCT(离散余弦变换)来降低频率的方法

    一般步骤:

    • 缩小图片: 32 * 32 是一个较好的大小,这样方便DCT计算

    • 转化为灰度图:把缩放后的图片转化为256阶的灰度图。(具体算法见平均哈希算法步骤)

    • 计算DCT:DCT把图片分离成分率的集合

    • 缩小DCT:DCT计算后的矩阵是 32 * 32 ,保留左上角的 8 * 8 ,这些代表的图片的最低频率

    • 计算平均值:计算缩小DCT后的所有像素点的平均值。

    • 进一步减小DCT:大于平均值记录为1,反之记录为0.

    • 得到信息指纹:组合64个信息位,顺序随意保持一致性。

    最后比对两张图片的指纹,获得汉明距离即可。

    这里给出别人的DCT的介绍和计算方法(离散余弦变换的方法)

    dHash算法

    相比pHash,dHash的速度要快的多,相比aHash,dHash在效率几乎相同的情况下的效果要更好,它是基于渐变实现的。

    步骤:

    • 缩小图片:收缩到9*8的大小,一遍它有72的像素点

    • 转化为灰度图:把缩放后的图片转化为256阶的灰度图。(具体算法见平均哈希算法步骤)

    • 计算差异值:dHash算法工作在相邻像素之间,这样每行9个像素之间产生了8个不同的差异,一共8行,则产生了64个差异值

    • 获得指纹:如果左边的像素比右边的更亮,则记录为1,否则为0.最后比对两张图片的指纹,获得汉明距离即可。

    总结

    这几种算法是识别相似图像的基础,显然,有时两图中的人相似比整体的颜色相似更重要,所以我们有时需要进行人脸识别,然后在脸部区进行局部哈希,或者进行其他的预处理再进行哈希,这里涉及其他知识本文不作介绍。

    下一次将讲述利用opencv和以训练好的模型来进行人脸识别。

    本文算法的实现在下面,点一下下面的连接就好

    前言

    和网上各种首先你要有一个女朋友的系列一样,想进行人脸判断,首先要有脸
    只要能靠确定人脸的位置,那么进行两张人脸是否相似的操作便迎刃而解了。

    所以本篇文章着重讲述如何利用openCV定位人脸。

    上一篇文章的地址:

    利用python进行识别相似图片(一)

    安装openCV

    opencv官网

    在进行下一步操作时,我们需要安装openCV,本来安装openCV的步骤跟平常安装其他模块一样,而然由于python的历史原因(用过都懂……),弄得一点都不友好。

    先说一下,python2.7的用户,可以直接在openCV的官网上直接下载,然后在openCV的build\python
    的目录下,根据自己的情况,选择x86,x64下的cv2.pyd放到你python的安装目录的
    \Lib\site-packages\下。

    至于python3.4的用户,即有点特别。你可以在StackOverFlow找到这样
    这样的答案,但我们不要这么麻烦。

    进入这个网站,下载openCV相关whl文件,例如
    opencv_python-3.1.0-cp35-none-win_amd64.whl

    然后再对应目录下使用pip install opencv_python-3.1.0-cp35-none-win_amd64.whl命令即可

    安装完成后,可以在python的命令行下测试。

    import cv2

    如果没有报错的话,恭喜你安装成功。

    不过无论是哪个版本的用户,在python上使用openCV都需要先安装numpy这个模块。

    numpy

    人脸识别的原理

    opencv的人脸识别是基于了haar特征,关于什么叫haar特征,足以开另外一篇文章说明了,碍于篇幅,这里不做介绍。
    opencv提供已经训练好的数据写成了xml文件,放在了opencv\sources\data\haarcascades的目录下。

    如果只是安装了opencv_python-3.1.0-cp35-none-win_amd64.whl的,可以在我的github上,下载cvdata里面的内容
    ,地址会在文章底部给出。

    除了人脸识别的数据外,还有人眼,上半身,下半身……等人体特征的数据,观察xml文件的命名,不难见名知义。

    接下来会介绍如何利用这个已经训练好的数据,如果仍对haar模型感兴趣,可以参考以下地址。

    zouxy09的专栏

    如何使用训练好的数据

    先讲关于openCV基本的一些操作。全部具体代码,请查看我的github。

    读入一张图片

    cv2.imread(path)

    如果你用type()把其返回值的类型是numpy.ndarray

    而同样,numpy.asarray(Image)返回的亦是numpy.ndarray对象,为什么强调这两点?

    1. cv2.imread(path)不能读取中文路径,若路径中含有中文字符,其会返回None

    2. 在后面的操作中,包括是切割图片(人脸部分),再进行局部哈希,比较相似度,
      等等都是用Image对象进行操作,如果再用Image.open()读入图片未免显得麻烦。

    所以干脆统一用Image.open()打开图片,再用numpy.asarray(Image)转化即可。

    需要注意有一个不同的地方是虽然其返回的也是三维数组,但在第三维,即某个坐标下的RGB值,两个矩阵的顺序是反的,但只要另外编写一个小函数将其反转即可。

    载入xml数据

    face_cascade = cv2.CascadeClassifier(xml_path)

    将图片灰度化

     if img.ndim == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
     else:
        gray = img 
    
    # 如果img维度为3,说明不是灰度图,先转化为灰度图gray,如果不为3,也就是2,原图就是灰度图

    img是之前读入的三维数组,虽然灰度图可以用Image对象的convert('L')完成,但由于不确定
    opencv的处理方法是否和该方法一样,所以还是用opencv自己的方法进行处理比较好。

    获取人脸坐标

    
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=3, 
    minSize=(10,10),flags=cv2.CASCADE_SCALE_IMAGE)
    
    • scale_factor:被检测对象的尺度变化。尺度越大,越容易漏掉检测的对象,但检测速度加快;尺度越小,检测越细致准确,但检测速度变慢。

    • min_neighbors:数值越大,检测到对象的条件越苛刻;反之检测到对象的条件越宽松;

    • minSize:检测对象的大小

    该方法返回的是一个列表,每个列表元素是长度为四的元组,分别脸部的左上角的x,y值,脸部区域的宽度和高度。

    下一步操作

    通过上述的方法,我们就已经获取到人脸的位置,下一步你可以通过ImageDraw`对象进行绘图,框出人脸的位置。

    同样,你也可以使用Imagecrop方法把人脸部分提取出来,然后进行局部哈希,
    通过上一篇文章提及的算法,比较两者的相似度。

    两种操作分别在我的github中实现了,请参考我的github中face1.py,和face2.py两个python文件。

    写一只具有识别能力的图片爬虫

    在上一篇文章中,我说了会应用这些算法做成以只具有识别能力的图片爬虫,然现在我也确实是在做但考虑到作为核心的图片识别和人脸识别的部分我已经写成文章分享出来,其余部分就是想写其他爬虫一样而已,所以我决定看看这两篇文章的反响后再决定是否继续该系列,把图片爬虫的制作过程和大家分享一下。

    总结

    鉴于个人实力有限,本文未能详细说明人脸识别的原理,但总结了如何利用已经训练好的数据进行人脸识别,希望能帮到有需要的朋友。

    如有不足之处,欢迎提出。

    本文涉及内容的详细代码在下面的github地址。

    我的github仓库


    展开全文
  • 利用python进行识别相似图片(二)

    千次阅读 2016-05-04 12:53:55
    前言 和网上各种首先你要有一个女朋友的系列一样,想进行人脸判断,首先要有脸, ...利用python进行识别相似图片(一) 安装openCV opencv官网 在进行下一步操作时,我们需要安装openCV,本来安

    前言

    和网上各种首先你要有一个女朋友的系列一样,想进行人脸判断,首先要有脸
    只要能靠确定人脸的位置,那么进行两张人脸是否相似的操作便迎刃而解了。

    所以本篇文章着重讲述如何利用openCV定位人脸。

    上一篇文章的地址:

    利用python进行识别相似图片(一)

    安装openCV

    opencv官网

    在进行下一步操作时,我们需要安装openCV,本来安装openCV的步骤跟平常安装其他模块一样,而然
    由于python的历史原因(用过都懂……),弄得一点都不友好。

    先说一下,python2.7的用户,可以直接在openCV的官网上直接下载,然后在openCV的build\python
    的目录下,根据自己的情况,选择x86,x64下的cv2.pyd放到你python的安装目录的
    \Lib\site-packages\下。

    至于python3.4的用户,即有点特别。你可以在StackOverFlow找到这样
    这样的答案,但我们不要这么麻烦。

    进入这个网站,下载openCV相关whl文件,例如
    opencv_python-3.1.0-cp35-none-win_amd64.whl

    然后再对应目录下使用pip install opencv_python-3.1.0-cp35-none-win_amd64.whl命令即可

    安装完成后,可以在python的命令行下测试。

    import cv2

    如果没有报错的话,恭喜你安装成功。

    不过无论是哪个版本的用户,在python上使用openCV都需要先安装numpy这个模块。

    numpy

    人脸识别的原理

    opencv的人脸识别是基于了haar特征,关于什么叫haar特征,足以开另外一篇文章说明了,碍于篇幅,这里不做介绍。
    opencv提供已经训练好的数据写成了xml文件,放在了opencv\sources\data\haarcascades的目录下。

    如果只是安装了opencv_python-3.1.0-cp35-none-win_amd64.whl的,可以在我的github上,下载cvdata里面的内容
    ,地址会在文章底部给出。

    除了人脸识别的数据外,还有人眼,上半身,下半身……等人体特征的数据,观察xml文件的命名,不难见名知义。

    接下来会介绍如何利用这个已经训练好的数据,如果仍对haar模型感兴趣,可以参考以下地址。

    zouxy09的专栏

    如何使用训练好的数据

    先讲关于openCV基本的一些操作。全部具体代码,请查看我的github。

    读入一张图片

    cv2.imread(path)

    如果你用type()把其返回值的类型是numpy.ndarray

    而同样,numpy.asarray(Image)返回的亦是numpy.ndarray对象,为什么强调这两点?

    1. cv2.imread(path)不能读取中文路径,若路径中含有中文字符,其会返回None

    2. 在后面的操作中,包括是切割图片(人脸部分),再进行局部哈希,比较相似度,
      等等都是用Image对象进行操作,如果再用Image.open()读入图片未免显得麻烦。

    所以干脆统一用Image.open()打开图片,再用numpy.asarray(Image)转化即可。

    需要注意有一个不同的地方是虽然其返回的也是三维数组,但在第三维,即某个坐标下的RGB值,两个矩阵的顺序是反的,但只要另外编写一个小函数将其反转即可。

    载入xml数据

    face_cascade = cv2.CascadeClassifier(xml_path)

    将图片灰度化

     if img.ndim == 3:
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
     else:
        gray = img 
    
    # 如果img维度为3,说明不是灰度图,先转化为灰度图gray,如果不为3,也就是2,原图就是灰度图

    img是之前读入的三维数组,虽然灰度图可以用Image对象的convert('L')完成,但由于不确定
    opencv的处理方法是否和该方法一样,所以还是用opencv自己的方法进行处理比较好。

    获取人脸坐标

    
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=3, 
    minSize=(10,10),flags=cv2.CASCADE_SCALE_IMAGE)
    
    • scale_factor:被检测对象的尺度变化。尺度越大,越容易漏掉检测的对象,但检测速度加快;尺度越小,检测越细致准确,但检测速度变慢。

    • min_neighbors:数值越大,检测到对象的条件越苛刻;反之检测到对象的条件越宽松;

    • minSize:检测对象的大小

    该方法返回的是一个列表,每个列表元素是长度为四的元组,分别脸部的左上角的x,y值,脸部区域的宽度和高度。

    下一步操作

    通过上述的方法,我们就已经获取到人脸的位置,下一步你可以通过ImageDraw`对象进行绘图,框出人脸的位置。

    同样,你也可以使用Imagecrop方法把人脸部分提取出来,然后进行局部哈希,
    通过上一篇文章提及的算法,比较两者的相似度。

    两种操作分别在我的github中实现了,请参考我的github中face1.py,和face2.py两个python文件。

    写一只具有识别能力的图片爬虫

    在上一篇文章中,我说了会应用这些算法做成以只具有识别能力的图片爬虫,然现在我也确实是在做
    但考虑到作为核心的图片识别和人脸识别的部分我已经写成文章分享出来,其余部分就是想写其他爬虫一样而已,所以我决定看看这两篇文章的反响后再决定是否继续该系列,把图片爬虫的制作过程和大家分享一下。

    总结

    鉴于个人实力有限,本文未能详细说明人脸识别的原理,
    但总结了如何利用已经训练好的数据进行人脸识别,希望能帮到有需要的朋友。

    如有不足之处,欢迎提出。

    本文涉及内容的详细代码在下面的github地址。

    我的github仓库

    欢迎star,也欢迎给意见

    本文参考文章

    wphh的博客


    from: https://segmentfault.com/a/1190000004500523?_ea=630748

    展开全文
  • 利用python进行识别相似图片(一)

    万次阅读 2016-05-04 12:52:59
    在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系。 当然了,图像识别这个话题作为计算机科学的一个分支,不可能就在本文简单几句就说清...

    文章简介

    在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系。
    当然了,图像识别这个话题作为计算机科学的一个分支,不可能就在本文简单几句就说清,所以本文只作基本算法的科普向

    如有错误,请多包涵和多多指教。

    参考的文章和图片来源会在底部一一列出。

    以及本篇文章所用的代码都会在底下给出github地址。

    安装相关库

    python用作图像处理的相关库主要有openCV(C++编写,提供了python语言的接口),PIL,但由于PIL很早就停了,所以不支持python3.x,所以建议使用基于PIL的pillow,本文也是在python3.4和pillow的环境下进行实验。

    pillow下载地址
    PIL的下载地址
    openCV的官网

    至于opencv,在做人脸识别的时候会用到,但本文不会涉及到,在本专栏的后续中会谈及openCV的人脸识别和基于此的python图片爬虫,有兴趣的朋友可以关注本专栏。

    相关背景

    要识别两张相似图像,我们从感性上来谈是怎么样的一个过程?首先我们会区分这两张相片的类型,例如是风景照,还是人物照。风景照中,是沙漠还是海洋,人物照中,两个人是不是都是国字脸,还是瓜子脸(还是倒瓜子脸……哈哈……)。

    那么从机器的角度来说也是这样的,先识别图像的特征,然后再相比。

    很显然,在没有经过训练的计算机(即建立模型),那么计算机很难区分什么是海洋,什么是沙漠。但是计算机很容易识别到图像的像素值。

    因此,在图像识别中,颜色特征是最为常用的。(其余常用的特征还有纹理特征形状特征空间关系特征等)

    其中又分为

    • 直方图

    • 颜色集

    • 颜色矩

    • 聚合向量

    • 相关图

    直方图计算法

    这里先用直方图进行简单讲述。

    先借用一下恋花蝶的图片,

    从肉眼来看,这两张图片大概也有八成是相似的了。

    在python中可以依靠Image对象的histogram()方法获取其直方图数据,但这个方法返回的结果是一个列表,如果想得到下图可视化数据,需要另外使用 matplotlib,这里因为主要介绍算法思路,matplotlib的使用这里不做介绍。

    是的,我们可以明显的发现,两张图片的直方图是近似重合的。所以利用直方图判断两张图片的是否相似的方法就是,计算其直方图的重合程度即可。

    计算方法如下:

    其中gi和si是分别指两条曲线的第i个点。

    最后计算得出的结果就是就是其相似程度。

    不过,这种方法有一个明显的弱点,就是他是按照颜色的全局分布来看的,无法描述颜色的局部分布和色彩所处的位置。

    也就是假如一张图片以蓝色为主,内容是一片蓝天,而另外一张图片也是蓝色为主,但是内容却是妹子穿了蓝色裙子,那么这个算法也很可能认为这两张图片的相似的。

    缓解这个弱点有一个方法就是利用Imagecrop方法把图片等分,然后再分别计算其相似度,最后综合考虑。

    图像指纹与汉明距离

    在介绍下面其他判别相似度的方法前,先补充一些概念。第一个就是图像指纹

    图像指纹和人的指纹一样,是身份的象征,而图像指纹简单点来讲,就是将图像按照一定的哈希算法,经过运算后得出的一组二进制数字。

    说到这里,就可以顺带引出汉明距离的概念了。

    假如一组二进制数据为101,另外一组为111,那么显然把第一组的第二位数据0改成1就可以变成第二组数据111,所以两组数据的汉明距离就为1

    简单点说,汉明距离就是一组二进制数据变成另一组数据所需的步骤数,显然,这个数值可以衡量两张图片的差异,汉明距离越小,则代表相似度越高。汉明距离为0,即代表两张图片完全一样。

    如何计算得到汉明距离,请看下面三种哈希算法

    平均哈希法(aHash)

    此算法是基于比较灰度图每个像素与平均值来实现的

    一般步骤

    • 1.缩放图片,可利用Image对象的resize(size)改变,一般大小为8*8,64个像素值。

    • 2.转化为灰度图
      转灰度图的算法。

      • 1.浮点算法:Gray=Rx0.3+Gx0.59+Bx0.11

      • 2.整数方法:Gray=(Rx30+Gx59+Bx11)/100

      • 3.移位方法:Gray =(Rx76+Gx151+Bx28)>>8;

      • 4.平均值法:Gray=(R+G+B)/3;

      • 5.仅取绿色:Gray=G;

    python中,可用Image的对象的方法convert('L')直接转换为灰度图

    • 3.计算平均值:计算进行灰度处理后图片的所有像素点的平均值。

    • 4.比较像素灰度值:遍历灰度图片每一个像素,如果大于平均值记录为1,否则为0.

    • 5.得到信息指纹:组合64个bit位,顺序随意保持一致性。

    最后比对两张图片的指纹,获得汉明距离即可。

    感知哈希算法(pHash)

    平均哈希算法过于严格,不够精确,更适合搜索缩略图,为了获得更精确的结果可以选择感知哈希算法,它采用的是DCT(离散余弦变换)来降低频率的方法

    一般步骤:

    • 缩小图片:32 * 32是一个较好的大小,这样方便DCT计算

    • 转化为灰度图:把缩放后的图片转化为256阶的灰度图。(具体算法见平均哈希算法步骤)

    • 计算DCT:DCT把图片分离成分率的集合

    • 缩小DCT:DCT计算后的矩阵是32 * 32,保留左上角的8 * 8,这些代表的图片的最低频率

    • 计算平均值:计算缩小DCT后的所有像素点的平均值。

    • 进一步减小DCT:大于平均值记录为1,反之记录为0.

    • 得到信息指纹:组合64个信息位,顺序随意保持一致性。

    最后比对两张图片的指纹,获得汉明距离即可。

    这里给出别人的DCT的介绍和计算方法(离散余弦变换的方法)

    DCT的维基百科
    luoweifu的博客

    dHash算法

    相比pHash,dHash的速度要快的多,相比aHash,dHash在效率几乎相同的情况下的效果要更好,它是基于渐变实现的。

    步骤:

    • 缩小图片:收缩到9*8的大小,以便它有72的像素点

    • 转化为灰度图:把缩放后的图片转化为256阶的灰度图。(具体算法见平均哈希算法步骤)

    • 计算差异值:dHash算法工作在相邻像素之间,这样每行9个像素之间产生了8个不同的差异,一共8行,则产生了64个差异值

    • 获得指纹:如果左边的像素比右边的更亮,则记录为1,否则为0.
      最后比对两张图片的指纹,获得汉明距离即可。

    总结

    这几种算法是识别相似图像的基础,显然,有时两图中的人相似比整体的颜色相似更重要,所以我们有时需要进行人脸识别,
    然后在脸部区进行局部哈希,或者进行其他的预处理再进行哈希,这里涉及其他知识本文不作介绍。

    下一次将讲述利用opencv和以训练好的模型来进行人脸识别。

    本文算法的实现在下面,点一下下面的连接就好

    我的github仓库

    各位亲,走过路过给一个star鼓励一下呗,当然也欢迎提意见。

    本文参考文章和图片来源

    wbj0110的文章
    赖勇浩的文章



    from: https://segmentfault.com/a/1190000004467183

    展开全文
  • python的功能实在太强大,这篇文章主要介绍了Python+Opencv识别两张相似图片的相关资料,文中利用Opencv库进行了更简洁化的实现,感兴趣的小伙伴们可以参考一下
  • Python+Opencv进行识别相似图片

    千次阅读 2017-05-22 16:55:47
    在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系。 当然了,图像识别这个话题作为计算机科学的一个分支,不可能就在本文简单几句就说...

    转于:http://blog.csdn.net/feimengjuan/article/details/51279629

    在网上看到python做图像识别的相关文章后,真心感觉python的功能实在太强大,因此将这些文章总结一下,建立一下自己的知识体系。

    当然了,图像识别这个话题作为计算机科学的一个分支,不可能就在本文简单几句就说清,所以本文只作基本算法的科普向

    看到一篇博客是介绍这个,但他用的是PIL中的Image实现的,感觉比较麻烦,于是利用OpenCV库进行了更简洁化的实现。

    相关背景

    要识别两张相似图像,我们从感性上来谈是怎么样的一个过程?首先我们会区分这两张相片的类型,例如是风景照,还是人物照。风景照中,是沙漠还是海洋,人物照中,两个人是不是都是国字脸,还是瓜子脸(还是倒瓜子脸……哈哈……)。

    那么从机器的角度来说也是这样的,先识别图像的特征,然后再相比。

    很显然,在没有经过训练的计算机(即建立模型),那么计算机很难区分什么是海洋,什么是沙漠。但是计算机很容易识别到图像的像素值。

    因此,在图像识别中,颜色特征是最为常用的。(其余常用的特征还有纹理特征形状特征空间关系特征等)

    其中又分为

    • 直方图

    • 颜色集

    • 颜色矩

    • 聚合向量

    • 相关图

    直方图计算法

    这里先用直方图进行简单讲述。

    先借用一下恋花蝶的图片,



    从肉眼来看,这两张图片大概也有八成是相似的了。

    Python中利用opencv中的calcHist()方法获取其直方图数据,返回的结果是一个列表,使用matplotlib,画出了这两张图的直方图数据图

    如下:



    是的,我们可以明显的发现,两张图片的直方图还是比较重合的。所以利用直方图判断两张图片的是否相似的方法就是,计算其直方图的重合程度即可。

    计算方法如下:


    其中gi和si是分别指两条曲线的第i个点。

    最后计算得出的结果就是就是其相似程度。

    不过,这种方法有一个明显的弱点,就是他是按照颜色的全局分布来看的,无法描述颜色的局部分布和色彩所处的位置。

    也就是假如一张图片以蓝色为主,内容是一片蓝天,而另外一张图片也是蓝色为主,但是内容却是妹子穿了蓝色裙子,那么这个算法也很可能认为这两张图片的相似的。

    缓解这个弱点有一个方法就是利用Imagecrop方法把图片等分,然后再分别计算其相似度,最后综合考虑。

    图像指纹与汉明距离

    在介绍下面其他判别相似度的方法前,先补充一些概念。第一个就是图像指纹

    图像指纹和人的指纹一样,是身份的象征,而图像指纹简单点来讲,就是将图像按照一定的哈希算法,经过运算后得出的一组二进制数字。

    说到这里,就可以顺带引出汉明距离的概念了。

    假如一组二进制数据为101,另外一组为111,那么显然把第一组的第二位数据0改成1就可以变成第二组数据111,所以两组数据的汉明距离就为1

    简单点说,汉明距离就是一组二进制数据变成另一组数据所需的步骤数,显然,这个数值可以衡量两张图片的差异,汉明距离越小,则代表相似度越高。汉明距离为0,即代表两张图片完全一样。

    如何计算得到汉明距离,请看下面三种哈希算法

    平均哈希法(aHash)

    此算法是基于比较灰度图每个像素与平均值来实现的

    一般步骤

    • 1.缩放图片,一般大小为8*8,64个像素值。

    • 2.转化为灰度图

    • 3.计算平均值:计算进行灰度处理后图片的所有像素点的平均值,直接用numpy中的mean()计算即可。

    • 4.比较像素灰度值:遍历灰度图片每一个像素,如果大于平均值记录为1,否则为0.

    • 5.得到信息指纹:组合64个bit位,顺序随意保持一致性。

    最后比对两张图片的指纹,获得汉明距离即可。

    感知哈希算法(pHash)

    平均哈希算法过于严格,不够精确,更适合搜索缩略图,为了获得更精确的结果可以选择感知哈希算法,它采用的是DCT(离散余弦变换)来降低频率的方法

    一般步骤:

    • 缩小图片:32 * 32是一个较好的大小,这样方便DCT计算

    • 转化为灰度图

    • 计算DCT:利用Opencv中提供的dct()方法,注意输入的图像必须是32位浮点型,所以先利用numpy中的float32进行转换

    • 缩小DCT:DCT计算后的矩阵是32 * 32,保留左上角的8 * 8,这些代表的图片的最低频率

    • 计算平均值:计算缩小DCT后的所有像素点的平均值。

    • 进一步减小DCT:大于平均值记录为1,反之记录为0.

    • 得到信息指纹:组合64个信息位,顺序随意保持一致性。

    最后比对两张图片的指纹,获得汉明距离即可。

    dHash算法

    相比pHash,dHash的速度要快的多,相比aHash,dHash在效率几乎相同的情况下的效果要更好,它是基于渐变实现的。

    步骤:

    • 缩小图片:收缩到9*8的大小,以便它有72的像素点

    • 转化为灰度图

    • 计算差异值:dHash算法工作在相邻像素之间,这样每行9个像素之间产生了8个不同的差异,一共8行,则产生了64个差异值

    • 获得指纹:如果左边的像素比右边的更亮,则记录为1,否则为0.
      最后比对两张图片的指纹,获得汉明距离即可。

    整个的代码实现如下:

    [python]  view plain  copy
    1. # -*- coding: utf-8 -*-  
    2. #feimengjuan  
    3. # 利用python实现多种方法来实现图像识别  
    4.   
    5. import cv2  
    6. import numpy as np  
    7. from matplotlib import pyplot as plt  
    8.   
    9. # 最简单的以灰度直方图作为相似比较的实现  
    10. def classify_gray_hist(image1,image2,size = (256,256)):  
    11.     # 先计算直方图  
    12.     # 几个参数必须用方括号括起来  
    13.     # 这里直接用灰度图计算直方图,所以是使用第一个通道,  
    14.     # 也可以进行通道分离后,得到多个通道的直方图  
    15.     # bins 取为16  
    16.     image1 = cv2.resize(image1,size)  
    17.     image2 = cv2.resize(image2,size)  
    18.     hist1 = cv2.calcHist([image1],[0],None,[256],[0.0,255.0])  
    19.     hist2 = cv2.calcHist([image2],[0],None,[256],[0.0,255.0])  
    20.     # 可以比较下直方图  
    21.     plt.plot(range(256),hist1,'r')  
    22.     plt.plot(range(256),hist2,'b')  
    23.     plt.show()  
    24.     # 计算直方图的重合度  
    25.     degree = 0  
    26.     for i in range(len(hist1)):  
    27.         if hist1[i] != hist2[i]:  
    28.             degree = degree + (1 - abs(hist1[i]-hist2[i])/max(hist1[i],hist2[i]))  
    29.         else:  
    30.             degree = degree + 1  
    31.     degree = degree/len(hist1)  
    32.     return degree  
    33.   
    34. # 计算单通道的直方图的相似值  
    35. def calculate(image1,image2):  
    36.     hist1 = cv2.calcHist([image1],[0],None,[256],[0.0,255.0])  
    37.     hist2 = cv2.calcHist([image2],[0],None,[256],[0.0,255.0])  
    38.      # 计算直方图的重合度  
    39.     degree = 0  
    40.     for i in range(len(hist1)):  
    41.         if hist1[i] != hist2[i]:  
    42.             degree = degree + (1 - abs(hist1[i]-hist2[i])/max(hist1[i],hist2[i]))  
    43.         else:  
    44.             degree = degree + 1  
    45.     degree = degree/len(hist1)  
    46.     return degree  
    47.   
    48. # 通过得到每个通道的直方图来计算相似度  
    49. def classify_hist_with_split(image1,image2,size = (256,256)):  
    50.     # 将图像resize后,分离为三个通道,再计算每个通道的相似值  
    51.     image1 = cv2.resize(image1,size)  
    52.     image2 = cv2.resize(image2,size)  
    53.     sub_image1 = cv2.split(image1)  
    54.     sub_image2 = cv2.split(image2)  
    55.     sub_data = 0  
    56.     for im1,im2 in zip(sub_image1,sub_image2):  
    57.         sub_data += calculate(im1,im2)  
    58.     sub_data = sub_data/3  
    59.     return sub_data  
    60.   
    61. # 平均哈希算法计算  
    62. def classify_aHash(image1,image2):  
    63.     image1 = cv2.resize(image1,(8,8))  
    64.     image2 = cv2.resize(image2,(8,8))  
    65.     gray1 = cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY)  
    66.     gray2 = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY)  
    67.     hash1 = getHash(gray1)  
    68.     hash2 = getHash(gray2)  
    69.     return Hamming_distance(hash1,hash2)  
    70.   
    71. def classify_pHash(image1,image2):  
    72.     image1 = cv2.resize(image1,(32,32))  
    73.     image2 = cv2.resize(image2,(32,32))  
    74.     gray1 = cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY)  
    75.     gray2 = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY)  
    76.     # 将灰度图转为浮点型,再进行dct变换  
    77.     dct1 = cv2.dct(np.float32(gray1))  
    78.     dct2 = cv2.dct(np.float32(gray2))  
    79.     # 取左上角的8*8,这些代表图片的最低频率  
    80.     # 这个操作等价于c++中利用opencv实现的掩码操作  
    81.     # 在python中进行掩码操作,可以直接这样取出图像矩阵的某一部分  
    82.     dct1_roi = dct1[0:8,0:8]  
    83.     dct2_roi = dct2[0:8,0:8]  
    84.     hash1 = getHash(dct1_roi)  
    85.     hash2 = getHash(dct2_roi)  
    86.     return Hamming_distance(hash1,hash2)  
    87.   
    88. # 输入灰度图,返回hash  
    89. def getHash(image):  
    90.     avreage = np.mean(image)  
    91.     hash = []  
    92.     for i in range(image.shape[0]):  
    93.         for j in range(image.shape[1]):  
    94.             if image[i,j] > avreage:  
    95.                 hash.append(1)  
    96.             else:  
    97.                 hash.append(0)  
    98.     return hash  
    99.   
    100.   
    101. # 计算汉明距离  
    102. def Hamming_distance(hash1,hash2):  
    103.     num = 0  
    104.     for index in range(len(hash1)):  
    105.         if hash1[index] != hash2[index]:  
    106.             num += 1  
    107.     return num  
    108.   
    109.   
    110. if __name__ == '__main__':  
    111.     img1 = cv2.imread('10.jpg')  
    112.     cv2.imshow('img1',img1)  
    113.     img2 = cv2.imread('11.jpg')  
    114.     cv2.imshow('img2',img2)  
    115.     degree = classify_gray_hist(img1,img2)  
    116.     #degree = classify_hist_with_split(img1,img2)  
    117.     #degree = classify_aHash(img1,img2)  
    118.     #degree = classify_pHash(img1,img2)  
    119.     print degree  
    120.     cv2.waitKey(0)  
    展开全文
  • python寻找一个文件夹下与目标图片相似图片,并且按相似程度给该文件夹下图片重命名,相似度最高用0.jpg或者_0.jpg重命名 效果: 目标图片
  • Python+Opencv识别两张相似图片.pdf
  • python查找相似图片或重复图片

    千次阅读 2020-08-07 11:02:06
    filename)) #根据MD5值比较 for photo in allfile: md5sum = getmd5(photo) if md5sum not in md5list: md5list.append(md5sum) else: list_delete.append(photo) print('重复的照片有:',list_delete) #删除图片 for...
  • python识别图片验证码

    千次阅读 2017-07-07 10:39:29
    字符型图片验证码识别完整过程及Python实现 1 摘要 验证码是目前互联网上非常常见也是非常重要的一个事物,充当着很多系统的 防火墙 功能,但是随时OCR技术的发展,验证码暴露出来的安全问题也越来越严峻。...
  • #--coding:utf-8-- from PIL import Image import imagehash import distance funct_hash=imagehash.phash pil_im=Image.open(r"timg.jpg") stepx=64 stepy=64 print pil_im.size oneitem=[] ...d
  • Python图像识别,图片相似度计算!

    千次阅读 2019-08-29 16:23:53
    1.背景 要识别两张图片是否相似,首先我们可能会区分这两张...但是让计算机去区分这些图片分别是哪一类是很不容易的,不过计算机可以知道图像的像素值的,因此,在图像识别过程中,通过颜色特征来识别相似图片是...
  • Python 识别验证码

    千次阅读 2017-08-24 14:01:01
    本次试验将带领大家认识验证码的一些特性,并利用 Python 中的 pillow 库完成对验证码的破解。 1.2 实验知识点 本节实验中将学习和实践以下知识点: Python基本知识 PIL模块的使用 1.3 实验环境 Python2.7 P
  • Python识别验证码

    千次阅读 2019-06-20 12:02:26
    由于本文实现的功能是在内网环境完成,因此,没有代码介绍,也没有识别效果展示。 爬虫过程中难免会碰到验证码,各种各样的验证码似乎阻挡了爬虫的脚步。 为了识别机器和真实用户而诞生的爬虫 碰到验证码有两个...
  • 1.背景 要识别两张图片是否相似,首先我们可能会区分这两张...但是让计算机去区分这些图片分别是哪一类是很不容易的,不过计算机可以知道图像的像素值的,因此,在图像识别过程中,通过颜色特征来识别相似图片是...
  • python利用pytesseract识别图片验证码

    千次阅读 2019-06-25 20:47:29
    pytesseract是python的一个光学字符识别模块。可用来做图片文字识别。 2.什么是光学字符识别 光学字符识别即Optical Character Recognition,简称OCR,是指通过扫描字符,通过其形状将其翻译成电子文本的过程,...
  • 识别快递单号 这是我在CSDN 的第一篇博文,其实也就拿来记点东西而已,本来平时嫌麻烦,有什么东西都是记载QQ空间的,但QQ空间没Markdown写起代码来麻烦,于是乎转战CSDN 这次跟老师做项目,这项目大概是流水线上...
  • Python对旋转图片验证码的设别和破解 本文主要使用python + selenium来破解旋转突破的验证码;其中用到numpy和OpenCV(CV2)来进行图片拼接,转换,遮罩,识别等 旋转图片的正确位置 旋转突破最难的在于如何计算...
  • 其中用到numpy和OpenCV(CV2)来进行图片拼接,转换,遮罩,识别等 将验证码图片与所有的图片拼接的大图比较,找到旋转角度 使用cv2.getRotationMatrix2D设置选择矩阵,warpAffine进行图片旋转 getRotationMatrix...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 36,529
精华内容 14,611
关键字:

python识别相似图片

python 订阅