Android实现图片相似度

最近公司有一个需求,就是希望能判断用户提交的照片是否是身份证的正面或者反面。可以通过预设一张拍摄清晰的身份证正面或者反面,来对比是否相似,那么问题就转化为如何计算两张图片相似度。找到一篇阮一峰老师当年的博客 很有启发,于是根据他说的每一步用Android里的方法来实现。

第一步,缩小尺寸。

将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。

Bitmap bitmap8 = ThumbnailUtils.extractThumbnail(bitmapOriginal, , );

第二步,简化色彩。

将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。

 public static Bitmap convertGreyImg(Bitmap img) {
int width = img.getWidth(); //获取位图的宽
int height = img.getHeight(); //获取位图的高 int[] pixels = new int[width * height]; //通过位图的大小创建像素点数组 img.getPixels(pixels, , width, , , width, height);
int alpha = 0xFF << ;
for (int i = ; i < height; i++) {
for (int j = ; j < width; j++) {
int original = pixels[width * i + j];
int red = ((original & 0x00FF0000) >> );
int green = ((original & 0x0000FF00) >> );
int blue = (original & 0x000000FF); int grey = (int) ((float) red * 0.3 + (float) green * 0.59 + (float) blue * 0.11);
grey = alpha | (grey << ) | (grey << ) | grey;
pixels[width * i + j] = grey;
}
}
Bitmap result = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
result.setPixels(pixels, , width, , , width, height);
return result;
}

第三步,计算平均值。

计算所有64个像素的灰度平均值。

    public static int getAvg(Bitmap img) {
int width = img.getWidth();
int height = img.getHeight();
int[] pixels = new int[width * height];
img.getPixels(pixels, , width, , , width, height); int avgPixel = ;
for (int pixel : pixels) {
avgPixel += pixel;
}
return avgPixel / pixels.length;
}

第四步,比较像素的灰度。

将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。

 public static String getBinary(Bitmap img, int average) {
StringBuilder sb = new StringBuilder(); int width = img.getWidth();
int height = img.getHeight();
int[] pixels = new int[width * height]; img.getPixels(pixels, , width, , , width, height);
for (int i = ; i < height; i++) {
for (int j = ; j < width; j++) {
int original = pixels[width * i + j];
if (original >= average) {
pixels[width * i + j] = ;
} else {
pixels[width * i + j] = ;
}
sb.append(pixels[width * i + j]);
}
}
return sb.toString();
}

第五步,计算哈希值。

将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。

下面是得到16位16进制的字符串,作为该图片的消息指纹

  public static String binaryString2hexString(String bString) {
if (bString == null || bString.equals("") || bString.length() % != )
return null;
StringBuilder sb = new StringBuilder();
int iTmp;
for (int i = ; i < bString.length(); i += ) {
iTmp = ;
for (int j = ; j < ; j++) {
iTmp += Integer.parseInt(bString.substring(i + j, i + j + )) << ( - j - );
}
sb.append(Integer.toHexString(iTmp));
}
return sb.toString

下面是两张图片的消息指纹比较的方法

 static void diff(String s1, String s2) {
char[] s1s = s1.toCharArray();
char[] s2s = s2.toCharArray();
int diffNum = ;
for (int i = ; i<s1s.length; i++) {
if (s1s[i] != s2s[i]) {
diffNum++;
}
}
System.out.println("diffNum="+diffNum);
}

至此关键代码都在这里了。


我拍照片试验了几次,以下是部分结果:

Str64->=81000081e9ff0000
Str64->=01800049e1ff0000
Str64->=10000d41ebff8000
Str64->=fdff47e80020231b
Str64->=ffffcfb80028031b
Str64->=ffff4fee0408031b
Str64->=040c7104000e7fff
Str64->=0b1b999f0300052f
Str64->=0b1b99c101400527

1、2、3行,4、5、6行,8、9行是大致同一个位置(手持手机,尽量保持同一个位置),第7行是其他位置,说明结果还是比较靠谱的,个人认为diff(s1, s2)方法

结果在1~5说明两张照片极其相似,6~10说明较为相似,10以上说明不相似

(相关代码在我的github上)

Android实现图片相似度的更多相关文章

  1. Android压缩图片到100K以下并保持不失真的高效方法

    前言:目前一般手机的相机都能达到800万像素,像我的Galaxy Nexus才500万像素,拍摄的照片也有1.5M左右.这么大的照片上传到服务器,不仅浪费流量,同时还浪费时间. 在开发Android企 ...

  2. 仿优酷Android客户端图片左右滑动(自动滑动)

    最终效果: 页面布局main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayou ...

  3. 用ticons指令结合ImageMagickDisplay工具批量生成Android适应图片

    用ticons指令结合ImageMagickDisplay工具批量生成Android适应图片 ticons的用法可以百度 这里记录下具体的编译方法 在安装了ticons和ImageMagickDisp ...

  4. Android 实现图片画画板

    本文主要讲述了Android 实现图片画画板 设计项目布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk ...

  5. 关于Android中图片大小、内存占用与drawable文件夹关系的研究与分析

    原文:关于Android中图片大小.内存占用与drawable文件夹关系的研究与分析 相关: Android drawable微技巧,你所不知道的drawable的那些细节 经常会有朋友问我这个问题: ...

  6. android 拉伸图片

    Android拉伸图片用的是9.png格式的图片,这种图片可以指定图片的那一部分拉伸,那一部分显示内容,美工给的小图片也能有很好的显示效果. 原背景图片 可以看到原背景图片很小,即使在再长的文字,背景 ...

  7. opencv学习笔记(六)直方图比较图片相似度

    opencv学习笔记(六)直方图比较图片相似度 opencv提供了API来比较图片的相似程度,使我们很简单的就能对2个图片进行比较,这就是直方图的比较,直方图英文是histogram, 原理就是就是将 ...

  8. Android大图片裁剪终极解决方案(上:原理分析)

    转载声明:Ryan的博客文章欢迎您的转载,但在转载的同时,请注明文章的来源出处,不胜感激! :-)  http://my.oschina.net/ryanhoo/blog/86842 约几个月前,我正 ...

  9. iOS,OC,图片相似度比较,图片指纹

    上周,正在忙,突然有个同学找我帮忙,说有个需求:图片相似度比较. 网上搜了一下,感觉不是很难,就写了下,这里分享给需要的小伙伴. 首先,本次采用的是OpenCV,图片哈希值: 先说一下基本思路: 1. ...

随机推荐

  1. smarty 3 + codeigniter 2 + hmvc

    参考资料 https://bitbucket.org/wiredesignz/codeigniter-modular-extensions-hmvc/src/fecd39ccdf56?at=defau ...

  2. UVa10082 没有通过

    #include<stdio.h> char s[]={"`1234567890-=QWERTYUIOP[]\ASDFGHJKL;'ZXCVBNM,./"},b[100 ...

  3. PhotoZoom Pro 7怎么进行参数设置

    每个用户在使用PhotoZoom时,在针对不同的图片,我们处理的方式也不同.所以在参数设置会因图片不同而不同.那么在PhotoZoom中参数究竟如何设置呢? 首先,我们先打开[参数设置],点击后会弹出 ...

  4. VS Code编写html(2)

    <html> <head> <title>welcome to myspace</title> <meta charset="utf-8 ...

  5. win7/win10 未分配磁盘怎样创建扩展分区 也就是逻辑分区(转截)

    我们有时候用windows7的磁盘管理工具对windows7系统分区管理的时候,我们可能会不小心把我们的电脑硬盘扩展分区都删除了,扩展分区变为了未分配的空间,这时候如果我们新建分区的话,建立的都是主分 ...

  6. 路飞学城Python-Day114

    120-基于用户认证组件的登陆验证信息存储 from django.shortcuts import render, HttpResponse, redirect from django.contri ...

  7. velocity.ui2.0所有的内置动画名称

    velocity升级到2.0后api发生了变化,按照原来的名称已经不能调用原来的动画效果,新的名称如下:velocity.ui2.0所有的内置动画名称 bounce flash headShake j ...

  8. `itchat`配置代理

    config.py配置 首先,先找到itchat安装的目录,然后定位到config.py文件: import os, platform VERSION = '1.3.10' BASE_URL = 'h ...

  9. 小白学习Spark系列三:RDD常用方法总结

    上一节简单介绍了Spark的基本原理以及如何调用spark进行打包一个独立应用,那么这节我们来学习下在spark中如何编程,同样先抛出以下几个问题. Spark支持的数据集,如何理解? Spark编程 ...

  10. 16种C语言编译警告(Warning)类型的解决方法

    当编译程序发现程序中某个地方有疑问,可能有问题时就会给出一个警告信息.警告信息可能意味着程序中隐含的大错误,也可能确实没有问题.对于警告的正确处理方式应该是:尽可能地消除之.对于编译程序给出的每个警告 ...