用图片搜索相似图片(视觉单词)

代码地址

  • 代码GitHub地址

准备文件

  • vlfeat(SIFT的开源实现):下载地址
  • 解压后将vlfeat-0.9.20\bin\win32加到系统的Path路径中,以便在命令行用sift命令
  • 安装pysqlite:pip install pysqlite
  • 安装matplotlib:pip isntall matplotlib
  • 安装cherryPy(轻量级网页服务器):pip install cherrypy
  • 图片库:10000张猫咪图片

流程

  • 用vlfeat(SIFT特征模型)提取每一张图片的特征点
  • 将每一张图的特征点采样聚类成图片的视觉单词
  • 即视觉单词,就是对应图片的代表
  • 创建数据库,将每张图片的视觉单词入库,并建立索引
  • 编写cherryPy的web应用,根据点击的图片搜索相似的图片

提取图片特征点并生成单词文件

  • 前提保证cmd能执行sift命令
  • CMD执行Step1.py
# -*- coding:utf-8 -*-
# Step1.py:提取图片的特征点并生成单词文件vocabulary.pkl
import pickle
import vocabulary
import imtools
import sift

# imlist是图片名字的列表,图片放在static文件夹下
imlist = imtools.get_imlist('static/')

# 图片的总数
nbr_images = len(imlist)

# 将每张图片的特征点存放进对应的.sift特征文件中
featlist = [ imlist[i][:-3]+'sift' for i in range(nbr_images)]

for i in range(nbr_images):
        sift.process_image(imlist[i], featlist[i])

# 利用k-means对图片特征文件聚类训练出对应的单词
# 时间关系,这里只用了46张图做例子,所以只创建46个单词
voc = vocabulary.Vocabulary('imagewords')
voc.train(featlist, 46, 10)

# 将单词都保存到vocabulary.pkl中
with open('vocabulary.pkl', 'wb') as f:
    pickle.dump(voc,f)

# 打印出单词总数量
print 'vocabulary is:', voc.name, voc.nbr_words

将图片单词信息存进数据库

  • 数据库是sqlite
  • CMD执行:Step2.py
# -*- coding:utf-8 -*-
# Step2.py:根据单词文件,将图片单词入sqlite数据库
import pickle
import sift
import imagesearch
import imtools

# 图片名字的列表
imlist = imlist = imtools.get_imlist('static/')
# 图片的数量
nbr_images = len(imlist)
# 对应图片特征文件的列表
featlist = [ imlist[i][:-3]+'sift' for i in range(nbr_images)]

# 载入单词文件
# 将单词,图片名,地址存进数据库images.db
with open('vocabulary.pkl', 'rb')as f:
    voc = pickle.load(f)

indx = imagesearch.Indexer('images.db', voc)
indx.create_tables()

for i in range(nbr_images):
    locs,descr = sift.read_features_from_file(featlist[i])
    indx.add_to_index(imlist[i],descr)

# 将命令提交执行
indx.db_commit()

配置cherryPy网页应用

  • 没点击图片时随机显示15张图片
  • 点击其中一张猫猫图片,搜索相似的图片显示出来
  • 本质是根据点击图片的单词,寻找在数据库中与之相近的单词,并将其显示出来
  • CMD执行Step3.py
  • 在浏览器浏览:127.0.0.1:8080
# -*- coding:utf-8 -*-
# Step3.py:用cherryPy做交互界面,显示结果
import cherrypy, os, urllib, pickle
import imtools
from numpy import *
import imagesearch

# cherryPy页面
# 网页根目录在配置文件service.conf中设置
# 默认端口是8080
class SearchImage:

    def __init__(self):
        # 加载图片名字列表
        self.imlist = imtools.get_imlist('static/')
        self.nbr_images = len(self.imlist)
        self.ndx = range(self.nbr_images)

        # 加载生成好的单词文件
        f = open('vocabulary.pkl', 'rb')
        self.voc = pickle.load(f)
        f.close()

        # 设置开始显示的图片数目
        self.maxres = 15

        # 设置页面的结构
        self.header = """ <!doctype html> <head> <title>Image search example</title> </head> <body> """
        self.footer = """ </body> </html> """

    # 响应index页面
    # 没有搜索的时候随机显示图片
    # 搜索的时候显示与该图片相似的图片,根据视觉单词
    def index(self,query=None):
        self.src = imagesearch.Searcher('images.db', self.voc)

        html = self.header
        html += """ <br /> Click an image to search. <a href='?query='> Random selection </a> of images. <br /><br /> """
        if query:
            # 显示查询结果的图片
            res = self.src.query(query)[:self.maxres]
            for dist,ndx in res:
                imname = self.src.get_filename(ndx)
                html += "<a href='?query="+imname+"'>"
                html += "<img src='"+imname+"' width='100' />"
                html += "</a>"
        else:
            # 随机显示图片
            random.shuffle(self.ndx)
            for i in self.ndx[:self.maxres]:
                imname = self.imlist[i]
                html += "<a href='?query="+imname+"'>"
                html += "<img src='"+imname+"' width='100' />"
                html += "</a>"

        html += self.footer
        return html

    index.exposed = True

# 启动应用
cherrypy.quickstart(SearchImage(), '/', os.path.join(os.path.dirname(__file__), 'service.conf'))

效果

  • 不搜索时:
    用图片搜索相似图片(视觉单词)_第1张图片

  • 点击搜索时:

你可能感兴趣的:(用图片搜索相似图片(视觉单词))