本片博客只是用于学习记录总结,欢迎大神指导
现实中实现图片比对方式有很多种,根据业务场景不同使用的技术也不同,本文是我工作中遇到的某场景下实现的方式,在此做个记录总结
一、直方图比较法
这个方法是开始网上随便找的一个方法,能实现当时的业务场景,但是比对出图片的相似度差异太小弃用了,暂时先付上代码
/** * 直方图 * * @param * @return */ public static int[] getData(BufferedImage img) { try { BufferedImage slt = new BufferedImage(img.getWidth(), img.getHeight(), BufferedImage.TYPE_INT_RGB); //slt.getGraphics().drawImage(img, 0, 0, img.getWidth(), img.getHeight(), 0,105,img.getWidth(),img.getHeight(),null); slt.getGraphics().drawImage(img, 0, 0, img.getWidth(), img.getHeight(), null); // ImageIO.write(slt,"jpeg",new File("slt.jpg")); int[] data = new int[256]; for (int x = 0; x < slt.getWidth(); x++) { for (int y = 0; y < slt.getHeight(); y++) { int rgb = slt.getRGB(x, y); Color myColor = new Color(rgb); int r = myColor.getRed(); int g = myColor.getGreen(); int b = myColor.getBlue(); data[(r + g + b) / 3]++; } } // data 就是所谓图形学当中的直方图的概念 return data; } catch (Exception exception) { return null; } }
二、指纹相似对比较法
public class ImageTools { /** * 图像指纹的尺寸,将图像缩放到指定的尺寸,来计算哈希数组 */ private static final int HASH_SIZE = 16; public 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); } /** * 二值化处理 * * @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; } } /** * 计算均值 * * @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 * @param width * @param height * @description width 和 height 分别指定了新创建的图像的宽度和高度。它们应该是整数,表示像素数。 * BufferedImage.TYPE_3BYTE_BGR 是一个常量,表示图像的像素格式。在这里,每个像素使用三个字节(BGR),也就是24位。 * @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 f1 * @param f2 * @return 返回相似度(0.0 ~ 1.0) */ public static float compare(byte[] f1, byte[] f2) { long start = System.currentTimeMillis(); 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; } } long end = System.currentTimeMillis() - start; return (float) sameCount / f1.length*100; } }
//传入图片,调用比对方法获取相似度
float percent = ImageTools.compare(ImageTools.hashValue(image1), image);
三、什么是哈希:
哈希(Hash)是一种常见的密码学技术,用于把任意长度的消息转换成固定长度的摘要信息,并确保任何对原始消息的修改都会导致不同的摘要信息。哈希技术在信息安全、数据完整性验证和数字签名等方面有广泛的应用。
直言:单向加密技术,将任意长度得原始消息转换成一个特定长度的哈希值,并且无法反推
四、哈希特点:
- 压缩性:无论输入消息的长度多长,产生的哈希值长度固定。
- 易计算性:计算哈希值的操作很容易,即使处理的数据量很大。
- 抗碰撞性:难以找到两个不同的输入消息,其哈希值相同,也称为“哈希冲突”。
五、什么是哈希算法:
简单得来说就是把任意输入通过特定得方式(hash函数)处理后生成一个值,这个值等同于存放数据得地址,这个地址里在把输入得数据进行存贮。散列算法(Hash Algorithm),又称哈希算法,杂凑算法,是一种从任意文件中创造小的数字「指纹」的方法。与指纹一样,散列算法 就是一种以较短的信息来保证文件唯一性的标志,这种标志与文件的每一个字节都相关,而且难以找到逆向规律。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)