wudi 5 gadi atpakaļ
vecāks
revīzija
54a042dafc

+ 55 - 7
src/main/java/com/mokasz/image_pool/restful/controller/ImageController.java

@@ -12,6 +12,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestParam;
@@ -19,6 +20,9 @@ import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.io.IOException;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
 
 @RestController
 @RequestMapping("/service/image")
@@ -33,18 +37,62 @@ public class ImageController {
     @Autowired
     private JdbcTemplate jdbcTemplate;
 
+    private void calculate (byte[] fileBytes, float[] vector)
+    {
+        Mat input = Imgcodecs.imdecode(new MatOfByte(fileBytes), Imgcodecs.IMREAD_UNCHANGED);
+        Mat output = new Mat();
+        pHash.compute(input, output);
+        transformMatToArrayOfFloat(output, vector);
+    }
+
+    private void transformMatToArrayOfFloat (Mat mat, float[] floats) {
+        if (mat.width() != 8 || mat.height() != 1) throw new RuntimeException("Matrix dimension is not 1x8");
+        for (int i = 0; i < 8; i++) {
+            floats[i] = (float) mat.get(0, i)[0];
+        }
+    }
+
+    private void transformBinaryArray (float[] octets, float[] binaries) {
+        for (int i = 0; i < 8; i++) {
+            for (int j = 0; j < 8; j++) {
+                int v = (int) octets[i];
+                binaries[i * 8 + j] = (v & (1 << j)) >> j;
+            }
+        }
+    }
+
+    private String getReadableHash (float[] floats) {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (int i = 0; i < 8; i++) {
+            stringBuilder.append(String.format("%02X", (int) floats[i]));
+        }
+        return stringBuilder.toString();
+    }
+
     @PostMapping("/store")
     public ImageSaveResponse store (@RequestParam("file") MultipartFile file) throws IOException {
         logger.info("File size: {} Name: {}", file.getSize(), file.getOriginalFilename());
-        Mat input = Imgcodecs.imdecode(new MatOfByte(file.getBytes()), Imgcodecs.IMREAD_UNCHANGED);
-        Mat output = new Mat();
-        pHash.compute(input, output);
-        return new ImageSaveResponse(output.dump(), 1L);
+        float[] floats = new float[8];
+        calculate(file.getBytes(), floats);
+        float[] binaries = new float[64];
+        transformBinaryArray(floats, binaries);
+        logger.info("{}", binaries);
+        String hash = getReadableHash(floats);
+        int updated = jdbcTemplate.update("INSERT INTO image_pool.image_hash VALUES (?, NOW(), ?) ON CONFLICT (hash) DO NOTHING", hash, binaries);
+        logger.info("{}", updated);
+        return new ImageSaveResponse(hash, 1L);
     }
 
     @PostMapping("/match")
-    public ImageQueryResponse match (@RequestParam("pool") String pool) {
-        int updated = jdbcTemplate.update("INSERT INTO test_conn (name) VALUES (?)", pool);
-        return new ImageQueryResponse(updated, "Updated");
+    public List<ImageQueryResponse> match (@RequestParam("file") MultipartFile file, @RequestParam("pool") String pool) throws IOException {
+        logger.info("Not implemented pool: {}", pool);
+        float[] floats = new float[8];
+        calculate(file.getBytes(), floats);
+        float[] binaries = new float[64];
+        transformBinaryArray(floats, binaries);
+        logger.info("{}", floats);
+        List<ImageQueryResponse> list = jdbcTemplate.query("SELECT hash, l2_distance(?::FLOAT2[], vector) AS similarity FROM image_pool.image_hash ORDER BY vector <-> ?::FLOAT2[] DESC LIMIT 2",
+                (ResultSet rs, int rowNum) -> new ImageQueryResponse(rs.getFloat("similarity"), rs.getString("hash")), binaries, binaries);
+        return list;
     }
 }

+ 2 - 2
src/main/java/com/mokasz/image_pool/restful/entity/ImageQueryResponse.java

@@ -4,6 +4,6 @@ import lombok.Data;
 
 @Data
 public class ImageQueryResponse {
-    private final int retCode;
-    private final String message;
+    private final float similarity;
+    private final String hash;
 }