图像处理 -Java- 以图搜图
 作者:alexgaoyh
- 2024-03-12  河南
- 本文字数:2066 字 - 阅读完需:约 7 分钟 
背景
《图像处理-Java-以图搜图》,之前在编写过关于图像边缘检测-去黑边、图像边缘检测-自动纠偏、图像处理-锐化、图像处理-去噪/高斯模糊/套红、图像处理-背景色平滑/反色、图像处理-指定大小压缩、图像处理-Java-字深字浅等一系列文章,接下来主要介绍基于 opencv+lucene 的以图搜图功能。
概述
使用 JAVA 语言实现,实现思路是使用 opencv 获得图像的特征,之后将图像特征存入 lucene 后使用 KnnVectorQuery 进行搜索,从而达到以图搜图的效果。
实现步骤
- 引入 OpenCV 后获得图像特征; 
- 处理图像特征,包括归一化等操作; 
- 归一化后的图像特征存入 lucene 中; 
- 使用 KnnVectorQuery 进行相关搜索 
代码实现
        <dependency>            <groupId>org.opencv</groupId>            <artifactId>opencv-401</artifactId>            <version>401</version>            <scope>system</scope>            <systemPath>${pom.basedir}/libs/opencv-401.jar</systemPath>        </dependency>
        <dependency>            <groupId>org.apache.lucene</groupId>            <artifactId>lucene-core</artifactId>            <version>9.10.0</version>        </dependency>
复制代码
     /**     * 图像特征     *     * @param imagePath     * @return     */    public static byte[] matOfKeyPointImage(String imagePath) {        Mat image = Imgcodecs.imread(imagePath);
        // Convert image to grayscale        Mat grayImage = new Mat();        Imgproc.cvtColor(image, grayImage, Imgproc.COLOR_BGR2GRAY);
        // Initialize ORB detector        ORB detector = ORB.create();
        // Detect keypoints        MatOfKeyPoint keypoints = new MatOfKeyPoint();        detector.detect(grayImage, keypoints);
        // Compute descriptors        Mat descriptors = new Mat();        detector.compute(grayImage, keypoints, descriptors);
        // Convert descriptors to byte array        MatOfByte matOfByte = new MatOfByte();        descriptors.convertTo(matOfByte, CvType.CV_8U);
        // Convert MatOfByte to byte array        byte[] descriptorsData = new byte[(int) (matOfByte.total() * matOfByte.channels())];        matOfByte.get(0, 0, descriptorsData);
        return descriptorsData;    }
    @Test    public void testQuery() throws IOException {        // 第一个存储的向量,用来后续的搜索        float[] firstVector = null;
        try (MMapDirectory dir = new MMapDirectory(indexPath)) {            try (IndexWriter writer = new IndexWriter(dir, new IndexWriterConfig())) {                List<String> imageAbsPathList = new ArrayList<>();                imageAbsPathList.add("pap-1.jpg");                imageAbsPathList.add("pap-2.jpg");                imageAbsPathList.add("pap-3.jpg");                for(String imageAbsPath : imageAbsPathList) {                    byte[] bytes = OpenCVUtils.matOfKeyPointImage(imageAbsPath);                    // TODO 这里不合适,后续需要再次调整,由于lucene的限制,这里限制了特征向量的长度。 这里主要是把 byte[] -> float[], 并且只取前面1024个特征。                    float[] floats = OpenCVUtils.normalize(OpenCVUtils.convertArray(OpenCVUtils.byteArrayToFloatList(bytes), 1024));                    if(firstVector == null) {                        firstVector = floats;                    }                    Document doc = new Document();                    doc.add(new StoredField("id", imageAbsPath));                    doc.add(new KnnVectorField("field", floats));                    writer.addDocument(doc);                }            }            System.out.println();            try (IndexReader reader = DirectoryReader.open(dir)) {                IndexSearcher searcher = new IndexSearcher(reader);
                TopDocs results = searcher.search(new KnnVectorQuery("field", firstVector, 3), 10);                System.out.println("Hits: " + results.totalHits);                for (ScoreDoc sdoc : results.scoreDocs) {                    Document doc = reader.document(sdoc.doc);                    StoredField idField = (StoredField) doc.getField("id");                    System.out.println("Found: " + idField.toString() + " = " + String.format("%.1f", sdoc.score));                }            }        }
    }
复制代码
 参考
划线
评论
复制
发布于: 刚刚阅读数: 3
版权声明: 本文为 InfoQ 作者【alexgaoyh】的原创文章。
原文链接:【http://xie.infoq.cn/article/631d821a4f2aa7a6328a39b37】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。

alexgaoyh
关注
DevOps 2013-12-08 加入
https://gitee.com/alexgaoyh







 
    
评论