画像の知識は0だけど、類似画像の検索をしたかったのでLireを使ってみた


ここで言ってる類似画像検索とは、以下のサイトなどでもある特定の画像と似た画像を検索するというやつですね。

Google Similar Images

GazoPa similar image search


画像についての知識は0なので、自分で1から作るのは時間がかかり過ぎるので、ライブラリを探すことにした。


で、少し調べたら Lireというのがヒットした。


Lireがどういう仕組みで動くとかは、こちらに書いてあるみたいだけど、私には理解不能ですw


興味のある方PDFなどの参考資料もあるようなので読み込んでみては?

http://www.semanticmetadata.net/wiki/doku.php?id=lire:lire#how_does_lire_actually_work


ライセンスは、「Gnu GPL license」のようです。


まず、ダウンロードは、以下のサイトからLire-0.8.zipを落としました。

http://sourceforge.net/projects/caliph-emir/files/
※この時点で2010/3/11が最終の更新みたい。


落としたzipファイルは解凍しておきます。


次にEclipseJavaプロジェクトを作成します。


で、lire.jarをビルドパスに追加します。
また、関連jarとして圧縮ファイルのlibフォルダに同梱されていた以下のjarもビルトパスに追加。

  • lucene-core-3.0.1.jar
  • Jama-1.0.2.jar
  • caliph-emir-cbir.jar


以上で準備は完了。


まず、類似画像を検索するために、検索対象となる画像のIndex(索引)を作ります。


コードは、wikiにサンプルが載っているのでほぼそのまま使います。

package sample;

import java.io.File;
import java.io.FileInputStream;

import net.semanticmetadata.lire.DocumentBuilder;
import net.semanticmetadata.lire.DocumentBuilderFactory;

import org.apache.lucene.analysis.SimpleAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.FSDirectory;

public class LireCreateIndex {

	private final static String TARGET_DIR = "C:\\Users\\Public\\Pictures\\Sample Pictures";

	private final static String INDEX_PATH = "E:\\lire\\index";

	public static void main(String[] args) {
		DocumentBuilder builder = DocumentBuilderFactory.getExtensiveDocumentBuilder();
		try {
			// Indexを場所のフォルダを指定し、IndexWriteをNEWする!!
			IndexWriter iw = null;
			iw = new IndexWriter(FSDirectory.open(new File(INDEX_PATH)), new SimpleAnalyzer(),
					true, IndexWriter.MaxFieldLength.UNLIMITED);

			// 検索対象とするファイルを置いてあるフォルダを指定し、その配下のファイルを対象にIndexを作る
			File dir = new File(TARGET_DIR);
			File[] files = dir.listFiles();
			for (File file : files) {
				Document doc = null;
				try {
					doc = builder.createDocument(new FileInputStream(file), file.getName());
					iw.addDocument(doc);
				} catch (Exception e) {
					// 画像読み込みエラーなど
					e.printStackTrace();
				}
			}
			iw.optimize();
			iw.close();
		} catch (Exception e) {
			// Indexファイル作成エラーなど
			e.printStackTrace();
			System.exit(0);
		}

	}
}


今回は面倒なので、Windowsのサンプルピクチャのフォルダ配下の画像を類似画像検索の対象とするようにしました。


Indexを作ったところで、いよいよ類似画像検索です。

package sample;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;

import javax.imageio.ImageIO;

import net.semanticmetadata.lire.DocumentBuilder;
import net.semanticmetadata.lire.ImageSearchHits;
import net.semanticmetadata.lire.ImageSearcher;
import net.semanticmetadata.lire.ImageSearcherFactory;

import org.apache.lucene.index.IndexReader;
import org.apache.lucene.store.FSDirectory;

public class LireSimilarSearch {

	private final static String INDEX_PATH = "E:\\lire\\index";

	public static void main(String[] args) {

		try {
			// 検索対象のIndexを読むReaderを作る
			IndexReader reader = IndexReader.open(FSDirectory.open(new File(INDEX_PATH)));
			// 画像を検索するためのサーチャーを作成
			// カラーだけのサーチャーとか色々あるみたいです。
			// あと、自分でどこに重みを置いて検索するかなども指定できるようです。
			// http://www.semanticmetadata.net/wiki/doku.php?id=lire:searchindex
			ImageSearcher searcher = ImageSearcherFactory.createDefaultSearcher();
			// ターゲットの画像を指定
			FileInputStream imageStream = new FileInputStream(
					"C:\\Users\\Public\\Pictures\\Sample Pictures\\sample.jpg");
			BufferedImage bimg = ImageIO.read(imageStream);
			ImageSearchHits hits = null;
			// 画像検索
			hits = searcher.search(bimg, reader);
			// 似ている画像トップファイルを5件をコンソールに出力
			for (int i = 0; i < 5; i++) {
				System.out
						.println(hits.score(i)
								+ ": "
								+ hits.doc(i).getField(DocumentBuilder.FIELD_NAME_IDENTIFIER)
										.stringValue());
			}

		} catch (Exception e) {
			// ファイル読み込みエラーなど
			e.printStackTrace();
		}
	}

}


以下、が出力結果ですね

スコア :ファイル名
0.5416657 : Koala.jpg
0.33018762 : Desert.jpg
0.29604518 : Lighthouse.jpg
0.2810576 : Tulips.jpg
0.2410211 : Hydrangeas.jpg


超簡単だね♪


画像の知識がない自分が1から作るのは大変だけど、とりあえず試すならLireで十分じゃないかなぁ。


色彩とか何に類似の重みを置くかなど自由に指定できるようなので、色々試したいな。