From c76cbbefa26910c82dfd3585f8f999ee5784254b Mon Sep 17 00:00:00 2001 From: KKSU <15274802129@163.com> Date: Wed, 28 Aug 2024 10:16:48 +0800 Subject: [PATCH] 新增功能操作按钮,和更新了数据库数据 --- src/main/java/cc/mrbird/febs/mall/test/FingerPrint.java | 634 ++++++++++++++++++++++++++++---------------------------- 1 files changed, 317 insertions(+), 317 deletions(-) diff --git a/src/main/java/cc/mrbird/febs/mall/test/FingerPrint.java b/src/main/java/cc/mrbird/febs/mall/test/FingerPrint.java index 788a348..a73b2f8 100644 --- a/src/main/java/cc/mrbird/febs/mall/test/FingerPrint.java +++ b/src/main/java/cc/mrbird/febs/mall/test/FingerPrint.java @@ -1,317 +1,317 @@ -package cc.mrbird.febs.mall.test; - -import javax.imageio.ImageIO; -import java.awt.*; -import java.awt.color.ColorSpace; -import java.awt.image.BufferedImage; -import java.awt.image.ColorConvertOp; -import java.io.File; -import java.io.IOException; -import java.util.Arrays; - -/** - * 图片是采用phash算法,一共分为四步吧. - * - * 1.将图片缩放到16*16大小,这是我们选择的合适的大小,假如宽高不一样,直接将其压到16*16,去掉细节,只保留宏观; - * - * 2.图片一共是16*16的,共256个像素,我们将图片进行灰度化,灰度化就是只有黑白灰三种,从白到黑,一共分了255层; - * - * 3.灰度化之后将图片进行DCT转换(离散余弦变化),因为为了识别有的图片旋转,这个DCT转换是将图片进行了一种压缩算法; - * - * 4.我们对这个算法进行了优化,因为之前是计算像素的均值,我们为了更准确,我们取RGB,rgb一共分为255个像素,我们将255个像素分为16段,如果像素大于0-16记为0,17到32记为1,直到255,这样就得到255位的二进制,这就是这张图片的指纹码. - * - * 得到唯一标识的指纹码之后怎么去计算像素度呢? - * - * 通过汉明距离比较两个二进制距离,如果距离小于<10的话,我们就判定两张图片相似.如果两个指纹码(二进制)一模一样,我们就判定两个是一张图片,或者类似; - */ -/** - * 视频相似度算法: - * 视频的话我们是通过ffmpeg(ff am pig),它是一个专门处理视频的框架,可以从视频中按针提取图片.然后就按照图片的相似度取对比了... - */ - -/** - * https://blog.csdn.net/weixin_34095889/article/details/91923072?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171652008316800182787012%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=171652008316800182787012&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-91923072-null-null.142^v100^pc_search_result_base8&utm_term=java%20%E6%8A%8A%E5%9B%BE%E7%89%87%E8%BD%AC%E6%8D%A2%E6%88%90%E9%BB%91%E7%99%BD%E7%81%B0%E5%83%8F%E7%B4%A0%E9%A3%8E%E6%A0%BC&spm=1018.2226.3001.4187 - * 均值哈希实现图像指纹比较 - */ -public class FingerPrint { - - public static void main(String[] args) { - FingerPrint fp1 = null; - FingerPrint fp2 = null; - try { - fp1 = new FingerPrint(ImageIO.read(new File("D:\\image\\F1.png"))); - fp2 = new FingerPrint(ImageIO.read(new File("D:\\image\\Z1.jpg"))); - } catch (IOException e) { - e.printStackTrace(); - } - System.out.println(fp1.toString(false)); - System.out.println(fp2.toString(false)); - System.out.printf("sim=%f",fp1.compare(fp2)); - } - - /** - * 图像指纹的尺寸,将图像resize到指定的尺寸,来计算哈希数组 - */ - private static final int HASH_SIZE=16; - /** - * 保存图像指纹的二值化矩阵 - */ - private final byte[] binaryzationMatrix; - public FingerPrint(byte[] hashValue) { - if(hashValue.length!=HASH_SIZE*HASH_SIZE) - throw new IllegalArgumentException(String.format("length of hashValue must be %d",HASH_SIZE*HASH_SIZE )); - this.binaryzationMatrix=hashValue; - } - public FingerPrint(String hashValue) { - this(toBytes(hashValue)); - } - public FingerPrint (BufferedImage src){ - this(hashValue(src)); - } - private static byte[] hashValue(BufferedImage src){ - BufferedImage hashImage = resize(src,HASH_SIZE,HASH_SIZE); - byte[] matrixGray = (byte[]) toGray(hashImage).getData().getDataElements(0, 0, HASH_SIZE, HASH_SIZE, null); - return binaryzation(matrixGray); - } - /** - * 从压缩格式指纹创建{@link FingerPrint}对象 - * @param compactValue - * @return - */ - public static FingerPrint createFromCompact(byte[] compactValue){ - return new FingerPrint(uncompact(compactValue)); - } - - public static boolean validHashValue(byte[] hashValue){ - if(hashValue.length!=HASH_SIZE) - return false; - for(byte b:hashValue){ - if(0!=b&&1!=b)return false; - } - return true; - } - public static boolean validHashValue(String hashValue){ - if(hashValue.length()!=HASH_SIZE) - return false; - for(int i=0;i<hashValue.length();++i){ - if('0'!=hashValue.charAt(i)&&'1'!=hashValue.charAt(i))return false; - } - return true; - } - public byte[] compact(){ - return compact(binaryzationMatrix); - } - - /** - * 指纹数据按位压缩 - * @param hashValue - * @return - */ - private static byte[] compact(byte[] hashValue){ - byte[] result=new byte[(hashValue.length+7)>>3]; - byte b=0; - for(int i=0;i<hashValue.length;++i){ - if(0==(i&7)){ - b=0; - } - if(1==hashValue[i]){ - b|=1<<(i&7); - }else if(hashValue[i]!=0) - throw new IllegalArgumentException("invalid hashValue,every element must be 0 or 1"); - if(7==(i&7)||i==hashValue.length-1){ - result[i>>3]=b; - } - } - return result; - } - - /** - * 压缩格式的指纹解压缩 - * @param compactValue - * @return - */ - private static byte[] uncompact(byte[] compactValue){ - byte[] result=new byte[compactValue.length<<3]; - for(int i=0;i<result.length;++i){ - if((compactValue[i>>3]&(1<<(i&7)))==0) - result[i]=0; - else - result[i]=1; - } - return result; - } - /** - * 字符串类型的指纹数据转为字节数组 - * @param hashValue - * @return - */ - private static byte[] toBytes(String hashValue){ - hashValue=hashValue.replaceAll("\\s", ""); - byte[] result=new byte[hashValue.length()]; - for(int i=0;i<result.length;++i){ - char c = hashValue.charAt(i); - if('0'==c) - result[i]=0; - else if('1'==c) - result[i]=1; - else - throw new IllegalArgumentException("invalid hashValue String"); - } - return result; - } - /** - * 缩放图像到指定尺寸 - * @param src - * @param width - * @param height - * @return - */ - private static BufferedImage resize(Image src,int width,int height){ - BufferedImage result = new BufferedImage(width, height, - BufferedImage.TYPE_3BYTE_BGR); - Graphics g = result.getGraphics(); - try{ - g.drawImage(src.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); - }finally{ - g.dispose(); - } - return result; - } - /** - * 计算均值 - * @param src - * @return - */ - private static int mean(byte[] src){ - long sum=0; - // 将数组元素转为无符号整数 - for(byte b:src)sum+=(long)b&0xff; - return (int) (Math.round((float)sum/src.length)); - } - /** - * 二值化处理 - * @param src - * @return - */ - private static byte[] binaryzation(byte[]src){ - byte[] dst = src.clone(); - int mean=mean(src); - for(int i=0;i<dst.length;++i){ - // 将数组元素转为无符号整数再比较 - dst[i]=(byte) (((int)dst[i]&0xff)>=mean?1:0); - } - return dst; - - } - /** - * 转灰度图像 - * @param src - * @return - */ - private static BufferedImage toGray(BufferedImage src){ - if(src.getType()==BufferedImage.TYPE_BYTE_GRAY){ - return src; - }else{ - // 图像转灰 - BufferedImage grayImage = new BufferedImage(src.getWidth(), src.getHeight(), - BufferedImage.TYPE_BYTE_GRAY); - new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(src, grayImage); - return grayImage; - } - } - - @Override - public String toString() { - return toString(true); - } - /** - * @param multiLine 是否分行 - * @return - */ - public String toString(boolean multiLine) { - StringBuffer buffer=new StringBuffer(); - int count=0; - for(byte b:this.binaryzationMatrix){ - buffer.append(0==b?'0':'1'); - if(multiLine&&++count%HASH_SIZE==0) - buffer.append('\n'); - } - return buffer.toString(); - } - @Override - public boolean equals(Object obj) { - if(obj instanceof FingerPrint){ - return Arrays.equals(this.binaryzationMatrix,((FingerPrint)obj).binaryzationMatrix); - }else - return super.equals(obj); - } - - /** - * 与指定的压缩格式指纹比较相似度 - * @param compactValue - * @return - * @see #compare(FingerPrint) - */ - public float compareCompact(byte[] compactValue){ - return compare(createFromCompact(compactValue)); - } - /** - * @param hashValue - * @return - * @see #compare(FingerPrint) - */ - public float compare(String hashValue){ - return compare(new FingerPrint(hashValue)); - } - /** - * 与指定的指纹比较相似度 - * @param hashValue - * @return - * @see #compare(FingerPrint) - */ - public float compare(byte[] hashValue){ - return compare(new FingerPrint(hashValue)); - } - /** - * 与指定图像比较相似度 - * @param image2 - * @return - * @see #compare(FingerPrint) - */ - public float compare(BufferedImage image2){ - return compare(new FingerPrint(image2)); - } - /** - * 比较指纹相似度 - * @param src - * @return - * @see #compare(byte[], byte[]) - */ - public float compare(FingerPrint src){ - if(src.binaryzationMatrix.length!=this.binaryzationMatrix.length) - throw new IllegalArgumentException("length of hashValue is mismatch"); - return compare(binaryzationMatrix,src.binaryzationMatrix); - } - /** - * 判断两个数组相似度,数组长度必须一致否则抛出异常 - * @param f1 - * @param f2 - * @return 返回相似度(0.0~1.0) - */ - private static float compare(byte[] f1,byte[] f2){ - if(f1.length!=f2.length) - throw new IllegalArgumentException("mismatch FingerPrint length"); - int sameCount=0; - for(int i=0;i<f1.length;++i){ - if(f1[i]==f2[i])++sameCount; - } - return (float)sameCount/f1.length; - } - public static float compareCompact(byte[] f1,byte[] f2){ - return compare(uncompact(f1),uncompact(f2)); - } - public static float compare(BufferedImage image1,BufferedImage image2){ - return new FingerPrint(image1).compare(new FingerPrint(image2)); - } - -} +//package cc.mrbird.febs.mall.test; +// +//import javax.imageio.ImageIO; +//import java.awt.*; +//import java.awt.color.ColorSpace; +//import java.awt.image.BufferedImage; +//import java.awt.image.ColorConvertOp; +//import java.io.File; +//import java.io.IOException; +//import java.util.Arrays; +// +///** +// * 图片是采用phash算法,一共分为四步吧. +// * +// * 1.将图片缩放到16*16大小,这是我们选择的合适的大小,假如宽高不一样,直接将其压到16*16,去掉细节,只保留宏观; +// * +// * 2.图片一共是16*16的,共256个像素,我们将图片进行灰度化,灰度化就是只有黑白灰三种,从白到黑,一共分了255层; +// * +// * 3.灰度化之后将图片进行DCT转换(离散余弦变化),因为为了识别有的图片旋转,这个DCT转换是将图片进行了一种压缩算法; +// * +// * 4.我们对这个算法进行了优化,因为之前是计算像素的均值,我们为了更准确,我们取RGB,rgb一共分为255个像素,我们将255个像素分为16段,如果像素大于0-16记为0,17到32记为1,直到255,这样就得到255位的二进制,这就是这张图片的指纹码. +// * +// * 得到唯一标识的指纹码之后怎么去计算像素度呢? +// * +// * 通过汉明距离比较两个二进制距离,如果距离小于<10的话,我们就判定两张图片相似.如果两个指纹码(二进制)一模一样,我们就判定两个是一张图片,或者类似; +// */ +///** +// * 视频相似度算法: +// * 视频的话我们是通过ffmpeg(ff am pig),它是一个专门处理视频的框架,可以从视频中按针提取图片.然后就按照图片的相似度取对比了... +// */ +// +///** +// * https://blog.csdn.net/weixin_34095889/article/details/91923072?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522171652008316800182787012%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=171652008316800182787012&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~first_rank_ecpm_v1~rank_v31_ecpm-4-91923072-null-null.142^v100^pc_search_result_base8&utm_term=java%20%E6%8A%8A%E5%9B%BE%E7%89%87%E8%BD%AC%E6%8D%A2%E6%88%90%E9%BB%91%E7%99%BD%E7%81%B0%E5%83%8F%E7%B4%A0%E9%A3%8E%E6%A0%BC&spm=1018.2226.3001.4187 +// * 均值哈希实现图像指纹比较 +// */ +//public class FingerPrint { +// +// public static void main(String[] args) { +// FingerPrint fp1 = null; +// FingerPrint fp2 = null; +// try { +// fp1 = new FingerPrint(ImageIO.read(new File("D:\\image\\F1.png"))); +// fp2 = new FingerPrint(ImageIO.read(new File("D:\\image\\Z1.jpg"))); +// } catch (IOException e) { +// e.printStackTrace(); +// } +// System.out.println(fp1.toString(false)); +// System.out.println(fp2.toString(false)); +// System.out.printf("sim=%f",fp1.compare(fp2)); +// } +// +// /** +// * 图像指纹的尺寸,将图像resize到指定的尺寸,来计算哈希数组 +// */ +// private static final int HASH_SIZE=16; +// /** +// * 保存图像指纹的二值化矩阵 +// */ +// private final byte[] binaryzationMatrix; +// public FingerPrint(byte[] hashValue) { +// if(hashValue.length!=HASH_SIZE*HASH_SIZE) +// throw new IllegalArgumentException(String.format("length of hashValue must be %d",HASH_SIZE*HASH_SIZE )); +// this.binaryzationMatrix=hashValue; +// } +// public FingerPrint(String hashValue) { +// this(toBytes(hashValue)); +// } +// public FingerPrint (BufferedImage src){ +// this(hashValue(src)); +// } +// private static byte[] hashValue(BufferedImage src){ +// BufferedImage hashImage = resize(src,HASH_SIZE,HASH_SIZE); +// byte[] matrixGray = (byte[]) toGray(hashImage).getData().getDataElements(0, 0, HASH_SIZE, HASH_SIZE, null); +// return binaryzation(matrixGray); +// } +// /** +// * 从压缩格式指纹创建{@link FingerPrint}对象 +// * @param compactValue +// * @return +// */ +// public static FingerPrint createFromCompact(byte[] compactValue){ +// return new FingerPrint(uncompact(compactValue)); +// } +// +// public static boolean validHashValue(byte[] hashValue){ +// if(hashValue.length!=HASH_SIZE) +// return false; +// for(byte b:hashValue){ +// if(0!=b&&1!=b)return false; +// } +// return true; +// } +// public static boolean validHashValue(String hashValue){ +// if(hashValue.length()!=HASH_SIZE) +// return false; +// for(int i=0;i<hashValue.length();++i){ +// if('0'!=hashValue.charAt(i)&&'1'!=hashValue.charAt(i))return false; +// } +// return true; +// } +// public byte[] compact(){ +// return compact(binaryzationMatrix); +// } +// +// /** +// * 指纹数据按位压缩 +// * @param hashValue +// * @return +// */ +// private static byte[] compact(byte[] hashValue){ +// byte[] result=new byte[(hashValue.length+7)>>3]; +// byte b=0; +// for(int i=0;i<hashValue.length;++i){ +// if(0==(i&7)){ +// b=0; +// } +// if(1==hashValue[i]){ +// b|=1<<(i&7); +// }else if(hashValue[i]!=0) +// throw new IllegalArgumentException("invalid hashValue,every element must be 0 or 1"); +// if(7==(i&7)||i==hashValue.length-1){ +// result[i>>3]=b; +// } +// } +// return result; +// } +// +// /** +// * 压缩格式的指纹解压缩 +// * @param compactValue +// * @return +// */ +// private static byte[] uncompact(byte[] compactValue){ +// byte[] result=new byte[compactValue.length<<3]; +// for(int i=0;i<result.length;++i){ +// if((compactValue[i>>3]&(1<<(i&7)))==0) +// result[i]=0; +// else +// result[i]=1; +// } +// return result; +// } +// /** +// * 字符串类型的指纹数据转为字节数组 +// * @param hashValue +// * @return +// */ +// private static byte[] toBytes(String hashValue){ +// hashValue=hashValue.replaceAll("\\s", ""); +// byte[] result=new byte[hashValue.length()]; +// for(int i=0;i<result.length;++i){ +// char c = hashValue.charAt(i); +// if('0'==c) +// result[i]=0; +// else if('1'==c) +// result[i]=1; +// else +// throw new IllegalArgumentException("invalid hashValue String"); +// } +// return result; +// } +// /** +// * 缩放图像到指定尺寸 +// * @param src +// * @param width +// * @param height +// * @return +// */ +// private static BufferedImage resize(Image src,int width,int height){ +// BufferedImage result = new BufferedImage(width, height, +// BufferedImage.TYPE_3BYTE_BGR); +// Graphics g = result.getGraphics(); +// try{ +// g.drawImage(src.getScaledInstance(width, height, Image.SCALE_SMOOTH), 0, 0, null); +// }finally{ +// g.dispose(); +// } +// return result; +// } +// /** +// * 计算均值 +// * @param src +// * @return +// */ +// private static int mean(byte[] src){ +// long sum=0; +// // 将数组元素转为无符号整数 +// for(byte b:src)sum+=(long)b&0xff; +// return (int) (Math.round((float)sum/src.length)); +// } +// /** +// * 二值化处理 +// * @param src +// * @return +// */ +// private static byte[] binaryzation(byte[]src){ +// byte[] dst = src.clone(); +// int mean=mean(src); +// for(int i=0;i<dst.length;++i){ +// // 将数组元素转为无符号整数再比较 +// dst[i]=(byte) (((int)dst[i]&0xff)>=mean?1:0); +// } +// return dst; +// +// } +// /** +// * 转灰度图像 +// * @param src +// * @return +// */ +// private static BufferedImage toGray(BufferedImage src){ +// if(src.getType()==BufferedImage.TYPE_BYTE_GRAY){ +// return src; +// }else{ +// // 图像转灰 +// BufferedImage grayImage = new BufferedImage(src.getWidth(), src.getHeight(), +// BufferedImage.TYPE_BYTE_GRAY); +// new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null).filter(src, grayImage); +// return grayImage; +// } +// } +// +// @Override +// public String toString() { +// return toString(true); +// } +// /** +// * @param multiLine 是否分行 +// * @return +// */ +// public String toString(boolean multiLine) { +// StringBuffer buffer=new StringBuffer(); +// int count=0; +// for(byte b:this.binaryzationMatrix){ +// buffer.append(0==b?'0':'1'); +// if(multiLine&&++count%HASH_SIZE==0) +// buffer.append('\n'); +// } +// return buffer.toString(); +// } +// @Override +// public boolean equals(Object obj) { +// if(obj instanceof FingerPrint){ +// return Arrays.equals(this.binaryzationMatrix,((FingerPrint)obj).binaryzationMatrix); +// }else +// return super.equals(obj); +// } +// +// /** +// * 与指定的压缩格式指纹比较相似度 +// * @param compactValue +// * @return +// * @see #compare(FingerPrint) +// */ +// public float compareCompact(byte[] compactValue){ +// return compare(createFromCompact(compactValue)); +// } +// /** +// * @param hashValue +// * @return +// * @see #compare(FingerPrint) +// */ +// public float compare(String hashValue){ +// return compare(new FingerPrint(hashValue)); +// } +// /** +// * 与指定的指纹比较相似度 +// * @param hashValue +// * @return +// * @see #compare(FingerPrint) +// */ +// public float compare(byte[] hashValue){ +// return compare(new FingerPrint(hashValue)); +// } +// /** +// * 与指定图像比较相似度 +// * @param image2 +// * @return +// * @see #compare(FingerPrint) +// */ +// public float compare(BufferedImage image2){ +// return compare(new FingerPrint(image2)); +// } +// /** +// * 比较指纹相似度 +// * @param src +// * @return +// * @see #compare(byte[], byte[]) +// */ +// public float compare(FingerPrint src){ +// if(src.binaryzationMatrix.length!=this.binaryzationMatrix.length) +// throw new IllegalArgumentException("length of hashValue is mismatch"); +// return compare(binaryzationMatrix,src.binaryzationMatrix); +// } +// /** +// * 判断两个数组相似度,数组长度必须一致否则抛出异常 +// * @param f1 +// * @param f2 +// * @return 返回相似度(0.0~1.0) +// */ +// private static float compare(byte[] f1,byte[] f2){ +// if(f1.length!=f2.length) +// throw new IllegalArgumentException("mismatch FingerPrint length"); +// int sameCount=0; +// for(int i=0;i<f1.length;++i){ +// if(f1[i]==f2[i])++sameCount; +// } +// return (float)sameCount/f1.length; +// } +// public static float compareCompact(byte[] f1,byte[] f2){ +// return compare(uncompact(f1),uncompact(f2)); +// } +// public static float compare(BufferedImage image1,BufferedImage image2){ +// return new FingerPrint(image1).compare(new FingerPrint(image2)); +// } +// +//} -- Gitblit v1.9.1