Java基于相似算法实现以图搜图

news2024/12/29 10:27:27

一、简述

  本文主要讲如何利用图片相似性算法,基于LIRE来实现图片搜索。

二、依赖

   <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-core -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-core</artifactId>
            <version>6.3.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-queryparser -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-queryparser</artifactId>
            <version>6.3.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.lucene/lucene-analyzers-common -->
        <dependency>
            <groupId>org.apache.lucene</groupId>
            <artifactId>lucene-analyzers-common</artifactId>
            <version>6.3.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-math3 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-math3</artifactId>
            <version>3.6.1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.sangupta/jopensurf -->
        <dependency>
            <groupId>com.sangupta</groupId>
            <artifactId>jopensurf</artifactId>
            <version>1.0.0</version>
        </dependency>
    </dependencies>

二、样例1

  Data目录下存放所有图片的样本。

package com.dearcloud.imagesearch;

import net.semanticmetadata.lire.aggregators.AbstractAggregator;
import net.semanticmetadata.lire.aggregators.BOVW;
import net.semanticmetadata.lire.builders.DocumentBuilder;
import net.semanticmetadata.lire.imageanalysis.features.global.CEDD;
import net.semanticmetadata.lire.imageanalysis.features.local.opencvfeatures.CvSurfExtractor;
import net.semanticmetadata.lire.imageanalysis.features.local.simple.SimpleExtractor;
import net.semanticmetadata.lire.indexers.parallel.ParallelIndexer;
import net.semanticmetadata.lire.searchers.GenericFastImageSearcher;
import net.semanticmetadata.lire.searchers.ImageSearchHits;
import net.semanticmetadata.lire.searchers.ImageSearcher;
import net.semanticmetadata.lire.utils.FileUtils;
import net.semanticmetadata.lire.utils.ImageUtils;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.store.FSDirectory;

import javax.imageio.ImageIO;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

public class IndexingAndSearchWithLocalFeatures {
    public static void main(String[] args) throws IOException {
        String indexPath = "D:\\以图搜图\\衬衣\\index";
        String imageData = "D:\\以图搜图\\衬衣\\Data";
        indexer(indexPath, imageData);

        String searchImage = "D:\\以图搜图\\衬衣\\search\\timg.jpg";
        String searchOutputFolder = "D:\\以图搜图\\衬衣\\output";
        search(indexPath, searchImage, searchOutputFolder);
    }

    /**
     * Indexing data using OpenCV and SURF as well as CEDD and SIMPLE.
     * @param indexFolder
     * @param imageDirectory
     */
    private static void indexer(String indexFolder, String imageDirectory) {
        // Checking if arg[0] is there and if it is a directory.
        boolean passed = false;
        // use ParallelIndexer to index all photos from args[0] into "index".
        int numOfDocsForVocabulary = 500;
        Class<? extends AbstractAggregator> aggregator = BOVW.class;
        int[] numOfClusters = new int[]{128};
        ParallelIndexer indexer = new ParallelIndexer(DocumentBuilder.NUM_OF_THREADS, indexFolder, imageDirectory, numOfClusters, numOfDocsForVocabulary, aggregator);
        indexer.setImagePreprocessor(image -> ImageUtils.createWorkingCopy(image));
        //Local
        indexer.addExtractor(CvSurfExtractor.class);
        //Simple
        indexer.addExtractor(CEDD.class, SimpleExtractor.KeypointDetector.CVSURF);

        indexer.run();
        System.out.println("Finished indexing.");
    }

    /**
     * Linear search on the indexed data.
     * @param indexPath
     * @throws IOException
     */
    public static void search(String indexPath, String searchFile, String searchOutputFolder) throws IOException {
        IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(indexPath)));

        // make sure that this matches what you used for indexing (see below) ...
        ImageSearcher imgSearcher = new GenericFastImageSearcher(1000, CEDD.class, SimpleExtractor.KeypointDetector.CVSURF, new BOVW(), 128, true, reader, indexPath + ".config");
        // just a static example with a given image.
        ImageSearchHits hits = imgSearcher.search(ImageIO.read(new File(searchFile)), reader);

        for (int i = 0; i < hits.length(); i++) {
            double score = hits.score(i);
            String imagePath = reader.document(hits.documentID(i)).getValues(DocumentBuilder.FIELD_NAME_IDENTIFIER)[0];
            System.out.printf("%.2f: (%d) %s\n", score, hits.documentID(i), imagePath);
        }
        String outputHtmlReport = FileUtils.saveImageResultsToHtml("search-", hits, searchFile, reader);
        System.out.println("Report:" + outputHtmlReport);
        org.apache.commons.io.FileUtils.copyFile(org.apache.commons.io.FileUtils.getFile(outputHtmlReport), org.apache.commons.io.FileUtils.getFile(searchOutputFolder, outputHtmlReport));
    }

}

三、样例2

  1、Indexer

package com.dearcloud.imagesearch;

import net.semanticmetadata.lire.builders.GlobalDocumentBuilder;
import net.semanticmetadata.lire.imageanalysis.features.global.AutoColorCorrelogram;
import net.semanticmetadata.lire.imageanalysis.features.global.CEDD;
import net.semanticmetadata.lire.imageanalysis.features.global.FCTH;
import net.semanticmetadata.lire.utils.FileUtils;
import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;

public class LireIndexer {
    public static void main(String[] args) throws IOException {
        String indexPath = "D:\\以图搜图\\全部\\index";
        String imageData = "D:\\以图搜图\\全部\\Data";
        index(indexPath, imageData);
    }

    private static void index(String indexFolder, String imageDirectory) throws IOException {
        // Getting all images from a directory and its sub directories.
        ArrayList<String> images = FileUtils.getAllImages(new File(imageDirectory), true);

        // Creating a CEDD document builder and indexing all files.
        GlobalDocumentBuilder globalDocumentBuilder = new GlobalDocumentBuilder(false, false);
        /*
            If you want to use DocValues, which makes linear search much faster, then use.
            However, you then have to use a specific searcher!
         */
        // GlobalDocumentBuilder globalDocumentBuilder = new GlobalDocumentBuilder(false, true);

        /*
            Then add those features we want to extract in a single run:
         */
        globalDocumentBuilder.addExtractor(CEDD.class);
        globalDocumentBuilder.addExtractor(FCTH.class);
        globalDocumentBuilder.addExtractor(AutoColorCorrelogram.class);

        // Creating an Lucene IndexWriter
        IndexWriterConfig conf = new IndexWriterConfig(new WhitespaceAnalyzer());
        IndexWriter iw = new IndexWriter(FSDirectory.open(Paths.get(indexFolder)), conf);
        // Iterating through images building the low level features
        for (Iterator<String> it = images.iterator(); it.hasNext(); ) {
            String imageFilePath = it.next();
            System.out.println("Indexing " + imageFilePath);
            try {
                BufferedImage img = ImageIO.read(new FileInputStream(imageFilePath));
                if (img == null) continue;
                Document document = globalDocumentBuilder.createDocument(img, imageFilePath);
                iw.addDocument(document);
            } catch (Exception e) {
                System.err.println("Error reading image or indexing it.");
                e.printStackTrace();
            }
        }
        // closing the IndexWriter
        iw.close();
        System.out.println("Finished indexing.");
    }
}

  2、Searcher

package com.dearcloud.imagesearch;

import net.semanticmetadata.lire.builders.DocumentBuilder;
import net.semanticmetadata.lire.imageanalysis.features.global.CEDD;
import net.semanticmetadata.lire.searchers.GenericFastImageSearcher;
import net.semanticmetadata.lire.searchers.ImageSearchHits;
import net.semanticmetadata.lire.searchers.ImageSearcher;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.store.FSDirectory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Paths;

public class LireSearcher {
    public static void main(String[] args) throws IOException {
        String indexPath = "D:\\以图搜图\\全部\\index";
        String searchImage = "D:\\以图搜图\\全部\\search\\timg.jpg";
        String searchOutputFolder = "D:\\以图搜图\\全部\\output";
        search(indexPath, searchImage, searchOutputFolder);
    }

    private static void search(String indexFolder, String searchFile, String searchOutputFolder) throws IOException {
        BufferedImage img = ImageIO.read(FileUtils.getFile(searchFile));

        IndexReader reader = DirectoryReader.open(FSDirectory.open(Paths.get(indexFolder)));
        ImageSearcher searcher = new GenericFastImageSearcher(30, CEDD.class);
        // ImageSearcher searcher = new GenericFastImageSearcher(30, AutoColorCorrelogram.class); // for another image descriptor ...

        /*
            If you used DocValues while Indexing, use the following searcher:
         */
        // ImageSearcher searcher = new GenericDocValuesImageSearcher(30, CEDD.class, ir);
        // searching with a image file ...
        ImageSearchHits hits = searcher.search(img, reader);
        // searching with a Lucene document instance ...
        // ImageSearchHits hits = searcher.search(ir.document(0), ir);
        for (int i = 0; i < hits.length(); i++) {
            String fileName = reader.document(hits.documentID(i)).getValues(DocumentBuilder.FIELD_NAME_IDENTIFIER)[0];
            System.out.println(hits.score(i) + ": \t" + fileName);
        }
        String outputHtmlReport = net.semanticmetadata.lire.utils.FileUtils.saveImageResultsToHtml("search-", hits, searchFile, reader);
        System.out.println("Report:" + outputHtmlReport);
        org.apache.commons.io.FileUtils.copyFile(org.apache.commons.io.FileUtils.getFile(outputHtmlReport), org.apache.commons.io.FileUtils.getFile(searchOutputFolder, outputHtmlReport));
    }
}

四、素材

   

    

  

五、LIRE支持的算法

  

  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2170048.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Apache Solr:深入探索与常见误区解析

Apache Solr&#xff1a;深入探索与常见误区解析 Apache Solr 是一个强大的搜索引擎&#xff0c;基于 Lucene 构建&#xff0c;广泛应用于电商平台、日志分析、内容管理系统等领域。Solr 的功能强大&#xff0c;然而它的配置和使用过程却不乏一些容易误解和出错的地方。本文将…

Spring validation校验框架

第1步&#xff1a;导入依赖 <!-- 校验框架--> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId> </dependency> 第2步&#xff1a;为需要校验的参数&…

Leetcode 739.42. 每日温度 接雨水 单调栈 C++实现

问题&#xff1a;Leetcode 739. 每日温度 算法1&#xff1a;从右到左 栈中记录下一个更大元素的「候选项」。 代码&#xff1a; class Solution { public:vector<int> dailyTemperatures(vector<int>& temperatures) {int n temperatures.size();vector<…

【echarts】报错series.render is required.

总结&#xff1a;就是echarts无法保存renderItem函数到json里&#xff0c;因为renderItem是个封装方法&#xff0c;因此需要初始化加载时重新插入renderItem即可 1.描述&#xff1a;控制台报错series.render is required. 原数据json如下&#xff1a; {type: "bar"…

【数学分析笔记】第3章第4节闭区间上的连续函数(2)

3. 函数极限与连续函数 3.4 闭区间上的连续函数 3.4.4 中间值定理 【定理3.4.4】若 f ( x ) f(x) f(x)在 [ a , b ] [a,b] [a,b]上连续&#xff0c;则它一定能取到最大值 M M M与最小值 m m m之间的任何一个值。 M max ⁡ f ( x ) , x ∈ [ a , b ] , m min ⁡ f ( x ) , …

Vmware 静态ip配置

虚拟机网络设置NAT 查看当前的网络接口 ip addr编辑网络接口配置文件 sudo vi /etc/sysconfig/network-scripts/ifcfg-<接口名>配置静态 IP 地址 Vmware ➡ 编辑 ➡ 虚拟网络编辑器 ➡ Nat设置 参考上图进行配置&#xff0c;千万不要配置宿主机的配置 BOOTPROTOstat…

2023_Spark_实验十一:RDD基础算子操作

一、RDD的练习可以使用两种方式 使用Shell使用IDEA 二、使用Shell练习RDD 当你打开 Spark 的交互式命令行界面&#xff08;也就是 Spark shell&#xff09;的时候&#xff0c;它已经自动为你准备好了一个叫做 sc 的特殊对象&#xff0c;这个对象是用来和 Spark 集群沟通的。你…

女性在网络安全行业崛起,引领行业新风向

1、网络安全自诞生之日起&#xff0c;就与女性有着不解之缘。 ●二战期间&#xff0c;美国雇佣了1万名女性作为“密码女孩”来破译日本人和德国人发送的密信。 ●英国同样雇用了7000多名女性在英国密码分析中心工作&#xff0c;约占全部工作人员的四分之三。 ●世界上的第一…

108.游戏安全项目:信息显示二-剑侠情缘基址分析

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;易道云信息技术研究院 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要盲目相信…

spring-boot web + vue

依赖的软件 maven 1. 官网下载zip 文件&#xff0c;比如apache-maven-3.9.9-bin.zip 2. 解压到某个盘符&#xff0c;必须保证父亲目录的名字包含英文&#xff0c;数字&#xff0c;破折号&#xff08;-&#xff09; 3. 设置环境变量M2_HOME, 并将%M2_HOME%\bin添加到windown…

openpnp - 散料飞达不要想着做万能版本,能够贴合现有的物料就好

文章目录 openpnp - 散料飞达不要想着做万能版本&#xff0c;能够贴合现有的物料就好概述笔记天真的版本改进的版本物料编带标准物料编带的样式对于散料飞达关心的尺寸不同编带宽度的散料飞达关键尺寸的列表8mm物料编带12mm物料编带16mm物料编带24mm物料编带32mm物料编带44mm物…

【Linux】环境变量(初步认识环境变量)

文章目录 1. 环境变量1.1 基本概念 2. 认识常见环境变量2.1 PATH2.2 HOME2.3 SHELL2.4 PWD2.5 USER 3. 理解环境变量 1. 环境变量 在main函数的命令行参数中&#xff0c;有argc、argv、env三个参数。 argc&#xff1a;命令函参数的个数argc&#xff1a;存放每个参数的具体数值…

FPGA学习(1)-mux2,2选1多路器

目录 1 开发板配套资料 1.1学习网址和资料网址 2.创建工程文件 2.1创建过程 2.2写程序及仿真测试 2.2.1 写程序生成电路 2.2.2仿真 2.2.3 生成执行文件并烧录 3.实验现象 买的小梅哥店铺的开发板&#xff1a;xc7z020clg400 看的小梅哥的视频&#xff1a;03C _基于ZYN…

提取出散射矩阵归一化相位的含义

散射矩阵的值是从图像中获得的&#xff0c;相位角是距离导致的&#xff0c;所以要归一化&#xff0c;VV/HH VV幅度/HH幅度。 VV相位-HH相位

Java-数据结构-Map与Set-(一) ٩(๑>◡<๑)۶

文本目录&#xff1a; ❄️一、搜索树&#xff1a; ☑ 1、概念&#xff1a; ☑ 2、操作-插入&#xff1a; 代码&#xff1a; ☑ 3、操作-查看&#xff1a; 代码&#xff1a; ☑ 4、操作-删除&#xff1a; 代码&#xff1a; ☑ 5、性能分析&#xff1a; ❄️二、搜索&#…

如何在Ubuntu上查看和刷新DNS缓存

DNS缓存是用于DNS查找的临时存储系统&#xff0c;负责将域名转换为IP地址。进行DNS查询时&#xff0c;系统会检查缓存中的相关信息。如果找到了&#xff0c;那么它会加速域名解析的过程。如果DNS缓存中的数据过时或不正确&#xff0c;则需刷新它以确保使用正确的信息。本文主要…

自己掏耳朵怎么弄干净?双十一必买的四大可视挖耳勺分享

我们在掏耳朵时是不是老是觉得要么掏不干净&#xff0c;要么太进去了弄到痛耳朵。因为耳道属于我们一个盲区&#xff0c;在使用棉签或者普通耳勺容易因为操作不当弄伤耳膜。可能还会照成不可逆的后果。所以自己在掏耳勺更加推荐大家使用可视挖耳勺会更加干净和安全。那么&#…

【MATLAB代码】二维环境下的RSSI定位程序,自适应锚点数量,带图像输出、坐标输出、中文注释

程序描述 MATLAB编写的RSSI定位程序&#xff0c;自适应锚点数量&#xff0c;带图像输出、坐标输出、中文注释。 功能概述&#xff1a; 本程序实现了在二维平面上通过接收信号强度指示&#xff08;RSSI&#xff09;进行定位的功能。它使用多个锚节点的信号强度测量来估计未知…

CSS链接

链接是网站的重要组成部分&#xff0c;几乎在每个网页上都能看到不少的链接&#xff0c;合理的设计链接的样式能够给网页的颜值加分。链接有四种不同的状态&#xff0c;分别是 link、visited、active 和 hover&#xff0c;可以通过以下伪类选择器来为链接的四种状态设置不同的样…

CentOS8使用chrony同步网络时间

文章目录 引言I CentOS8使用chrony网络时间同步安装chrony配置间同步服务器地址检查本机的时区设置时区chronyc命令II windows网络时间同步2.1 修改同步服务器2.2 修改同步频率引言 应用场景: 获取服务器时间进行船舶在线率统计 dtos.forEach(item -> {if(item.getDwtime(…