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

  • 时间:
  • 浏览:17

简介:

本文引见了图象检索的3种真现体例,均用Python完成,此中前两种基于曲圆图比力,哈希法基于像素散布。
检索体例是:提早导进图片库做为检索范畴,给出待检索的图片,将其取图片库中的图片停止比力,得出一切类似度落后止排序,从而检索成果为类似度由下到低的图片。因为工程中借包括Qt界里类、触收函数等其他部份,正在该文档中只给出枢纽函数的代码。

开辟体系:MacOS
真现体例:Qt + Python

办法1:自界说的曲圆图比力算法

a) 根本思绪

遍历图片像素面,提与R\G\B值并停止对应的计数,获得本初曲圆图,但因为0⑵55的范畴太年夜,因而每个像素值的统计量均偏偏小,因而别离将R\G\B的256个像素值映照到0⑶1共32个像素值上,将像素值范畴由256*3减少到32*3。记载像素值采取的数据构造为1维数组,第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)

测验考试了两种体例,第1种是对图象遍用时逐一挪用getpixel()去获得R,G,B的值,但发明这类体例的速率太缓。第2种采取的是内存读与,操纵load()函数1次性读与图象的像素值,然后对像素值停止遍历,该办法的速率比逐一提与更快。

#统计曲圆图,用load()载进图片的像素pix,再别离读与每一个像素面的R\G\B值停止统计(别离为0⑵55)
#将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)

办法2:openCV库的曲圆图比力算法真现

openCV开源库已散成了曲圆图提与、曲圆图平衡化和曲圆图比力的功用,挪用便利。为了进1步领会曲圆图比力的各种真现办法,操纵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⑻'))
#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

别的,该办法的速率很快,完整基于图象的色采散布,但正在1些状况下粗度其实不下。

办法3:均匀哈希值比力算法真现

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

a) 根本思绪

均匀哈希值的比力算法是基于像素散布的,比力工具是灰度图的图象指纹。图象指纹的计较经由过程比力每一个图的像素值战争均像素值去计较,然后计较图象指纹之间的汉明间隔,排序后获得类似图象。

b) 详细真现

详细办法是:计较停止灰度处置后图片的一切像素面的均匀值,然后遍历灰度图片每个像素,若是年夜于均匀值记载为1,不然为0,那1步经由过程界说函数getCode(img)完成。接着计较编码之间的汉明间隔,即1组2进造数据变成另外一组数据所需的步调数,汉明间隔越小,申明图象指纹的类似度越下。计较汉明间隔能够经由过程简朴的遍历战计数去完成,函数为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 = [] #2值数组
  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时计较好,制止后绝操纵中的冗余反复计较。

以上便是本文的全数内容,期望对各人的进修有所帮忙,也期望各人多多撑持剧本之家。