LIRE(Lucene Image Retrieval)相似图像索引和搜索机制

左手的ㄟ右手 2022-06-05 07:59 270阅读 0赞

众说周知,lucene是一个开源的强大的索引工具,但是它仅限于文本索引。基于内容的图像检索(CBIR)要求我们利用图像的一些基本特征(如颜色纹理形状以及sift,surf等等)搜索相似的图片,LIRE(Lucene Image Retrieval)是一款基于lucene的图像特征索引工具,它能帮助我们方便的对图像特征建立索引和搜索,作者也在不断加入新的特征供用户使用。如果你熟悉lucene,那么用LIRE提取特征建立索引是非常方便的。

LIRE官网: http://www.semanticmetadata.net/lire/

包和源码: http://code.google.com/p/lire/

基本使用示例: http://www.semanticmetadata.net/wiki/doku.php?id=start

API: http://www.itec.uni-klu.ac.at/lire/nightly/api/index.html

本文不讨论API的调用方法,我粗略的读了下lire的源码,在这里对它的机制做个简单的说明。

LireFeature是图像特征的接口,具体的特征提取,距离计算,表示都有各自实现的类。值得一提的是,LIRE的作者实现了非常多的特征提取方法,而且都是java实现的,也没有借助opencv等工具,在此之前我能看到的sift特征提取都是c或者c++实现的。

  1. public interface LireFeature {
  2. public void extract(BufferedImage bimg);
  3. public byte[] getByteArrayRepresentation();
  4. public void setByteArrayRepresentation(byte[] in);
  5. public void setByteArrayRepresentation(byte[] in, int offset, int length);
  6. public double[] getDoubleHistogram();
  7. float getDistance(LireFeature feature);
  8. java.lang.String getStringRepresentation();
  9. void setStringRepresentation(java.lang.String s);
  10. }

DocumentBuilder是建立Document的接口类,Document就是lucene中的文档,它建立的文档包含了图像的某个特征和图像的标识字符串两个Field。

  1. public Document createDocument(BufferedImage image, String identifier) throws FileNotFoundException;

ChainedDocumentBuilder可以建立将多个特征综合起来的文档。

DocumentBuilderFactory是DocumentBuilder的工厂类,由它初始化各个特征的DocumentBuilder。

通过调用createDocument就能返回每个图像对应特征和标识的文档,用lucene的IndexWriter就能将它写入索引文件。

SimpleResult是单个搜索的结果,它包含3个成员变量,分别是距离(相似度),文档和索引号。它实现了Comparable接口,排序的方法是按照相似度的由高到底排序,如果相似度一样,就按照索引号在前的排在前面。

  1. public class SimpleResult implements Comparable<SimpleResult> {
  2. private float distance;
  3. private Document document;
  4. private int indexNumber = 0;
  5. public int compareTo(SimpleResult o) {
  6. int compareValue = (int) Math.signum(distance - ((SimpleResult) o).distance);
  7. if (compareValue==0 && !document.equals(o.document)) {
  8. return (int) Math.signum(indexNumber-o.indexNumber);
  9. }
  10. return compareValue;
  11. }
  12. @Override
  13. public boolean equals(Object obj) {
  14. // it's not the same if it's not the same class.
  15. if (! (obj instanceof SimpleResult)) return false;
  16. // it's the same if the document is the same, regardless of the distance.
  17. else return (document.equals(((SimpleResult)obj).document) && indexNumber == ((SimpleResult)obj).indexNumber);
  18. }
  19. }

ImageSearcherFactory是搜索的工厂类,由它初始化各个特征的搜索类。

这里主要讲一下GenericFastImageSearcher类,很多特征都能通过它来搜索,它的成员变量maxHits为搜索结果的个数,TreeSet docs是排序的搜索结果,float maxDistance搜索结果中的最大距离。

  1. protected float findSimilar(IndexReader reader, LireFeature lireFeature) throws IOException {
  2. maxDistance = -1f;
  3. overallMaxDistance = -1f;
  4. // clear result set ...
  5. docs.clear();
  6. // Needed for check whether the document is deleted.
  7. Bits liveDocs = MultiFields.getLiveDocs(reader);
  8. Document d;
  9. float tmpDistance;
  10. int docs = reader.numDocs();
  11. for (int i = 0; i < docs; i++) {
  12. if (reader.hasDeletions() && !liveDocs.get(i)) continue; // if it is deleted, just ignore it.
  13. d = reader.document(i);
  14. tmpDistance = getDistance(d, lireFeature);
  15. assert (tmpDistance >= 0);
  16. // calculate the overall max distance to normalize score afterwards
  17. if (overallMaxDistance < tmpDistance) {
  18. overallMaxDistance = tmpDistance;
  19. }
  20. // if it is the first document:
  21. if (maxDistance < 0) {
  22. maxDistance = tmpDistance;
  23. }
  24. // if the array is not full yet:
  25. if (this.docs.size() < maxHits) {
  26. this.docs.add(new SimpleResult(tmpDistance, d, i));
  27. if (tmpDistance > maxDistance) maxDistance = tmpDistance;
  28. } else if (tmpDistance < maxDistance) {
  29. // if it is nearer to the sample than at least on of the current set:
  30. // remove the last one ...
  31. this.docs.remove(this.docs.last());
  32. // add the new one ...
  33. this.docs.add(new SimpleResult(tmpDistance, d, i));
  34. // and set our new distance border ...
  35. maxDistance = this.docs.last().getDistance();
  36. }
  37. }
  38. return maxDistance;
  39. }

从它的findSimilar方法可以看出,它的实现是线性检索的,也就是从头到尾遍历所有文档,并且维护一个maxHits大小的TreeSet,TreeSet里面放的是距离最小的maxHits个搜索结果。如果有不理解此过程的童鞋,可以参考一下“TOP N搜索算法”。

  1. public ImageSearchHits search(BufferedImage image, IndexReader reader) throws IOException {
  2. logger.finer("Starting extraction.");
  3. LireFeature lireFeature = null;
  4. SimpleImageSearchHits searchHits = null;
  5. try {
  6. lireFeature = (LireFeature) descriptorClass.newInstance();
  7. // Scaling image is especially with the correlogram features very important!
  8. BufferedImage bimg = image;
  9. if (Math.max(image.getHeight(), image.getWidth()) > GenericDocumentBuilder.MAX_IMAGE_DIMENSION) {
  10. bimg = ImageUtils.scaleImage(image, GenericDocumentBuilder.MAX_IMAGE_DIMENSION);
  11. }
  12. lireFeature.extract(bimg);
  13. logger.fine("Extraction from image finished");
  14. float maxDistance = findSimilar(reader, lireFeature);
  15. searchHits = new SimpleImageSearchHits(this.docs, maxDistance);
  16. } catch (InstantiationException e) {
  17. logger.log(Level.SEVERE, "Error instantiating class for generic image searcher: " + e.getMessage());
  18. } catch (IllegalAccessException e) {
  19. logger.log(Level.SEVERE, "Error instantiating class for generic image searcher: " + e.getMessage());
  20. }
  21. return searchHits;
  22. }

search方法返回的是ImageSearchHits,它就是ArrayList results;并且利用findSimilar遍历时最大的distance做了个归一化操作, result.setDistance(1f - result.getDistance() / maxDistance);作用就是将距离变成了相似度(0到1),并且数值越大就越相似。

以上就是我粗略看的一些部分,可以看出lire的搜索过程其实是线性搜索的,由于具体的特征表示没来的及看,不知道它到底有没有利用lucene的倒排优势(对于高维数据还真不知道怎么利用倒排表)。对于大规模的数据速度估计够呛,好在lire的作者也意识到了这一点, http://www.semanticmetadata.net/2013/03/20/large-image-data-sets-with-lire-some-new-numbers/作者表示正在把LSH算法(Locality sensitive hashing)集成进去,LSH对于这种高维数据的相似检索速度可以说是质的飞跃。

自己做的一些实验,大概13万张图片,用的CEDD特征,索引文件只用了不到30M的大小,检索速度没测,目测1秒以内。

左上第一张图片就是输入图片。
1365476975_5633.jpg

作者:fengzhe0411 发表于2013-4-9 11:07:42 原文链接

发表评论

表情:
评论列表 (有 0 条评论,270人围观)

还没有评论,来说两句吧...

相关阅读

    相关 matlab检索相似图像

    在Matlab中检索相似图像通常需要使用图像处理和计算机视觉技术。以下是一种常见的方法,可以帮助您在Matlab中进行相似图像检索: 准备图像数据库: 首先,您需要有一个包含

    相关 相似图片搜索的原理

    最近在做一些东西,想到计算两幅图片的相似程度,在知乎上看到这篇文章,特转下来看。 [作者:阮一峰][Link 1] 上个月,Google把["相似图片搜索][Link

    相关 相似图片搜索算法介绍

    前言 之前对图片聚类有一丢丢的研究,最近发现,使用一些相似图片搜索算法也可以实现图片聚类的目标:将同类别或差不多的图片聚在一起。所以整理出相似图片搜索算法介绍这篇文章,主