package com.mokasz.image_pool.restful.controller; import com.mokasz.image_pool.algorithm.FeatureExtractor; import com.mokasz.image_pool.algorithm.OpenCvService; import com.mokasz.image_pool.restful.entity.ImageQueryResponse; import com.mokasz.image_pool.restful.entity.ImageSaveResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.sql.ResultSet; import java.util.List; @RestController @RequestMapping("/service/image") public class ImageController { private final Logger logger = LoggerFactory.getLogger(this.getClass()); private final OpenCvService service = new OpenCvService(); @Autowired private JdbcTemplate jdbcTemplate; @GetMapping("/") public ImageSaveResponse index() throws IOException { return new ImageSaveResponse("ok", 0); } @PostMapping("/store2") public ImageSaveResponse store2(@RequestParam("file") MultipartFile file) throws IOException { FeatureExtractor.compute(file.getBytes()); return new ImageSaveResponse("OK", 1L); } @PostMapping("/store") public ImageSaveResponse store( @RequestParam("file") MultipartFile file, @RequestParam("pool") int pool) throws IOException { logger.info("File size: {} Name: {}", file.getSize(), file.getOriginalFilename()); float[] floats = new float[8]; service.calculatePHash(file.getBytes(), floats); float[] binaries = new float[64]; service.transformBinaryArray(floats, binaries); logger.info("{}", binaries); String hash = service.getReadableHash(floats); int updated = jdbcTemplate.update( "INSERT INTO image_pool.image_hash VALUES (?, NOW(), ?) ON CONFLICT (hash) DO NOTHING", hash, binaries); logger.info("{}", updated); jdbcTemplate.update( "INSERT INTO image_pool.image_to_pool VALUES (?, ?, NOW()) ON CONFLICT (hash, pool_id) DO NOTHING", hash, pool); return new ImageSaveResponse(hash, 1L); } @PostMapping("/match") public List match( @RequestParam("file") MultipartFile file, @RequestParam("pool") int pool, @RequestParam(value = "max", defaultValue = "1") float max, @RequestParam(value = "min", defaultValue = "1") float min, @RequestParam(value = "limit", defaultValue = "10") int limit) throws IOException { float[] floats = new float[8]; service.calculatePHash(file.getBytes(), floats); float[] binaries = new float[64]; service.transformBinaryArray(floats, binaries); logger.info("{}", floats); List list = jdbcTemplate.query( "SELECT * FROM (SELECT hash, (64 - l2_distance(?::FLOAT2[], vector)) / 64 AS similarity FROM image_pool.image_hash WHERE hash IN (SELECT hash FROM image_pool.image_to_pool WHERE pool_id = ?) ORDER BY vector <-> ?::FLOAT2[] ASC) t WHERE similarity >=? and similarity<=? ORDER BY similarity DESC LIMIT ?", (ResultSet rs, int rowNum) -> new ImageQueryResponse(rs.getFloat("similarity"), rs.getString("hash")), binaries, pool, binaries, min, max, limit); return list; } }