图像搜索(SIFT算法)组件

标签: 图像搜索 sift 算法 | 发表时间:2014-04-01 00:46 | 作者:mysh
出处:http://www.iteye.com


前阵子做图像搜索功能, 对比过一些搜索算法, 发现 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 - 研发管理

 

原理就不扯了, 网上找来一个老外的代码, 按需要改造了一下, 封装了一个组件, 方便使用.

组件地址:  https://github.com/myshzzx/mlib/tree/master/imagesearch

 

实际使用是这样的, 首先对图像进行预处理(比如缩小图像, 以减少无关的细节干扰), 然后对图像生成 SIFT 特征值. 图像搜索即是在大规模样本特征值里寻找与目标特征值最相近的特征值.

一般大小的图片可以计算出 10^2 ~ 10^3 数量级的特征值, 每个特征值是一个 float[128], 即一个 128 维浮点向量, 而图像搜索就是计算向量的欧氏距离, 找距离最小的样本向量, 这无疑是海量的计算. 一个比较好的做法是利用向量的空间信息构建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;
	}
}

 



已有 0 人发表留言,猛击->> 这里<<-参与讨论


ITeye推荐



相关 [图像搜索 sift 算法] 推荐:

图像搜索(SIFT算法)组件

- - 行业应用 - ITeye博客
前阵子做图像搜索功能, 对比过一些搜索算法, 发现 sift 比较能满足我的需要, 它在图像旋转, 比例缩放, 图像扭曲的情况下也能有很好的识别效果, 在网上找了一些资料, 有些介绍了算法的细节, 有些做了对比评测. 2013计算机视觉代码合集 - Note of Transposition - 博客频道 - CSDN.NET.

Olaworks 玩转增强现实 视觉及图像搜索

- - TechWeb 新酷网站 RSS阅读
  Olaworks 是一家韩国增强现实(AR)技术初创公司,于2006年由 Jung-hee Ryu 创立. 该公司凭借其革新性的技术,从Intel Capital、SKYLAKE Incuvest获得了400万美元的投资. 致力于研发计算机视觉和图像技术,其开发的技术可以使智能手机,平板电脑等设备上的摄像头实现多种功能,其中 就包括增强现实和图像识别.

以图搜索——互联网图像搜索引擎的“鸡肋”?

- - 博客 - 伯乐在线
[核心提示] 以图搜索这个目前几乎所有互联网图像搜索引擎都支持的功能为何用户不常用,甚至鲜为人知呢. 图像无疑是互联网上最重要的资源媒介,搜索引擎也无疑是互联网上最重要的资源获取渠道,顺理成章,当图像遇上了搜索引擎时,它们之间迅速萌生了产品化的火花. 目前几乎所有的主流互联网搜索引擎都提供搜索图像的功能(在此之前还有专门的垂直搜索引擎  Tineye, Picitup),最常用的形式是,通过用户输入关键字来检索相关图像.

缓存算法

- lostsnow - 小彰
没有人能说清哪种缓存算法由于其他的缓存算法. (以下的几种缓存算法,有的我也理解不好,如果感兴趣,你可以Google一下  ). 大家好,我是 LFU,我会计算为每个缓存对象计算他们被使用的频率. 我是LRU缓存算法,我把最近最少使用的缓存对象给踢走. 我总是需要去了解在什么时候,用了哪个缓存对象.

BFPRT算法

- zii - 小彰
BFPRT算法的作者是5位真正的大牛(Blum 、 Floyd 、 Pratt 、 Rivest 、 Tarjan),该算法入选了在StackExchange上进行的当今世界十大经典算法,而算法的简单和巧妙颇有我们需要借鉴学习之处. BFPRT解决的问题十分经典,即从某n个元素的序列中选出第k大(第k小)的元素,通过巧妙的分析,BFPRT可以保证在最坏情况下仍为线性时间复杂度.

贪心算法

- Shan - 博客园-首页原创精华区
顾名思义,贪心算法总是作出在当前看来最好的选择. 也就是说贪心算法并不从整体最优考虑,它所作出的选择只是在某种意义上的局部最优选择. 当然,希望贪心算法得到的最终结果也是整体最优的. 虽然贪心算法不能对所有问题都得到整体最优解,但对许多问题它能产生整体最优解. 如单源最短路经问题,最小生成树问题等.

缓存算法

- 成 - FeedzShare
来自: 小彰 - FeedzShare  . 发布时间:2011年09月25日,  已有 2 人推荐. 没有人能说清哪种缓存算法由于其他的缓存算法. (以下的几种缓存算法,有的我也理解不好,如果感兴趣,你可以Google一下  ). 大家好,我是 LFU,我会计算为每个缓存对象计算他们被使用的频率.

K-Means 算法

- - 酷壳 - CoolShell.cn
最近在学习一些数据挖掘的算法,看到了这个算法,也许这个算法对你来说很简单,但对我来说,我是一个初学者,我在网上翻看了很多资料,发现中文社区没有把这个问题讲得很全面很清楚的文章,所以,把我的学习笔记记录下来,分享给大家. k-Means 算法是一种  cluster analysis 的算法,其主要是来计算数据聚集的算法,主要通过不断地取离种子点最近均值的算法.

查找算法:

- - CSDN博客推荐文章
从数组的第一个元素开始查找,并将其与查找值比较,如果相等则停止,否则继续下一个元素查找,直到找到匹配值. 注意:要求被查找的数组中的元素是无序的、随机的. 比如,对一个整型数组的线性查找代码:. // 遍历整个数组,并分别将每个遍历元素与查找值对比. 要查找的值在数组的第一个位置. 也就是说只需比较一次就可达到目的,因此最佳情况的大O表达式为:O(1).

排序算法

- - 互联网 - ITeye博客
排序算法有很多,所以在特定情景中使用哪一种算法很重要. 为了选择合适的算法,可以按照建议的顺序考虑以下标准: .     对于数据量较小的情形,(1)(2)差别不大,主要考虑(3);而对于数据量大的,(1)为首要.  一、冒泡(Bubble)排序——相邻交换 .  二、选择排序——每次最小/大排在相应的位置 .