当前访客身份:游客 [ 登录  | 注册加入尚学堂]
启用新域名sxt.cn
新闻资讯

我用JAVA做了个简易图像相似度计算器

我来了! 发表于 2年前  | 评论(0 )| 阅读次数(792 )|   0 人收藏此文章,   我要收藏

简单说两句:

笔主利用这个七夕前后两天的寂寞时光,用JAVA磨了一个简单的图像相似度计算小程序,就在刚才终于纠结完毕,输出了1.0版本,小小的满足了一下可怜的虚荣心..→_→

原理是使用最简单最基础的感知哈希算法,算法原理戳这里,绝对比笔主讲的要好:

http://www.ruanyifeng.com/blog/2011/07/principle_of_similar_image_search.html

 

UI设计图:

 

实际运行效果图:

 

关键算法:

 
// 全流程
public static void main(String[] args) throws IOException {
    // 获取图像
    File imageFile = new File("c:/1.jpg");
    Image image = ImageIO.read(imageFile);
    // 转换至灰度
    image = toGrayscale(image);
    // 缩小成32x32的缩略图
    image = scale(image);
    // 获取灰度像素数组
    int[] pixels = getPixels(image);
    // 获取平均灰度颜色
    int averageColor = getAverageOfPixelArray(pixels);
    // 获取灰度像素的比较数组(即图像指纹序列)
    pixels = getPixelDeviateWeightsArray(pixels, averageColor);
    // 获取两个图的汉明距离(假设另一个图也已经按上面步骤得到灰度比较数组)
    int hammingDistance = getHammingDistance(pixels, pixels);
    // 通过汉明距离计算相似度,取值范围 [0.0, 1.0]
    double similarity = calSimilarity(hammingDistance);
}

// 将任意Image类型图像转换为BufferedImage类型,方便后续操作
public static BufferedImage convertToBufferedFrom(Image srcImage) {
    BufferedImage bufferedImage = new BufferedImage(srcImage.getWidth(null),
            srcImage.getHeight(null), BufferedImage.TYPE_INT_ARGB);
    Graphics2D g = bufferedImage.createGraphics();
    g.drawImage(srcImage, null, null);
    g.dispose();
    return bufferedImage;
}

// 转换至灰度图
public static BufferedImage toGrayscale(Image image) {
    BufferedImage sourceBuffered = convertToBufferedFrom(image);
    ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_GRAY);
    ColorConvertOp op = new ColorConvertOp(cs, null);
    BufferedImage grayBuffered = op.filter(sourceBuffered, null);
    return grayBuffered;
}

// 缩放至32x32像素缩略图
public static Image scale(Image image) {
    image = image.getScaledInstance(32, 32, Image.SCALE_SMOOTH);
    return image;
}

// 获取像素数组
public static int[] getPixels(Image image) {
    int width = image.getWidth(null);
    int height = image.getHeight(null);
    int[] pixels = convertToBufferedFrom(image).getRGB(0, 0, width, height,
            null, 0, width);
    return pixels;
}

// 获取灰度图的平均像素颜色值
public static int getAverageOfPixelArray(int[] pixels) {
    Color color;
    long sumRed = 0;
    for (int i = 0; i < pixels.length; i++) {
        color = new Color(pixels[i], true);
        sumRed += color.getRed();
    }
    int averageRed = (int) (sumRed / pixels.length);
    return averageRed;
}

// 获取灰度图的像素比较数组(平均值的离差)
public static int[] getPixelDeviateWeightsArray(int[] pixels,final int averageColor) {
    Color color;
    int[] dest = new int[pixels.length];
    for (int i = 0; i < pixels.length; i++) {
        color = new Color(pixels[i], true);
        dest[i] = color.getRed() - averageColor > 0 ? 1 : 0;
    }
    return dest;
}

// 获取两个缩略图的平均像素比较数组的汉明距离(距离越大差异越大)
public static int getHammingDistance(int[] a, int[] b) {
    int sum = 0;
    for (int i = 0; i < a.length; i++) {
        sum += a[i] == b[i] ? 0 : 1;
    }
    return sum;
}

// 通过汉明距离计算相似度
public static double calSimilarity(int hammingDistance){
    int length = 32*32;
    double similarity = (length - hammingDistance) / (double) length;

    // 使用指数曲线调整相似度结果
    similarity = java.lang.Math.pow(similarity, 2);
    return similarity;
}




UI部分的代码就不公开了,成品下载地址如下:

http://download.csdn.net/detail/u011088871/7710537

 

解压后打开 run.bat 批处理文件就可以跑起来了 :)

分享到:0
关注微信,跟着我们扩展技术视野。每天推送IT新技术文章,每周聚焦一门新技术。微信二维码如下:
微信公众账号:尚学堂(微信号:bjsxt-java)
声明:博客文章版权属于原创作者,受法律保护。如果侵犯了您的权利,请联系管理员,我们将及时删除!
(邮箱:webmaster#sxt.cn(#换为@))
北京总部地址:北京市海淀区西三旗桥东建材城西路85号神州科技园B座三层尚学堂 咨询电话:400-009-1906 010-56233821
Copyright 2007-2015 北京尚学堂科技有限公司 京ICP备13018289号-1 京公网安备11010802015183