hWang-97

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理
  1 随笔 :: 0 文章 :: 0 评论 :: 1917 阅读

本片博客只是用于学习记录总结,欢迎大神指导

现实中实现图片比对方式有很多种,根据业务场景不同使用的技术也不同,本文是我工作中遇到的某场景下实现的方式,在此做个记录总结

一、直方图比较法

       这个方法是开始网上随便找的一个方法,能实现当时的业务场景,但是比对出图片的相似度差异太小弃用了,暂时先付上代码

复制代码
 /**
     * 直方图
     *
     * @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),又称哈希算法,杂凑算法,是一种从任意文件中创造小的数字「指纹」的方法。与指纹一样,散列算法    就是一种以较短的信息来保证文件唯一性的标志,这种标志与文件的每一个字节都相关,而且难以找到逆向规律。

 
复制代码

 

posted on   `hWang`  阅读(1917)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示