https://github.com/TouwaErioH/Machine-Learning/tree/master/image%20identification/Histogram%20retrieval

// 优化为对图片求直方图时分块,或者加权,越靠近中心权重越高

在指定的图片数据库内,完成图片检索。图像数据按照文件名的次序大概100幅为1类,以颜色直方图为依据,

用最邻近方法或其他方法,随机抽取一张图片,利用模板匹配方法在图片库中找出100幅最相似的图片,计算查全率和查准率。

报告最后部分展示10幅来自不同类别的图片,计算查全率和查准率,展示最接近的5幅图片,并分析结果。

数据集为

http://www.vision.caltech.edu/Image_Datasets/Caltech101/Caltech101.html

参考文献  Histogram-Based Color Image Retrieval

检索方法:

采用图像的RGB三通道直方图与hsv直方图,利用欧几里得距离(Euclid),卡方比较(Chi-Square),Bhattacharyya distance(巴氏距离),相关性比较(Correlation),计算与模板的距离,找到最相近的图片。

影响性能的参数:

rgb的直方图bins,hsv直方图的h,s的bins,以及采用的检索模式。

利用API:

cv2. calcHist()

cv2.compareHist()

# -*- coding: utf-8 -*-
"""
Created on Thu Oct 17 16:01:42 2019 @author: erio
"""
'''
从下面10组中随机各选取一幅图片,
直接根据其颜色直方图在9908(0-9907)幅图片中按照最邻近方法找出最接近的图片(若超出100幅取最接近的100幅。若不足100幅则不足)
计算查全率查准率
并展示最接近的五福图片
0-99 butterfly 100 mark 1,第一组图片,选取19.bmp为模板
100-199 mountain 100 mark 2 125.bmp
300-399 mark3 376.bmp
700-799 luori 100 mark 4 747.bmp
800-899 花 mark5 850.bmp
899-998 tree 100 mark 6 940.bmp
1106-1205 mark 7 1177.bmp
1593-1692 mark 8 1596.bmp
8641 8740 mark 9 8655.bmp
9029 9128 mark 10 9037.bmp
''' import cv2
import numpy as np #转bmp
def jpg2bmp():
for i in range(0,9908):
nam='D:/image/'+str(i)+'.jpg'
nam1='D:/image/'+str(i)+'.bmp'
img = cv2.imread(nam, 1)
cv2.imwrite(nam1, img) #计算图片的hsv histogram h,s为Hue, Saturation的bins
def calchsv(start,end,h,s):
histoh=[]
for i in range(start,end+1):
img = cv2.imread('D:/image/'+str(i)+'.bmp')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist1 = cv2.calcHist([hsv], [0, 1], None, [h, s], [0, 180, 0, 256])
#cv2.normalize(hist1, hist1, 0, 1, cv2.NORM_MINMAX, -1); #归一化,后面数据处理的方便,其次是保证程序运行时收敛加快
histoh.append(hist1)
return histoh #计算图片的rgb histogram 。分三个通道RGB计算,每个通道bins为bins,而后拼接为一个histogram.
def calcRGBhisto(start,end,bins):
histor=[] #histo storage all histogram nparrays
for i in range(start,end+1):
img = cv2.imread('D:/image/'+str(i)+'.bmp')
#histc = cv2.calcHist([img],[0,1,2],None,[bins,bins,bins],[0,255,0,255,0,255])
hist2 = cv2.calcHist([img],[2],None,[bins],[0,255]) #np.array RGB三通道
hist0 = cv2.calcHist([img],[0],None,[bins],[0,255]) #np.array
hist1 = cv2.calcHist([img],[1],None,[bins],[0,255]) #np.array
histf=np.vstack((hist0,hist1,hist2)) #histf,当前图片的直方图的nparray
#cv2.normalize(histf, histf, 0, 1, cv2.NORM_MINMAX, -1);
histor.append(histf)
return histor #imggroup为记录搜索数据的array。形如[[19,0,99],[125,100,199]] 意味第一组图片范围为0-99,选取19号图片为标准搜索
#hisstart,hisend为要做检索的图片范围,如0,9907
#method为采用的检索方式。如Euclid为根据图片的直方图的欧几里得距离,越短认为越接近
def search(imggroup,gsize,hisstart,hisend,method): #method记录判定方式,如Euclid;
rgbeqpre=0 #平均查全率查准率
hsveqrecall=0
rgbeqrecall=0
hsveqpre=0
if (method=="Euclid"):
calmethod="Euclid"
elif (method=="Correlation"):
calmethod=cv2.HISTCMP_CORREL
elif (method=="ChiSquare"):
calmethod=cv2.HISTCMP_CHISQR
else:
calmethod=cv2.HISTCMP_BHATTACHARYYA
rgbdis=[] #rgbdis记录认为属于某组的图片的距离该组标准的距离;如dis[1]记录所有认为属于第二组的图片的距离该组标准150.bmp的距离
hsvdis=[]
rgbresult=[] #rgbresult记录结果,为gsize维数组。从0开始index越小越接近标准。如rgbresult[0]数组记录判定为属于1组的图片index。如rgbresult[0][0]=19,即为19.bmp
hsvresult=[]
rgbindex=[] #rgbindex[0]数组记录判定为属于1组的图片index。
hsvindex=[]
for i in range(0,gsize+1):
rgbdis.append([])
hsvdis.append([])
rgbindex.append([])
hsvindex.append([])
ghisrgb=[] #选取为标准的图片的histogram数组。1维数组。如ghisrgb[0]为19.bmp的histogram
ghishsv=[]
gstart=[] #记录每组开始图片index
gend=[]
for i in range(0,gsize): #ghisrgb,ghishsv 记录各个选取图片的histogram gstart记录图片所属组的开始index,
ghisrgb.append(historgb[imggroup[i][0]]) #如第一组0-99,查找19.bmp,gstart[0]=0,gend[0]=99,ghisrgb[0]=histo[19]
ghishsv.append(histohsv[imggroup[i][0]])
gstart.append(imggroup[i][1])
gend.append(imggroup[i][2])
for i in range(hisstart,hisend+1): #在hisstart-hisend的范围内,计算图片距离所选取的每幅图片距离,选择最近的认为属于该组;cnt记录距离各组距离
tprgbdis=[]
tphsvdis=[] #记录当前图片采用rgb和hsvhistogram,距离选取出的图片的距离
for j in range(0,gsize):
if (calmethod=="Euclid"):
tempr=historgb[i]-ghisrgb[j]
tempr=np.power(tempr,2)
tempdis=np.sum(tempr)
tprgbdis.append(tempdis)
temph=histohsv[i]-ghishsv[j]
temph=np.power(temph,2)
tempdis=np.sum(temph)
tphsvdis.append(tempdis)
else:
match = cv2.compareHist(historgb[i],ghisrgb[j], calmethod)
tprgbdis.append(match)
match = cv2.compareHist(histohsv[i],ghishsv[j], calmethod)
tphsvdis.append(match)
#np.argsort()用于给数组排序,返回值为从小到大元素index的值.
#假设一个数组a为[0,1,2,20,67,3],使用numpy.argsort(a),返回值应为[0,1,2,5,3,4]
if(method=="Correlation"): #Correlation -1-1,越大越接近
tpp=np.argsort(tprgbdis)
final=tpp[gsize-1] #img i 与final组correlation最接近1,认为属于final组
rgbdis[final].append(tprgbdis[final]) #将i.img距离final组标准的距离记录到rgbdis[final]数组,同时其index i记录到rgbindex[final]数组。
rgbindex[final].append(i) tpp=np.argsort(tphsvdis)
final=tpp[0] #img i 与final组euclid距离最短,认为属于final组
hsvdis[final].append(tphsvdis[final])
hsvindex[final].append(i)
else: #其余的三种方法越小越接近
tpp=np.argsort(tprgbdis)
final=tpp[0] #img i 与final组距离最短,认为属于final组
rgbdis[final].append(tprgbdis[final])
rgbindex[final].append(i) tpp=np.argsort(tphsvdis)
final=tpp[0]
hsvdis[final].append(tphsvdis[final])
hsvindex[final].append(i) #gstart[i],第i组起始index。如第0组0-99,gstart[0]=0,gend[0]=99;
#index[i][result[i][j]] index[i]为认为属于[i]组的图片的index数组.result[i]为认为属于i组的图片的dis升序排序后的索引序列
#例如 index[0]={0,24,5} 那么result[0][2]=5
for i in range(0,gsize):
rgbcorr=0 #corr 认为属于i组并且确实属于i组
hsvcorr=0
if(method=="Correlation"): #越大越好
#print(type(rgbdis))
nprd=np.array(rgbdis[i])
nphd=np.array(hsvdis[i])
rgbresult.append(np.argsort(-nprd)) #argsort 得到的result是dis降序排序后的索引序列,数组
hsvresult.append(np.argsort(-nphd)) #result数组中增加一个数组,如[]-->[[0,1,2]],判定属于第0组的图片index为0,1,2
else: #越小越好
rgbresult.append(np.argsort(rgbdis[i]))
hsvresult.append(np.argsort(hsvdis[i])) #print(rgbresult[i].size,hsvresult[i].size)
if rgbresult[i].size<=100: #若判定为i组的图片不足100幅
rgbsize=rgbresult[i].size
else: #若判定为i组的图片超过100幅,取最近的100幅
rgbsize=100
if hsvresult[i].size<=100: #若判定为i组的图片不足100幅
hsvsize=hsvresult[i].size
else: #若判定为i组的图片超过100幅,取最近的100幅
hsvsize=100
for j in range(0,rgbsize): #result[i][0]理论上是被search的图片自身,imgnum
if (gstart[i]<=rgbindex[i][rgbresult[i][j]])&(rgbindex[i][rgbresult[i][j]]<=gend[i]):
rgbcorr=rgbcorr+1
for j in range(0,hsvsize): #result[i][0]理论上是被search的图片自身,imgnum
if (gstart[i]<=hsvindex[i][hsvresult[i][j]])&(hsvindex[i][hsvresult[i][j]]<=gend[i]):
hsvcorr=hsvcorr+1
rgbclose=[]
hsvclose=[] #取最接近的5幅图片展示
for k in range(0,6):
rgbclose.append(rgbindex[i][rgbresult[i][k]])
hsvclose.append(hsvindex[i][hsvresult[i][k]])
rgbpre=rgbcorr/(rgbsize)
rgbeqpre=rgbeqpre+rgbpre
rgbrecall=rgbcorr/100
rgbeqrecall=rgbeqrecall+rgbrecall
hsvpre=hsvcorr/(hsvsize)
hsveqpre=hsveqpre+hsvpre
hsvrecall=hsvcorr/100
hsveqrecall=hsveqrecall+hsvrecall
print("imgnumber %d\n"%(imggroup[i][0]))
print("using rgb histogram %s method 's precision:%.5f ,recall:%.5f\n"%(method,rgbpre,rgbrecall))
print("using hsv histogram %s method 's precision:%.5f ,recall:%.5f\n"%(method,hsvpre,hsvrecall))
print("rgb close 5\n")
print(rgbclose)
print("hsv close 5\n")
print(hsvclose)
print("rgbeqpre: %.5f,rgbeqrecall: %.5f,hsveqpre: %.5f,hsveqrecall: %.5f\n"%(rgbeqpre/gsize,rgbeqrecall/gsize,hsveqpre/gsize,hsveqrecall/gsize)) if __name__ == '__main__':
#jpg2bmp()
histostart = 0
histoend = 9907
histobins=32
h= 90#180
s= 256 #256
historgb = calcRGBhisto(histostart,histoend,histobins)
histohsv = calchsv(histostart,histoend,h,s)
print(type(histohsv))
#每组中选取一幅图片,查找最近的100张,计算查全率查准率。如第一组0-99,查19.bmp
group=[[19,0,99],[125,100,199],[376,300,399],[747,700,799],[850,800,899],[940,899,998],
[1177,1106,1205],[1596,1593,1692],[8655,8641,8740],[9037,9029,9128]]
#group=[[50,0,99],[137,100,199],[350,300,399]]
groupsize = 10
#search(group,groupsize,histostart,histoend,"Euclid")
#search(group,groupsize,histostart,histoend,"Correlation")
#search(group,groupsize,histostart,histoend,"ChiSquare")
search(group,groupsize,histostart,histoend,"Bhattach")

根据直方图 histogram 进行简单的图像检索的更多相关文章

  1. (转)颜色直方图, HSV直方图, histogram bins

    原文链接:https://www.xuebuyuan.com/3256564.html 一个histogram,通常可以用一个列向量表示(例子中的a,b),列向量里面的每一个值就是一个bin(a,b) ...

  2. opencv python:图像直方图 histogram

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

  3. 【POJ2136】Vertical Histogram(简单模拟)

    比较简单,按照样例模拟就好!~ #include <iostream> #include <cstdlib> #include <cstdio> #include ...

  4. 【计算机视觉】Histogram of Oriented Gridients(HOG) 方向梯度直方图

    Histogram of Oriented Gridients(HOG) 方向梯度直方图 Histogram of Oriented Gridients,缩写为HOG,是目前计算机视觉.模式识别领域很 ...

  5. 数字图像处理作业使用OpenCV - 自定义直方图

    第二次作业需要打印出来灰度直方图,当然不能使用ocv的自带calcHist函数来得到Mat对象了……结果上网搜索怎么用自己的数据创建直方图,搜到的都是直接用函数的_(:з」∠)_ 结果这个地方拖了好久 ...

  6. OpenCV-Python教程(10、直方图均衡化)

    相比C++而言,Python适合做原型.本系列的文章介绍如何在Python中用OpenCV图形库,以及与C++调用相应OpenCV函数的不同之处.这篇文章介绍在Python中使用OpenCV和NumP ...

  7. matplotlib简单示例

    一.简介 以下引用自百度百科 Matplotlib 是一个 Python 的 2D绘图库,它以各种硬拷贝格式和跨平台的交互式环境生成出版质量级别的图形 . 通过 Matplotlib,开发者可以仅需要 ...

  8. OpenCV-Python 直方图-3:二维直方图 | 二十八

    目标 在本章中,我们将学习查找和绘制2D直方图.这将在以后的章节中有所帮助. 介绍 在第一篇文章中,我们计算并绘制了一维直方图. 之所以称为一维,是因为我们仅考虑一个特征,即像素的灰度强度值. 但是在 ...

  9. OpenCV计算机视觉学习(9)——图像直方图 & 直方图均衡化

    如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 1, ...

随机推荐

  1. 利用sql_tuning_Advisor调优sql

    1.赋权给调优用户 grant ADVISOR to xxxxxx; 2.创建调优任务 使用sql_text创建 DECLARE my_task_name VARCHAR2 (30); my_sqlt ...

  2. 【Not BUG】微软Winform窗体中设计上的Bug,会导致程序编译失败?不,这不是BUG!

    这不是BUG!!! 原文地址: https://www.cnblogs.com/thanks/p/14302011.html 现在让我们回忆一下原文 原文的操作步骤: 1. 新建一个Window Fo ...

  3. 01-CentOS 8.1安装 Docker

    官方参考地址:https://docs.docker.com/install/linux/docker-ce/centos/ 里面包含包下载地址:https://download.docker.com ...

  4. 远程部署项目,修改catalina.bat文件 完美解决在代理服务器上HttpURLConnection 调接口超时的问题

    远程给客户部署项目,运行时程序调外部接口时总是出不去,经过不懈努力,后来发现客户那边的网络走的是代理,于是在代码中加下面代码: //设置代理 System.setProperty("http ...

  5. 前端知识(二)04-vue-element-admin-谷粒学院

    目录 一.vue-element-admin 1.简介 2.安装 二.vue-admin-template 1.简介 2.安装 一.vue-element-admin 1.简介 vue-element ...

  6. linux中的虚拟环境工具

    1.虚拟环境工具的学习 python的虚拟环境,其实就是在机器上,方便的创建出多个解释器,每个解释器运行一个项目,互相之间不受影响 2.virtualenv工具,可以方便的创建,使用,删除也很方便 3 ...

  7. [微信小程序]字体文件,字体图标(.ttf,.woff,woff2)等无法显示问题

    一. 背景 项目引用了第三方UI框架Vant-weapp,但是前几天Vant的cdn被运营商封禁,导致van-icon无法使用. 有赞官方在Github上给出了在小程序app.wxss上添加以下代码的 ...

  8. circus reload

    circus reload Configuration - Circus 0.15.0 documentation https://circus.readthedocs.io/en/latest/fo ...

  9. 类型检查和鸭子类型 Duck typing in computer programming is an application of the duck test 鸭子测试 鸭子类型 指示编译器将类的类型检查安排在运行时而不是编译时 type checking can be specified to occur at run time rather than compile time.

    Go所提供的面向对象功能十分简洁,但却兼具了类型检查和鸭子类型两者的有点,这是何等优秀的设计啊! Duck typing in computer programming is an applicati ...

  10. 使用nodejs构建Docker image最佳实践

    目录 简介 准备nodejs应用程序 创建Dockerfile文件 创建.dockerignore文件 创建docker image 运行docker程序 node的docker image需要注意的 ...