广告位联系
返回顶部
分享到

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

python 来源:互联网搜集 作者:秩名 发布时间:2019-08-08 17:04:18 人浏览
摘要

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

本篇文章介绍python实现图像检索的三种(直方图/OpenCV/哈希法)

简介:

本文介绍了图像检索的三种实现方式,均用python完成,其中前两种基于直方图比较,哈希法基于像素分布。

检索方式是:提前导入图片库作为检索范围,给出待检索的图片,将其与图片库中的图片进行比较,得出所有相似度后进行排序,从

检索结果为相似度由高到低的图片。由于工程中还包含Qt界面类、触发函数等其他部分,在该文档中只给出关键函数的代码。


开发系统:MacOS

实现方式:Qt + Python

方法一:自定义的直方图比较算法

a) 基本思路

遍历图片像素点,提取R\G\B值并进行对应的计数,得到原始直方图,但由于0-255的范围太大,因此每一个像素值的统计量均偏小,因此分别将R\G\B的256个像素值映射到0-31共32个像素值上,将像素值范围由256*3缩小到32*3。记录像素值采用的数据结构为一维数组,第1到32个值为R的像素直方图,第33到第64个值为G的像素统计,第65到96个值为B的像素统计。得到直方图后,计算待检索图的直方图和图片库中图像的直方图之间的相似性。

b) 具体实现

用到的函数:
 

  • split_Img()
  • calc_Hist(img)
  • calc_Similar(h1,h2)
  • calc_Similar_Split(h1,h2)


遍历图片的像素点以计算直方图:calc_Hist(img)

尝试了两种方式,第一种是对图像遍历时逐个调用getpixel()来获取R,G,B的值,但发现这种方式的速度太慢。第二种采用的是内存读取,利用load()函数一次性读取图像的像素值,然后对像素值进行遍历,该方法的速度比逐个提取更快。
 

 
#统计直方图,用load()载入图片的像素pix,再分别读取每个像素点的R\G\B值进行统计(分别为0-255)
#将256个颜色值的统计情况投影到32个,返回R\G\B投影后的统计值数组,共32*3=96个元素
def calc_Hist(img):
  '''
  #120张图片,4.43s
  w,h = img.size
  pix = img.load() #载入图片,pix存的是像素
  calcR = [0 for i in range(0,32)]
  calcG = [0 for i in range(0,32)]
  calcB = [0 for i in range(0,32)]
  for i in range(0,w):
    for j in range(0,h):
      (r,g,b) = pix[i,j]
      #print (r,g,b)
      calcR[r/8] += 1
      calcG[g/8] += 1
      calcB[b/8] += 1
  calcG.extend(calcB)
  calcR.extend(calcG)

  return calcR
  '''
  #120张图,3.49s

  w,h = img.size
  pix = img.load() #载入图片,pix存的是像素
  calcR = [0 for i in range(0,256)]
  calcG = [0 for i in range(0,256)]
  calcB = [0 for i in range(0,256)]
  for i in range(0,w):
    for j in range(0,h):
      (r,g,b) = pix[i,j]
      #print (r,g,b)
      calcR[r] += 1
      calcG[g] += 1
      calcB[b] += 1
  calcG.extend(calcB)
  calcR.extend(calcG) #256*3

  #calc存放最终结果,32*3
  calc = [0 for i in range(0,96)]
  step = 0 #calc的下标,0~95
  start = 0 #每次统计的开始位置
  while step < 96:
    for i in range(start,start+8): #8个值为1组,统计值相加,eg:色彩值为0~7的统计值全部转换为色彩值为0的统计值
      calc[step] += calcR[i]
    start = start+8
    step += 1
  #print calc
  return calc
 

直方图比较 calc_Similar(h1,h2)

采用的公式是: 


 

其中N为颜色级数,Sim越靠近1则两幅图像的相似度越高。

c) 问题和改进

简单实现直方图比较后,检索的结果并不好,和预期相比误差较大。分析原因,直方图比较主要依靠整幅图像的色彩统计来进行比较,而对像素的位置并没有很好的记录,因此会造成误判。

同时增加calc_Similar_Split(h1,h2)函数,加入分块比较的部分,计算方法是:对每个小块调用calc_Similar(h1,h2),累加计算结果,最后除以16取平均值。

测试发现效果显著提升,基于颜色相似的同时保留了形状信息。

函数如下:
 

 
#该函数用于统一图片大小为256*256,并且分割为16个块,返回值是16个局部图像句柄的数组
def split_Img(img, size = (64,64)):
  img = img.resize((256,256)).convert('RGB')
  w,h = img.size
  sw,sh = size
  return [img.crop((i,j,i+sw,j+sh)).copy() for i in xrange(0,w,sw) for j in xrange(0,h,sh)]

#计算两个直方图之间的相似度,h1和h2为直方图,zip表示同步遍历
def calc_Similar(h1,h2):
  return sum(1 - (0 if g==s else float(abs(g-s))/max(g,s)) for g,s in zip(h1,h2)) / len(h1)
 

方法二:openCV库的直方图比较算法实现

openCV开源库已经集成了直方图提取、直方图均衡化以及直方图比较的功能,调用方便。为了进一步了解直方图比较的各类实现方法,利用openCV重新进行了实验。

a) 基本思路

对图片库中每个图片提取直方图并均衡化,然后调用cv库函数进行直方图比较,结果进行排序,并显示。

b) 具体实现

首先调用cv2.imread()读取图像,然后调用cv2.calcHist()计算直方图,cv2.normalize()均衡化后进入比较阶段,调用cv2.compareHist(),比较待检索图和图片库图像之间的直方图差异,然后调用DisplayTotalPics()进行显示。

关键代码如下:
 
 
results = {} #记录结果
reverse = True #correlation/intersection方法reverse为true,另外两种为false

imgCV = cv2.imread(self.testImg.encode('utf-8'))
#self.testImg为待匹配图片
testHist = cv2.calcHist([imgCV],[0,1,2],None,[8,8,8],[0,256,0,256,0,256])
#提取直方图
testHist = cv2.normalize(testHist,testHist,0,255,cv2.NORM_MINMAX).flatten()
#均衡化

#计算self.testImg和其他图片的直方图差异,INTERSECTION方法效果比较好
for (k, hist) in self.index_cv.items():
#self.index_cv保存的是图片库中图片的直方图信息
  d = cv2.compareHist(testHist,hist, cv2.cv.CV_COMP_INTERSECT)
  results[k] = d
  #对结果排序,以v即上面的d作为关键字
  results = sorted([(v, k) for (k, v) in results.items()], reverse = reverse)
  end = time.time()
  print 'OpenCV Time:'
  print end-start    
self.DisplayTotalPics(results)
 

c) 问题与解决

openCV中的compareHist函数中提供了4中比较方法:

1.相关系数标准(method=CV_COMP_CORREL) 值越大,相关度越高,最大值1,最小值0
2.卡方系数标准(method=CV_COMP_CHISQR) 值越小,相关度越高,无上限,最小值0
3.相交系数标准(method=CV_COMP_INTERSECT)值大,相关度越高,最大9.455319,最小0
4.巴氏系数的标准(method=CV_COMP_BHATTACHARYYA) 值小,相关度越高,最大值1,最小值0

测试后选择的是method = cv2.cv.CV_COMP_INTERSECT

另外,该方法的速度很快,完全基于图像的色彩分布,但在一些情况下精度并不高。

方法三:平均哈希值比较算法实现

用到的函数:getKey(),getCode(),cmpCode()

a) 基本思路

平均哈希值的比较算法是基于像素分布的,比较对象是灰度图的图像指纹。图像指纹的计算通过比较每个图的像素值和平均像素值来计算,然后计算图像指纹之间的汉明距离,排序后得到相似图像。

b) 具体实现

具体方法是:计算进行灰度处理后图片的所有像素点的平均值,然后遍历灰度图片每一个像素,如果大于平均值记录为1,否则为0,这一步通过定义函数getCode(img)完成。接着计算编码之间的汉明距离,即一组二进制数据变为另一组数据所需的步骤数,汉明距离越小,说明图像指纹的相似度越高。计算汉明距离可以通过简单的遍历和计数来完成,函数为compCode(code1,code2),其中code1和code2为getCode得到的图像指纹。

关键函数代码如下:
 
 
#获取排序时的关键值(即汉明距离)   
def getKey(x):
  return int(x[1])

#由灰度图得到2值“指纹”,从而计算汉明距离
def getCode(img):
  w,h = img.size
  pixel = []
  for i in range(0,w):
    for j in range(0,h):
      pixel_value = img.getpixel((i,j))
      pixel.append(pixel_value) #加入pixel数组
  avg = sum(pixel)/len(pixel) #计算像素平均值

  cp = [] #二值数组
  for px in pixel:
    if px > avg:
      cp.append(1)
    else:
      cp.append(0)
  return cp

#计算两个编码之间的汉明距离
def compCode(code1,code2):
  num = 0
  for index in range(0,len(code1)):
    if code1[index] != code2[index]:
      num+=1
  #print num
  #print '\n'
  return num
 

c) 问题与优化

我们发现在数据量大时,该方法的检索速度较慢,因此我们将图像指纹也作为图像的属性存在self.hashCode中,在importFolder时计算好,避免后续操作中的冗余重复计算。


版权声明 : 本文内容来源于互联网或用户自行发布贡献,该文观点仅代表原作者本人。本站仅提供信息存储空间服务和不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权, 违法违规的内容, 请发送邮件至2530232025#qq.cn(#换@)举报,一经查实,本站将立刻删除。
原文链接 : https://blog.csdn.net/Mengwei_Ren/article/details/73359298
相关文章
  • Python Django教程之实现新闻应用程序

    Python Django教程之实现新闻应用程序
    Django是一个用Python编写的高级框架,它允许我们创建服务器端Web应用程序。在本文中,我们将了解如何使用Django创建新闻应用程序。 我们将
  • 书写Python代码的一种更优雅方式(推荐!)

    书写Python代码的一种更优雅方式(推荐!)
    一些比较熟悉pandas的读者朋友应该经常会使用query()、eval()、pipe()、assign()等pandas的常用方法,书写可读性很高的「链式」数据分析处理代码
  • Python灰度变换中伽马变换分析实现

    Python灰度变换中伽马变换分析实现
    1. 介绍 伽马变换主要目的是对比度拉伸,将图像灰度较低的部分进行修正 伽马变换针对的是对单个像素点的变换,也就是点对点的映射 形
  • 使用OpenCV实现迷宫解密的全过程

    使用OpenCV实现迷宫解密的全过程
    一、你能自己走出迷宫吗? 如下图所示,可以看到是一张较为复杂的迷宫图,相信也有人尝试过自己一点一点的找出口,但我们肉眼来解谜
  • Python中的数据精度问题的介绍

    Python中的数据精度问题的介绍
    一、python运算时精度问题 1.运行时精度问题 在Python中(其他语言中也存在这个问题,这是计算机采用二进制导致的),有时候由于二进制和
  • Python随机值生成的常用方法

    Python随机值生成的常用方法
    一、随机整数 1.包含上下限:[a, b] 1 2 3 4 import random #1、随机整数:包含上下限:[a, b] for i in range(10): print(random.randint(0,5),end= | ) 查看运行结
  • Python字典高级用法深入分析讲解
    一、 collections 中 defaultdict 的使用 1.字典的键映射多个值 将下面的列表转成字典 l = [(a,2),(b,3),(a,1),(b,4),(a,3),(a,1),(b,3)] 一个字典就是一个键对
  • Python浅析多态与鸭子类型使用实例
    什么多态:同一事物有多种形态 为何要有多态=》多态会带来什么样的特性,多态性 多态性指的是可以在不考虑对象具体类型的情况下而直
  • Python字典高级用法深入分析介绍
    一、 collections 中 defaultdict 的使用 1.字典的键映射多个值 将下面的列表转成字典 l = [(a,2),(b,3),(a,1),(b,4),(a,3),(a,1),(b,3)] 一个字典就是一个键对
  • Python淘宝或京东等秒杀抢购脚本实现(秒杀脚本

    Python淘宝或京东等秒杀抢购脚本实现(秒杀脚本
    我们的目标是秒杀淘宝或京东等的订单,这里面有几个关键点,首先需要登录淘宝或京东,其次你需要准备好订单,最后要在指定时间快速
  • 本站所有内容来源于互联网或用户自行发布,本站仅提供信息存储空间服务,不拥有版权,不承担法律责任。如有侵犯您的权益,请您联系站长处理!
  • Copyright © 2017-2022 F11.CN All Rights Reserved. F11站长开发者网 版权所有 | 苏ICP备2022031554号-1 | 51LA统计