|
|
@@ -0,0 +1,50 @@
|
|
|
+package com.mokasz.image_pool.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;
|
|
|
+
|
|
|
+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 * 8 + 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();
|
|
|
+ }
|
|
|
+}
|