python Opencv计算图像相似度过程解析

这篇文章主要介绍了python Opencv计算图像相似度过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

一、相关概念

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

而没有学习训练过的机器就没办法了。

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

  • 直方图
  • 颜色集
  • 颜色矩
  • 聚合向量
  • 相关图

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 平均哈希

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

一般步骤:

  • 缩放图片,一般大小为8*8,64个像素值。
  • 转化为灰度图
  • 计算平均值:计算进行灰度处理后图片的所有像素点的平均值,直接用numpy中的mean()计算即可。
  • 比较像素灰度值:遍历灰度图片每一个像素,如果大于平均值记录为1,否则为0.
  • 得到信息指纹:组合64个bit位,顺序随意保持一致性。
  • 最后比对两张图片的指纹,获得汉明距离即可。
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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Python OpenCV图像指定区域裁剪的实现

    在工作中.在做数据集时,需要对图片进行处理,照相的图片我们只需要特定的部分,所以就想到裁剪一种所需的部分.当然若是图片有规律可循则使用opencv对其进行膨胀腐蚀等操作.这样更精准一些. 一.指定图像位置的裁剪处理 import os import cv2 # 遍历指定目录,显示目录下的所有文件名 def CropImage4File(filepath,destpath): pathDir = os.listdir(filepath) # 列出文件路径中的所有路径或文件 for allDir i

  • python opencv 图像拼接的实现方法

    初级的图像拼接为将两幅图像简单的粘贴在一起,仅仅是图像几何空间的转移与合成,与图像内容无关.高级图像拼接也叫作基于特征匹配的图像拼接,拼接时消去两幅图像相同的部分,实现拼接合成全景图. 具有相同尺寸的图A和图B含有相同的部分与不同的部分,如图所示:             用基于特征的图像拼接实现后: 设图像高为h,相同部分的宽度为wx 拼接后图像的宽w=wA+wB-wx 因此,可以先构建一个高为h,宽为W*2的空白图像,将左图像向右平移wx,右图像粘贴在右侧.则右图像刚好覆盖左图像中的相同部分

  • python-opencv获取二值图像轮廓及中心点坐标的代码

    python-opencv获取二值图像轮廓及中心点坐标代码: groundtruth = cv2.imread(groundtruth_path)[:, :, 0] h1, w1 = groundtruth.shape contours, cnt = cv2.findContours(groundtruth.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) if len(contours) != 1:#轮廓总数 continue M = cv

  • opencv python 图像轮廓/检测轮廓/绘制轮廓的方法

    图像的轮廓检测,如计算多边形外界.形状毕竟.计算感兴趣区域等. Contours : Getting Started 轮廓 简单地解释为连接所有连续点(沿着边界)的曲线,具有相同的颜色或强度. 轮廓是形状分析和物体检测和识别的有用工具 NOTE 为获得更好的准确性,请使用二值图,在找到轮廓之前,应用阈值法或canny边缘检测 从OpenCV 3.2开始,findContours()不再修改源图像,而是将修改后的图像作为三个返回参数中的第一个返回 在OpenCV中,查找轮廓是从黑色背景中查找白色对

  • Python使用Opencv实现图像特征检测与匹配的方法

    特征检测是计算机对一张图像中最为明显的特征进行识别检测并将其勾画出来.大多数特征检测都会涉及图像的角点.边和斑点的识别.或者是物体的对称轴. 角点检测 是由Opencv的cornerHarris函数实现,其他函数参数说明如下: cv2.cornerHarris(src=gray, blockSize=9, ksize=23, k=0.04) # cornerHarris参数: # src - 数据类型为 float32 的输入图像. # blockSize - 角点检测中要考虑的领域大小. #

  • python使用opencv对图像mask处理的方法

    MASK图像掩膜处理 在图像操作中有时候会用到掩膜处理,如果使用遍历法掩膜图像ROI区域对于python来讲是很慢的,所以我们要找到一种比较好的算法来实现掩膜处理. 假设我们有一副图像: 而我们关心的区域就在这一小堆线上,想把这一堆线提取出来,我们先通过numpy生成一个mask图像: sss=np.zeros([480,640],dtype=np.uint8) sss[300:350,310:400]=255 生成一个640*480大小的一个图片,填充为0,然后在300:350,310:400

  • Opencv-Python图像透视变换cv2.warpPerspective的示例

    Opencv-Python图像透视变换cv2.warpPerspective 代码如下: # -*- coding:utf-8 -*- import cv2 import numpy as np import sys img = cv2.imread('test.jpg') # cv2.imshow("original", img) # 可选,扩展图像,保证内容不超出可视范围 img = cv2.copyMakeBorder(img, 200, 200, 200, 200, cv2.B

  • Python Opencv实现图像轮廓识别功能

    本文实例为大家分享了python opencv识别图像轮廓的具体代码,供大家参考,具体内容如下 要求:用矩形或者圆形框住图片中的云朵(不要求全部框出) 轮廓检测 Opencv-Python接口中使用cv2.findContours()函数来查找检测物体的轮廓. import cv2 img = cv2.imread('cloud.jpg') # 灰度图像 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 二值化 ret, binary = cv2.th

  • python实现图像检索的三种(直方图/OpenCV/哈希法)

    简介: 本文介绍了图像检索的三种实现方式,均用python完成,其中前两种基于直方图比较,哈希法基于像素分布. 检索方式是:提前导入图片库作为检索范围,给出待检索的图片,将其与图片库中的图片进行比较,得出所有相似度后进行排序,从而检索结果为相似度由高到低的图片.由于工程中还包含Qt界面类.触发函数等其他部分,在该文档中只给出关键函数的代码. 开发系统:MacOS 实现方式:Qt + Python 方法一:自定义的直方图比较算法 a) 基本思路 遍历图片像素点,提取R\G\B值并进行对应的计数,得

  • 用Python+OpenCV对比图像质量的几种方法

    前言 图片的本质就是大量像素在二维平面上的组合,每个像素点用数字化方式记录颜色.可以直观的想象,一张图片就是一个巨大的电子栅格,每个格子内有一盏灯泡,这个灯泡可以变换256的三次方种颜色,就像下面这张卡通像素图一样,越清晰的图片像素越密集. 这一次来看看OpenCV提供的两种图像质量对比方式(PSNR & SSIM)及其扩展, 这篇文章会涉及到一点数学公式,顺便介绍一个我用过的生成公式的最佳在线编辑工具,秒杀所有收费工具. 链接在这里, 请收好: https://www.mathcha.io/e

随机推荐