本项目引用部分LIRe(Lucene Image Retrieval)框架源码以及Facebook faiss引擎部分思想,基于Apache Lucene的以图搜图引擎。通过实时接收Kafka中传来的基于MTCNN深度模型人脸识别算法得到512维的特征向量,实时建立索引,并且加入缓存机制,并且支持一定日期范围内(可配置)快速检索。 为了方便开发和阅读,涉及到项目中的关键词均用英文,比如Document, Extractor, Builder等。
LIRE(Lucene Image Retrieval)是一款基于lucene的图像特征索引工具。
lucene是一个开源的强大的索引工具,但是它仅限于文本索引,LIRe基于lucene对图像特征建立索引和搜索。
- 获取内容(分析图像)
在索引操作期间,图像数据首先被DocumentBuilder对象解析,使用Extractor提取特征,并创建对应的Document实例,该实例包含两个Field实例(图像特征和图像对应的标志字符串),它们都是图像的重要信息。随后的分析过程将域处理成大量语汇单元。最后将语汇单元加入到段结构中。 - 建立文档
使用Lucene索引数据时,必须先从数据中提取纯文本格式信息,以便Lucene识别该文本并建立对应的Lucene文档。 - 文档分析
一旦建立其Lucene文档和域,就可以调用IndexWriter对象的addDocument方法将数据传递给Lucene进行索引操作了。在索引操作时,Lucene首先分析文本,将文本数据分割成语汇单元串,然后对它们执行一些可选操作。 - 文档索引
在索引步骤中,文档被加入到索引列表。
- 在索引操作期间,图像数据首先被DocumentBuilder对象解析,使用Extractor提取特征,并创建对应的Document实例,该实例包含两个Field实例(图像特征和图像对应的标志字符串),它们都是图像的重要信息。随后的分析过程将域处理成大量语汇单元。最后将语汇单元加入到段结构中。
- 提取文本和创建文档 �使用Lucene索引数据时,必须先从数据中提取纯文本格式信息,以便Lucene识别该文本并建立对应的Lucene文档。
- IndexWriter
索引过程的核心组件。这个类负责创建新索引或者打开已有索引,以及向索引中添加、删除或更新被索引文档的信息。可以把IndexWriter看作这样一个对象:它为你提供针对索引文件的写入操作,但不能用于读取或搜索索引。IndexWriter需要开辟一定空间来存储索引,该功能可以由Directory完成 - Directory
该类描述了Lucene索引的存放位置。它是一个抽象类,它的子类负责具体指定索引的存储路径。用FSDirectory.open方法来获取真实文件在文件系统的存储路径,然后将它们一次传递给IndexWriter类构造方法。IndexWriter不能直接索引文本,这需要先由Analyzer将文本分割成独立的单词才行。 - Analyzer
文本文件在被索引之前,需要经过Analyzer(分析器)处理。Analyzer是由IndexWriter的构造方法来指定的,它负责从被索引文本文件中提取语汇单元,并提出剩下的无用信息。如果被索引内容不是纯文本文件,那就需要先将其转换为文本文档。对于要将Lucene集成到应用程序的开发人员来说,选择什么样Analyzer是程序设计中非常关键的一步。分析器的分析对象为文档,该文档包含一些分离的能被索引的域。 - Document
Document对象代表一些域(Field)的集合。文档的域代表文档或者文档相关的一些元数据。元数据(如作者、标题、主题和修改日期等)都作为文档的不同域单独存储并被索引。Document对象的结构比较简单,为一个包含多个Filed对象容器;Field是指包含能被索引的文本内容的类。 - Field
索引中的每个文档都包含一个或多个不同命名的域,这些域包含在Field类中。每个域都有一个域名和对应的域值,以及一组选项来精确控制Lucene索引操作各个域值。
- 每一张图片对应一个document对象,document对象包含多个Field
- Field ①为图像文件的为一id,官网源码默认的是图片的路径(url)
- 除了第一个Field,其他Field都与图像特征feature有关,DocumentBuilder在初始化之前可以指定特征提取算法(Extractor),Field ②③④ 分别对应不同的算法提取的特征。
- Extractor提取特征的时候,特征使用double[] 存储,后面生成Field时会压缩成byte[] ,因为lucene都是以二进制形式保存数据的。
- 以上当一个document对象创建完成后,也就是一张图片解析完之后,会交给lucene来加到索引中去,lucene索引使用的是倒排索引的数据结构。
- DocumentBuilder是建立Document的接口类,Document就是lucene中的文档,在本项目中Document对象包含了图像的feature和图像的唯一标识字符串两个Field
- 安装sdkman(软件管理工具)
$ curl -s "https://get.sdkman.io" | bash
$ source "$HOME/.sdkman/bin/sdkman-init.sh"
- 检查是否安装成功
$ sdk version
- 安装gradle
$ sdk install gradle 4.7
-
安装chocolatey(windows上的软件安装工具)
- 使用cmd.exe
@"%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe" -NoProfile -InputFormat None -ExecutionPolicy Bypass -Command "iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))" && SET "PATH=%PATH%;%ALLUSERSPROFILE%\chocolatey\bin"
- 使用PowerShell.exe
首先运行
Get-ExecutionPolic
如果返回
Restricted
则运行
Set-ExecutionPolicy AllSigned 或者 Set-ExecutionPolicy Bypass -Scope Process
最后运行
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
-
安装Gradle
choco install gradle
$ gradle copyJar
在build/libs中会生成 Antaeus-1.0.jar
$ gradle build
- kafka消息队列接收
- 输入本地图像所在文件夹自动建立索引
最后一个参数是需要index的图片文件夹路径
$ cd /home/Antaeus
$ java -cp build/libs/Antaeus-1.0.jar com.oceanai.main.AntaeusServer index.json
or
$ cd /home/Antaeus
$ ./start.sh -antaeus
对象数据结构
public class IndexMessage {
private String id;
private double[] feature;
}
{"id":"0","feature":[0.06056745,0.01256264,...,510 values more]}
[{"id":"14,02607d203666","feature":[-0.08406701683998108,...]},
{"id":"14,02607d203666","feature":[-0.08406701683998108,...]}]
$ java -cp build/libs/Antaeus-1.0.jar net.semanticmetadata.lire.lire.Indexer images/
详细请见search api文档
FROM antaeus-base
MAINTAINER wangrupeng [email protected]
EXPOSE 28888
MAINTAINER wangrupeng [email protected]
COPY Antaeus /home/Antaeus
WORKDIR /home/Antaeus
docker build -t image-antaeus ./
/etc/init.d/OpenSSL start