画像検索(SIFTアルゴリズム)コンポーネント

6971 ワード

この間、画像検索機能を作って、いくつかの検索アルゴリズムを比較したことがあって、siftが比較的に私の需要を満たすことができることを発見して、それは画像の回転、比例のスケール、画像のねじれの情況の下でもとても良い識別効果があって、ネット上でいくつかの資料を探して、いくつかアルゴリズムの細部を紹介して、いくつか比較評価をしました
www.cscjournals.org/csc/manuscript/Journals/IJIP/volume3/Issue4/IJIP-51.pdf
2013コンピュータビジュアルコード集合-Note of Transposition-ブログチャンネル-CSDN.NET
Computer Vision Algorithm Implementations
Fiji Is Just ImageJ
ImageAnalyzer | NeoTOS - Torben Schinke
Lire | SemanticMetadata.net
OpenSIFT: An Open-Source SIFT Library
SURFとSIFT-偽君-ブログ園
VLFeat(1)——SIFT画像特徴抽出(VC++実装)シズキ萌_新浪のブログ
特徴抽出ステップSIFT,PCA-SIFT,GLOH,SURF-研究開発管理
 
原理は引っ張らないで、ネット上で1つの外国人のコードを探して、必要に応じて改造して、1つのコンポーネントをパッケージして、使いやすいです.
コンポーネントアドレス:https://github.com/myshzzx/mlib/tree/master/imagesearch
 
実際に用いると、まず画像に対して前処理(例えば、画像を縮小して、関係のないディテール干渉を低減する)を行い、その後、画像に対してSIFT特徴値を生成する.画像検索とは、大規模なサンプルの特徴値の中で目標の特徴値に最も近い特徴値を探すことである.
一般的な大きさの画像は10^2~10^3の数桁の特徴値を計算することができ、各特徴値はfloat[128]、すなわち128次元浮動小数点ベクトルであり、画像検索はベクトルのオーステナイト距離を計算し、距離の最小のサンプルベクトルを探すことであり、これは間違いなく大量の計算である.1つの比較的良い方法は,ベクトルの空間情報を利用してk−dツリー,すなわちk次元ベクトルツリーを構築することであり,ここでk=128,検索時に空間情報を利用して可能性の高い分岐を優先的に検索し,検索時間T(n)=θ(log(n)). 
私はGPUで加速して検索を加速することを試みて、aparapiを使って、仕方なくそれは基本的なタイプの演算だけを支持して、Javaの対象を処理することができなくて、つまりk-d木は使えなくて、配列の組織の特徴値を使うことができて、GPUはオーステナイト距離の計算を処理して、計算の粒度が小さいため、データのインタラクション量は大きくて、このような方式でかえってCPUを使うより遅いかもしれません.
 
このコンポーネントは、サンプル画像の差が大きい場合に適している、各特徴値のマッチング検索で最も近いものしか見つからないため、サンプルライブラリにターゲット画像に近い画像が複数あると、最も近いものが見つかる、それに近い他の画像は「隠される」.このような場合、検索コードを変更する必要がある.
 
次に、その使い方を示すサンプルコードを貼ります.
public class SiftHelperTest {
	private static final Logger log = LoggerFactory.getLogger(SiftHelperTest.class);

	private static String[] dirs = new String[]{
					"E:\\project\\texture\\picsRep\\sample"
	};

	private static File resultDir = new File("l:/result");

	public static void main(String[] args) throws IOException, InterruptedException {
		SiftHelper.FeaMgrType feaMgrType = SiftHelper.FeaMgrType.KDTree;
		final SiftHelper<String> analyzer = new SiftHelper<>(String.class, feaMgrType);

		//       
		ImgPreProc samplePreProc = genImgPreProc(180);
		ImgPreProc testPreProc = genImgPreProc(150);

		analyzer.setImgPreProc(samplePreProc);
		analyzer.setMinMatchCount(2);

		//      
		final ExecutorService exec = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
		for (String dir : dirs)
			FileUtil.recurDir(new File(dir), null, new FileUtil.FileTask() {
				@Override
				public void handle(final File f) {
					exec.submit(() -> {
						try {
							analyzer.bindImage(f.getName(), ImageIO.read(f));
						} catch (Exception e) {
							e.printStackTrace();
						}
					});
				}
			});
		exec.shutdown();
		exec.awaitTermination(1, TimeUnit.DAYS);

		//       ,              ,                     /      .
		analyzer.getFeatureManager().setEachFeatureTimeout(3000);

		System.out.println("ready to search.");
		BufferedReader s = new BufferedReader(new InputStreamReader(System.in));
		String file;
		while ((file = s.readLine()) != null) {
			if ((file = file.trim()).length() < 1) continue;
			//     
			searchImg(analyzer, file, testPreProc, dirs[0], resultDir);
		}
	}


	static void searchImg(SiftHelper<String> analyzer, String file, ImgPreProc preProc, String sampleDir,
	                      File resultDir) {
		try {
			List<ImageFeature> features = preProc.process(ImageIO.read(new File(file)));

			List<ImageAnalyzerResult<String>> res = analyzer.findImage(features);

			System.out.println(file + " Results: " + res.size());
			int i = 1;

			if (resultDir.exists())
				for (File child : resultDir.listFiles())
					if (child.isFile()) child.delete();

			for (ImageAnalyzerResult<String> result : res) {
				System.out.println(result);

				if (resultDir.exists()) {
					String dir = sampleDir + "/" + result.getUserObj();
					Files.copy(Paths.get(dir), Paths.get(resultDir.getPath() + "/" + (i++) + " " + result.getUserObj()));
				}
			}
			System.out.println();
		} catch (Exception e) {
			log.error("searchImg failed: " + file, e);
		}

		System.gc();
	}


	static ImgPreProc genImgPreProc(int scaleLimit) {
		GrayScaleLimit preProc = new GrayScaleLimit();
		ImageFeatureExtractor sift = new JavaSIFT();
		preProc.setFe(sift);
		preProc.setScaleLimit(scaleLimit);
		return preProc;
	}
}