package com.mokasz.pool.image.algorithm; import org.bytedeco.javacpp.Loader; import org.bytedeco.opencv.opencv_java; import org.opencv.core.Mat; import org.opencv.core.MatOfByte; import org.opencv.img_hash.PHash; import org.opencv.imgcodecs.Imgcodecs; import org.springframework.stereotype.Service; @Service public class OpenCvService { // 静态初始化 OpenCV static { Loader.load(opencv_java.class); } private final PHash pHash = PHash.create(); public static final int HashLength = 8; private static void transformMatToArrayOfFloat(Mat mat, float[] floats) { if (mat.width() != HashLength || mat.height() != 1) { throw new RuntimeException("Matrix dimension is not 1x8"); } for (int i = 0; i < HashLength; i++) { floats[i] = (float) mat.get(0, i)[0]; } } public void calculatePHash(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); } public void transformBinaryArray(float[] octets, float[] binaries) { for (int i = 0; i < HashLength; i++) { for (int j = 0; j < HashLength; j++) { int v = (int) octets[i]; binaries[i * HashLength + j] = (v & (1 << j)) >> j; } } } public String getReadableHash(float[] floats) { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < HashLength; i++) { stringBuilder.append(String.format("%02X", (int) floats[i])); } return stringBuilder.toString(); } }