【python计算机视觉编程——7.图像搜索】

2024-09-08 11:28

本文主要是介绍【python计算机视觉编程——7.图像搜索】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

python计算机视觉编程——7.图像搜索

  • 7.图像搜索
    • 7.1 基于内容的图像检索(CBIR)
    • 从文本挖掘中获取灵感——矢量空间模型(BOW表示模型)
    • 7.2 视觉单词
        • **思想**
        • **特征提取**:
    • 创建词汇
    • 7.3 图像索引
      • 7.3.1 建立数据库
      • 7.3.2 添加图像
    • 7.4 在数据库中搜索图像
      • 7.4.1 利用索引获取获选图像
      • 7.4.2 用一幅图像进行查询
      • 7.4.3 确定对比基准并绘制结果
    • 7.5 使用几何特性对结果排序

7.图像搜索

利用文本挖掘技术对基于图像视觉内容进行图像搜索

7.1 基于内容的图像检索(CBIR)

CBIR用于检索在视觉上具有相似性的图像(颜色相似,纹理相似、图像中的物体或场景相似)。

将查询图像与数据库中所有的图像进行 完全比较(特征匹配)往往是不可行的,庞大的数据库回导致耗时过多。

  • 从文本挖掘中获取灵感——矢量空间模型(BOW表示模型)

矢量空间模型是一个用于表示和搜索文本文档的模型。这些矢量是由文本词频直方图构成的。换句话说,矢量包含了每个单词出现的次数。

通过单词计数来构建文档直方图向量v,从而建立文档索引。通常,在单词计数时会忽略掉一些常用词,“这” “和” “是”等,这些常用词称为停用词。由于每篇文档长度不同,故除以直方图总和将向量归一化成单位长度。对于直方图向量中的每个元素,一般根据每个单词的重要性来赋予相应的权重。通常,数据集(或语料库)中一个单词的重要性与它在文档中出现的次数成正比,而与它在语料库中出现的次数成反比。

  • 单词w在文档d中的词频
    t f w , d = 单词 w 在文档 d 中出现的次数 文档 d 中单词的总数 = n w ∑ j n j {\rm tf}_{w,d}=\frac{单词w在文档d中出现的次数}{文档d中单词的总数}=\frac{n_w}{\sum_j n_j} tfw,d=文档d中单词的总数单词w在文档d中出现的次数=jnjnw

  • 逆向文档频率
    i d f w , d = log ⁡ 在语料库 D 中文档的数目 语料库中包含单词 w 的文档数的 = log ⁡ ∣ ( D ) ∣ { d : w ∈ d } {\rm idf}_{w,d}=\log\frac{在语料库D中文档的数目}{语料库中包含单词w的文档数的}=\log\frac{|(D)|}{\{d:w\in d\}} idfw,d=log语料库中包含单词w的文档数的在语料库D中文档的数目=log{d:wd}(D)

7.2 视觉单词

首先需要建立视觉等效单词,通常采用sift局部描述子做到

  • 思想
    1. 特征提取
      • 从图像中提取局部特征(SIFT)。
    2. 特征聚类

      • 使用聚类算法(如 K-means)将这些局部特征描述符分组到不同的视觉单词中。每个聚类中心代表一个视觉单词。
    3. 特征表示

      • 将每个图像中的局部特征映射到最近的视觉单词上,形成图像的视觉单词直方图
  • 创建词汇

使用sift特征描述子创建视觉单词词汇

from PIL import Image
import os

需用到如下两个函数

def process_image(imagename, resultname, params="--edge-thresh 10 --peak-thresh 5"):if imagename[-3:] != 'pgm':im = Image.open(imagename).convert('L')im.save('tmp.pgm')imagename = 'tmp.pgm'     cmmd = str(".\sift.exe " + imagename + " --output=" + resultname + " " + params)os.system(cmmd)print('processed', imagename, 'to', resultname)
# 可以返回目录中所有jpg图像的列表
def get_imlist(path):return [os.path.join(path,f) for f in os.listdir(path) if f.endswith('.jpg')]
imlist=get_imlist(r'.\first1000')
nbr_images=len(imlist)
featlist=[imlist[i][:-3]+'sift' for i in range(nbr_images)]for i in range(nbr_images):process_image(imlist[i],featlist[i])
  • 创建类名为Vocabulary,内含有两个函数train和project

  • train函数:从图像特征文件中读取特征描述符,使用 K-means 聚类算法生成视觉单词,并计算每个图像的视觉单词直方图。随后,它计算每个视觉单词的 IDF,并保存训练数据的文件路径。

    • 步骤
      1. 读取特征
        • 从第一个特征文件中读取特征,并将其存储在 descriptors 中。
        • 依次读取其他特征文件,将它们的特征垂直堆叠到 descriptors 中。
      2. 训练视觉单词
        • 使用 kmeans 聚类算法对特征进行聚类,得到视觉单词。
        • descriptors[::subsampling, :]表示对特征进行子采样,以提高计算效率。
        • self.voc存储视觉单词,distortion存储聚类的失真度。
      3. 计算视觉单词直方图
        • 对每个图像计算视觉单词直方图。
        • 统计每个视觉单词在所有图像中的出现次数,计算 IDF 值。
      4. 存储训练数据
        • 保存特征文件路径到 self.trainingdata
  • project函数:计算每张图像的视觉单词直方图

    • 步骤

      • 将特征描述符映射到视觉单词

        • 使用 vq(向量量化)方法将特征描述符映射到最近的视觉单词。
        • words 包含每个特征描述符对应的视觉单词索引。
      • 创建视觉单词直方图

        • 遍历 words,统计每个视觉单词的出现次数。
        • 返回图像的视觉单词直方图 imhist。
class Vocabulary(object):def __init__(self,name):self.name=name  # 词汇表的名称self.voc=[]     # 存储视觉单词(词汇)的列表self.idf=[]     # 逆文档频率(IDF)值列表,用于加权视觉单词self.trainingdata=[]  # 训练数据的文件列表self.nbr_words=0   # 视觉单词的数量def train(self,featurefiles,k=100,subsampling=10):"""featurefiles:存储特征文件路径的列表,每个文件包含图像的特征k:视觉单词的数量,默认为 100subsampling:子采样比例,默认为10"""nbr_images=len(featurefiles)descr=[]descr.append(read_features_from_file(featurefiles[0])[1]) # 从第一个特征文件中读取特征,并将其存储在descriptors中descriptors=descr[0]for i in range(1,nbr_images): # 依次读取其他特征文件,将它们的特征垂直堆叠到 descriptors 中descr.append(read_features_from_file(featurefiles[0])[1])descriptors=np.vstack((descriptors,descr[i]))# 使用kmeans聚类算法对特征进行聚类,得到视觉单词# self.voc存储视觉单词,distortion存储聚类的失真度self.voc,distortion=kmeans(descriptors[::subsampling,:],k,1) #descriptors[::subsampling,:]:表示对特征进行子采样,以提高计算效率self.nbr_words=self.voc.shape[0]imwords=np.zeros((nbr_images,self.nbr_words)) #每一行表示一张图像的视觉单词直方图for i in range(nbr_images):imwords[i]=self.project(descr[i]) # 计算每张图像的视觉单词直方图,并将其存储在imwords的对应行中nbr_occurences=np.sum((imwords>0)*1,axis=0)  # 计算每个视觉单词在多少张图像中出现过self.idf=np.log((1.0*nbr_images)/(1.0*nbr_occurences+1)) #计算每个视觉单词的逆文档频率(IDF)。IDF是用来加权视觉单词的,避免频繁出现的视觉单词占据主导地位。+1 是为了避免除零错误self.trainingdata=featurefiles  # 保存训练数据文件路径列表,以便后续使用def project(self,descriptors):imhist=np.zeros((self.nbr_words))  # 使用 vq(向量量化)方法将特征描述符映射到最近的视觉单词words,distance=vq(descriptors,self.voc)  # words 包含每个特征描述符对应的视觉单词索引for w in words:imhist[w]+=1return imhist
voc=Vocabulary('ukbenchtest')
voc.train(featlist,1000,10) # 使用 featlist 中的特征文件训练 voc 对象,设定视觉单词数量为 1000,子采样比例为 10with open('vocabulary.pkl','wb') as f:pickle.dump(voc,f)
print('vocabulary is:',voc.name,voc.nbr_words)

在这里插入图片描述

7.3 图像索引

7.3.1 建立数据库

from numpy import *
import pickle
import sqlite3 as sqlite
class Indexer(object):def __init__(self,db,voc):""" Initialize with the name of the database and a vocabulary object. """self.con = sqlite.connect(db) #使用SQLite的connect函数连接到指定的数据库文件db,并将连接对象存储在 self.con 中self.voc = voc  # 将传入的 voc(词汇对象)存储在 self.voc 中,以便后续操作中使用def __del__(self):self.con.close()  # 在对象被销毁时,关闭与数据库的连接,以释放资源。def db_commit(self):self.con.commit()  # 提交当前事务,将对数据库的所有修改保存到数据库中。def create_tables(self): """ Create the database tables. """self.con.execute('create table imlist(filename)') #创建一个名为 imlist 的表,该表包含一个字段 filename,用于存储图像文件名。self.con.execute('create table imwords(imid,wordid,vocname)') # 创建一个名为 imwords 的表,包含字段 imid(图像ID)、wordid(视觉单词ID)和 vocname(词汇名称)。此表用于存储每张图像中视觉单词的出现情况。self.con.execute('create table imhistograms(imid,histogram,vocname)') #创建一个名为 imhistograms 的表,包含字段 imid(图像ID)、histogram(图像的视觉单词直方图)和 vocname(词汇名称)。此表用于存储每张图像的视觉单词直方图。        self.con.execute('create index im_idx on imlist(filename)') #为 imlist 表中的 filename 字段创建一个索引,以加快对图像文件名的查询速度。self.con.execute('create index wordid_idx on imwords(wordid)') #为 imwords 表中的 wordid 字段创建一个索引,以加快对视觉单词ID的查询速度。self.con.execute('create index imid_idx on imwords(imid)') #为 imwords 表中的 imid 字段创建一个索引,以加快对图像ID的查询速度。self.con.execute('create index imidhist_idx on imhistograms(imid)') #为 imhistograms 表中的 imid 字段创建一个索引,以加快对图像ID的查询速度。

7.3.2 添加图像

因为需要在索引中添加图像,所以还需要在类中添加以下几个方法

    def add_to_index(self,imname,descr):"""将图像及其特征描述符添加到数据库中"""if self.is_indexed(imname): return # 如果图像已经被索引(即已经存在于数据库中),则退出方法,避免重复索引。print('indexing', imname)imid = self.get_id(imname)imwords = self.voc.project(descr) #使用词汇对象 self.voc 的 project 方法,将特征描述符 descr 转换为视觉单词的直方图 imwordsnbr_words = imwords.shape[0] #获取视觉单词直方图中视觉单词的数量 nbr_wordsfor i in range(nbr_words):word = imwords[i]# wordid is the word number itselfself.con.execute("insert into imwords(imid,wordid,vocname) values (?,?,?)", (imid,word,self.voc.name))# 将图像 ID (imid)、视觉单词直方图 imwords(使用 pickle.dumps 将 NumPy 数组编码为字符串)和词汇名称 (self.voc.name) 插入到 imhistograms 表中,记录图像的视觉单词直方图self.con.execute("insert into imhistograms(imid,histogram,vocname) values (?,?,?)", (imid,pickle.dumps(imwords),self.voc.name))
    def is_indexed(self,imname):"""检查图像是否已被索引"""#执行 SQL 查询,检查 imlist 表中是否存在与 imname 匹配的 filename#fetchone() 方法返回查询结果的第一行。如果存在匹配的记录,则返回该记录;否则,返回 Noneim = self.con.execute("select rowid from imlist where filename='%s'" % imname).fetchone()return im != None
    def get_id(self,imname):"""获取图像的唯一 ID。如果图像不在数据库中,则将其添加进去并返回新 ID"""#执行 SQL 查询,从 imlist 表中获取与 imname 匹配的图像 ID(rowid)cur = self.con.execute("select rowid from imlist where filename='%s'" % imname)res=cur.fetchone()if res==None:cur = self.con.execute("insert into imlist(filename) values ('%s')" % imname)return cur.lastrowidelse:return res[0] 

接着我们遍历整个数据库中的样本图像,并将其加入我们的索引

nbr_images=len(imlist)
with open('vocabulary.pkl','rb') as f:voc=pickle.load(f)indx=Indexer('test.db',voc)
indx.create_tables()for i in range(nbr_images)[:1000]:locs,descr=read_features_from_file(featlist[i])indx.add_to_index(imlist[i],descr)indx.db_commit()
con=sqlite.connect('test.db')
print(con.execute('select count (filename) from imlist').fetchone())
print(con.execute('select * from imlist').fetchone())

在这里插入图片描述

7.4 在数据库中搜索图像

为实现搜索,我们创建一个Searcher类

class Searcher(object):def __init__(self,db,voc):""" Initialize with the name of the database. """self.con = sqlite.connect(db)self.voc = vocdef __del__(self):self.con.close()

7.4.1 利用索引获取获选图像

需要利用建立起来的索引找到包含特定单词的所有图像,因此添加candidates_from_word函数到Searcher类中

    def candidates_from_word(self,imword):""" Get list of images containing imword. """im_ids = self.con.execute("select distinct imid from imwords where wordid=%d" % imword).fetchall()return [i[0] for i in im_ids]

需要在合并了的列表中对每一个图像id出现的次数进行跟踪

    def candidates_from_histogram(self,imwords):""" Get list of images with similar words. """# get the word idswords = imwords.nonzero()[0]# find candidatescandidates = []for word in words:c = self.candidates_from_word(word)candidates+=c# take all unique words and reverse sort on occurrence tmp = [(w,candidates.count(w)) for w in set(candidates)]#         tmp.sort(cmp=lambda x,y:cmp(x[1],y[1]))tmp.sort(key=lambda x: x[1], reverse=True)tmp.reverse()# return sorted list, best matches first    return [w[0] for w in tmp] 
src=Searcher('test.db',voc)
locs,descr=read_features_from_file(featlist[0])
iw=voc.project(descr)print('ask using a histogram...')
print(src.candidates_from_histogram(iw)[:10])

在这里插入图片描述

7.4.2 用一幅图像进行查询

添加get_imhistogram函数到Searcher类中

    def get_imhistogram(self,imname):""" Return the word histogram for an image. """im_id = self.con.execute("select rowid from imlist where filename='%s'" % imname).fetchone()s = self.con.execute("select histogram from imhistograms where rowid='%d'" % im_id).fetchone()# use pickle to decode NumPy arrays from string#         return pickle.loads(str(s[0]))
#         print(type(s[0]))return pickle.loads(s[0])

添加query函数到Searcher类中

    def query(self,imname):""" Find a list of matching images for imname. """h = self.get_imhistogram(imname)candidates = self.candidates_from_histogram(h)matchscores = []for imid in candidates:# get the namecand_name = self.con.execute("select filename from imlist where rowid=%d" % imid).fetchone()cand_h = self.get_imhistogram(cand_name)cand_dist = sqrt( sum( self.voc.idf*(h-cand_h)**2 ) )matchscores.append( (cand_dist,imid) )# return a sorted list of distances and database idsmatchscores.sort()return matchscores
src=Searcher('test.db',voc)
print('try a query...')
print(src.query(imlist[0])[:10])

7.4.3 确定对比基准并绘制结果

def compute_ukbench_score(src,imlist):""" Returns the average number of correctimages on the top four results of queries. """nbr_images = len(imlist)pos = zeros((nbr_images,4))# get first four results for each imagefor i in range(nbr_images):pos[i] = [w[1]-1 for w in src.query(imlist[i])[:4]]# compute score and return averagescore = array([ (pos[i]//4)==(i//4) for i in range(nbr_images)])*1.0return sum(score) / (nbr_images)
compute_ukbench_score(src,imlist) 

定义plot_results函数

def plot_results(src,res):""" Show images in result list 'res'. """figure()nbr_results = len(res)for i in range(nbr_results):imname = src.get_filename(res[i])subplot(1,nbr_results,i+1)imshow(array(Image.open(imname)))axis('off')show()
src=Searcher('test.db',voc)
nbr_results=6
res=[w[1] for w in src.query(imlist[0])[:nbr_results]]
plot_results(src,res)

在这里插入图片描述

7.5 使用几何特性对结果排序

#载入图像列表
imlist=get_imlist(r'.\first1000')
nbr_images = len(imlist)
#载入特征列表
featlist = [imlist[i][:-3]+'sift' for i in range(nbr_images)]nbr_images=len(imlist)with open('vocabulary.pkl','rb') as f:voc=pickle.load(f)src=Searcher('test.db',voc)q_ind=50
nbr_results=20res_reg=[w[1] for w in src.query(imlist[q_ind])[:nbr_results]]
print('top matches (regular):',res_reg)q_locs,q_descr=read_features_from_file(featlist[q_ind])
fp=make_homog(q_locs[:,:2].T)model=RansacModel()rank={}
for ndx in res_reg[1:]:locs,descr=read_features_from_file(featlist[ndx])matches=match(q_descr,descr)ind=matches.nonzero()[0]ind2=matches[ind]tp=make_homog(locs[:,:2].T)try:H,inliers=H_from_ransac(fp[:,ind],tp[:,ind2],model,match_theshold=4)except:inliers=[]rank[ndx]=len(inliers)sorted_rank=sorted(rank.items(),key=lambda t:t[1],reverse=True)
res_geom=[res_reg[0]]+[s[0] for s in sorted_rank]
print('top matches (homography):',res_geom)plot_results(src,res_reg[:8])
plot_results(src,res_geom[:8])

在这里插入图片描述

这篇关于【python计算机视觉编程——7.图像搜索】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1147980

相关文章

基于人工智能的图像分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 图像分类是计算机视觉中的一个重要任务,目标是自动识别图像中的对象类别。通过卷积神经网络(CNN)等深度学习技术,我们可以构建高效的图像分类系统,广泛应用于自动驾驶、医疗影像诊断、监控分析等领域。本文将介绍如何构建一个基于人工智能的图像分类系统,包括环境

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。

hdu1240、hdu1253(三维搜索题)

1、从后往前输入,(x,y,z); 2、从下往上输入,(y , z, x); 3、从左往右输入,(z,x,y); hdu1240代码如下: #include<iostream>#include<algorithm>#include<string>#include<stack>#include<queue>#include<map>#include<stdio.h>#inc

Linux 网络编程 --- 应用层

一、自定义协议和序列化反序列化 代码: 序列化反序列化实现网络版本计算器 二、HTTP协议 1、谈两个简单的预备知识 https://www.baidu.com/ --- 域名 --- 域名解析 --- IP地址 http的端口号为80端口,https的端口号为443 url为统一资源定位符。CSDNhttps://mp.csdn.net/mp_blog/creation/editor

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

计算机毕业设计 大学志愿填报系统 Java+SpringBoot+Vue 前后端分离 文档报告 代码讲解 安装调试

🍊作者:计算机编程-吉哥 🍊简介:专业从事JavaWeb程序开发,微信小程序开发,定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事,生活就是快乐的。 🍊心愿:点赞 👍 收藏 ⭐评论 📝 🍅 文末获取源码联系 👇🏻 精彩专栏推荐订阅 👇🏻 不然下次找不到哟~Java毕业设计项目~热门选题推荐《1000套》 目录 1.技术选型 2.开发工具 3.功能

nudepy,一个有趣的 Python 库!

更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个有趣的 Python 库 - nudepy。 Github地址:https://github.com/hhatto/nude.py 在图像处理和计算机视觉应用中,检测图像中的不适当内容(例如裸露图像)是一个重要的任务。nudepy 是一个基于 Python 的库,专门用于检测图像中的不适当内容。该