一、相关概念

1. 一般我们人区分谁是谁,给物品分类,都是通过各种特征去辨别的,比如黑长直、大白腿、樱桃唇、瓜子脸。王麻子脸上有麻子,隔壁老王和儿子很像,但是儿子下巴涨了一颗痣和他妈一模一样,让你确定这是你儿子。
还有其他物品、什么桌子带腿、镜子反光能在里面倒影出东西,各种各样的特征,我们通过学习、归纳,自然而然能够很快识别分类出新物品。
而没有学习训练过的机器就没办法了。

  1. 但是图像是一个个像素点组成的,我们就可以通过不同图像之间这些差异性就判断两个图的相似度了。其中颜色特征是最常用的,(其余常用的特征还有纹理特征、形状特征和空间关系特征等)

    其中又分为

    直方图

    颜色集

    颜色矩

    聚合向量

    相关图

    1、直方图

    在Python中利用opencv中的calcHist()方法获取其直方图数据,返回的结果是一个列表,使用matplotlib,画出了这两张图的直方图数据图
import cv2
import numpy
from matplotlib import pyplot if __name__ == '__main__':
imgobj1 = cv2.imread('pho.jpg')
imgobj2 = cv2.imread('ph1.jpg')
hist1 = cv2.calcHist([imgobj1], [0], None, [256], [0.0, 255.0])
hist2 = cv2.calcHist([imgobj2], [0], None, [256], [0.0, 255.0])
pyplot.plot(range(256), hist1, 'r')
pyplot.plot(range(256), hist2, 'b')
pyplot.show()
cv2.imshow('img1',imgobj1)
cv2.imshow('img2',imgobj2)
cv2.waitKey(0)

1.2 灰度图及作用

- 灰度图是只含有黑白颜色,和0~255亮度等级的图片。灰度图具有存储小,其亮度值就是256色调色板索引号,从整幅图像的整体和局部的色彩以及亮度等级分布特征来看,灰度图描述与彩色图的描述是一致的特点。因此很多真彩色图片的分析,第一步就是转换为灰度图,然后再进行分析。
真彩色,因为是24位,2(^8) * 2(^8)* 2(^8) = 16777216种颜色,需要调色板16777216 * 4byte字节的空间也就是64MB的调色板空间,所以真彩色是不用调色板的。
例如视频目标跟踪和识别时,第一步就是要转换为灰度图。现有的成熟分析算法多是基于灰度图像的,灰度图像综合了真彩色位图的RGB各通道的信息。

(一):单通道图,

俗称灰度图,每个像素点只能有有一个值表示颜色,它的像素值在0到255之间,0是黑色,255是白色,中间值是一些不同等级的灰色。(也有3通道的灰度图,3通道灰度图只有一个通道有值,其他两个通道的值都是零)。

(二):三通道图,每个像素点都有3个值表示 ,所以就是3通道。也有4通道的图。例如RGB图片即为三通道图片,RGB色彩模式是工业界的一种颜色标准,是通过对红(R)、绿(G)、蓝(B)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,RGB即是代表红、绿、蓝三个通道的颜色,这个标准几乎包括了人类视力所能感知的所有颜色,是目前运用最广的颜色系统之一。总之,每一个点由三个值表示。

  • 直方图判断相似度,如上图,就算重合度即可
1.3 图像指纹和汉明距离
  • 图像指纹:

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

  • 汉明距离:

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

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

1.3.1 平均哈希

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

一般步骤:

  1. 缩放图片,一般大小为8*8,64个像素值。
  2. 转化为灰度图
  3. 计算平均值:计算进行灰度处理后图片的所有像素点的平均值,直接用numpy中的mean()计算即可。
  4. 比较像素灰度值:遍历灰度图片每一个像素,如果大于平均值记录为1,否则为0.
  5. 得到信息指纹:组合64个bit位,顺序随意保持一致性。
  6. 最后比对两张图片的指纹,获得汉明距离即可。
import cv2
import numpy as np img1 = cv2.imread("/absPath.png")
img2 = cv2.imread("./x.png") #调整到8*8
img1 = cv2.resize(img1,(8,8))
img2 = cv2.resize(img2,(8,8)) #转化为灰度图
gray1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
gray2 = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY) #获取哈希
hash1 = getHash(gray1)
hash2 = getHash(gray2) ret = Hamming_distance(hash1,hash2) # 输入灰度图,返回hash
def getHash(image):
avreage = np.mean(image) #计算像素平均值
hash = []
for i in range(image.shape[0]):
for j in range(image.shape[1]):
if image[i, j] > avreage:
hash.append(1)
else:
hash.append(0)
return hash # 计算汉明距离
def Hamming_distance(hash1, hash2):
num = 0
for index in range(len(hash1)):
if hash1[index] != hash2[index]:
num += 1
return num
1.3.2 感知哈希及d哈希

感知哈希算法(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.

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

  • dHash:
#差值感知算法
def dhash(image1,image2):
image1 = cv2.resize(image1,(9,8))
image2 = cv2.resize(image2,(9,8))
gray1 = cv2.cvtColor(image1,cv2.COLOR_BGR2GRAY) #切换至灰度图
gray2 = cv2.cvtColor(image2,cv2.COLOR_BGR2GRAY)
hash1 = dhashcaulate(gray1)
hash2 = dhashcaulate(gray2)
return Hamming_distance(hash1,hash2) def dhashcaulate(gray):
hash_str = ''
for i in range(8):
for j in range(8):
if gray[i, j] > gray[i, j + 1]:
hash_str = hash_str + '1'
else:
hash_str = hash_str + '0'
return hash_str

Opencv python图像处理-图像相似度计算的更多相关文章

  1. 图像相似度计算之哈希值方法OpenCV实现

    http://blog.csdn.net/fengbingchun/article/details/42153261 图像相似度计算之哈希值方法OpenCV实现 2014-12-25 21:27 29 ...

  2. 【图像处理】OpenCV+Python图像处理入门教程(七)图像形态学操作

    图像形态学主要从图像内提取分量信息,该分量信息通常对表达图像的特征具有重要意义.例如,在车牌号码识别中,能够使用形态学计算其重要特征信息,在进行识别时,只需对这些特征信息运算即可.图像形态学在目标视觉 ...

  3. 【图像处理】OpenCV+Python图像处理入门教程(五)阈值处理

    这篇随笔介绍使用OpenCV进行图像处理的第五章 阈值处理. 5  阈值处理 阈值是指像素到达某临界值.阈值处理表示像素到达某临界值后,对该像素点进行操作和处理. 例如:设定一幅图像素阈值为200,则 ...

  4. 【图像处理】OpenCV+Python图像处理入门教程(六)图像平滑处理

    相信很多小伙伴都听过"滤波器"这个词,在通信领域,滤波器能够去除噪声信号等频率成分,然而在我们OpenCV中,"滤波"并不是对频率进行筛选去除,而是实现了图像的 ...

  5. 【图像处理】OpenCV+Python图像处理入门教程(四)几何变换

    这篇随笔介绍使用OpenCV进行图像处理的第四章 几何变换. 4  几何变换 图像的几何变换是指将一幅图像映射到另一幅图像内.有缩放.翻转.仿射变换.透视.重映射等操作. 4.1  缩放 使用cv2. ...

  6. opencv python:图像直方图 histogram

    直接用matplotlib画出直方图 def plot_demo(image): plt.hist(image.ravel(), 256, [0, 256]) # image.ravel()将图像展开 ...

  7. openCV—Python(5)—— 图像几何变换

    一.函数简单介绍 1.warpAffine-图像放射变换(平移.旋转.缩放) 函数原型:warpAffine(src, M, dsize, dst=None, flags=None, borderMo ...

  8. opencv python:图像梯度

    一阶导数与Soble算子 二阶导数与拉普拉斯算子 图像边缘: Soble算子: 二阶导数: 拉普拉斯算子: import cv2 as cv import numpy as np # 图像梯度(由x, ...

  9. opencv python:图像二值化

    import cv2 as cv import numpy as np import matplotlib.pyplot as plt # 二值图像就是将灰度图转化成黑白图,没有灰,在一个值之前为黑, ...

随机推荐

  1. Ansible13:Playbook循环语句

    目录 循环语句 简介 loop关键字说明 在循环语句中注册变量 旧循环语句 1. with_items 2. with_nested 3. with_dict 4. with_fileglob 5. ...

  2. [笔记] 二级指针(pointer to pointer)

    // 1.pointer to pointer.cpp #include "stdafx.h" #include <stdlib.h> int _tmain(int a ...

  3. docker 的Portainer和Dive

    Portainer Portainer是Docker的图形化管理工具,提供状态显示面板.应用模板快速部署.容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作).事件日志显示.容器控制台操作 ...

  4. python3 根据时间获取本月一号和月末日期

    一.概述 有一个统计报表需求,需要知道上个月的第一天和最后一天,来进行上个月的数据统计. 二.代码实现 #!/usr/bin/env python3 # coding: utf-8 import ca ...

  5. CF573E Bear and Bowling 贪心、分块、凸包

    传送门 题解搬运工++ 先证明一个贪心做法的正确性:做以下操作若干次,每一次考虑选择没有被选到答案序列中的数加入到答案序列中对答案的贡献,设第\(i\)个位置的贡献为\(V_i\),如果最大的贡献小于 ...

  6. C#子线程执行完后,调用主线程的方法

    private delegate void CheckVersionNumber_CallBack(string str);//定义一个为委托 用于 检测版本 //检测版本private void m ...

  7. PAT 1020月饼

    月饼是中国人在中秋佳节时吃的一种传统食品,不同地区有许多不同风味的月饼.现给定所有种类月饼的库存量.总售价.以及市场的最大需求量,请你计算可以获得的最大收益是多少. 注意:销售时允许取出一部分库存.样 ...

  8. spark内存管理器--MemoryManager源码解析

    MemoryManager内存管理器 内存管理器可以说是spark内核中最重要的基础模块之一,shuffle时的排序,rdd缓存,展开内存,广播变量,Task运行结果的存储等等,凡是需要使用内存的地方 ...

  9. 5.Javascript闭包得实现原理和作用

    闭包的实现原理和作用 1.闭包的概念:指有权访问另一个函数作用域中的变量的函数,一般情况就是在一个函数中包含另一个函数. 2.闭包的作用:访问函数内部变量.保持函数在环境中一直存在,不会被垃圾回收机制 ...

  10. QTGraphics-View拖拽以及鼠标指针操作

    因为QGraphicsView继承自QWidget,它也提供了像QWidget那样的拖拽功能. 另外,为了方便,Graphics View框架也为场景以及每个item提供拖拽支持.当视图接收到拖拽事件 ...