当前位置:
首页 >
Android 以图找图功能
发布时间:2023/12/15
60
豆豆
生活随笔
收集整理的这篇文章主要介绍了
Android 以图找图功能
小编觉得挺不错的,现在分享给大家,帮大家做个参考.
到2016年的最后一个月了,总得写点什么或者记录点什么。恩,就记录一下,我当时做以图找图,这个功能的过程和结果吧。以图找图简而言之就是确认小图是否属于大图的一部分。
这个方法不是百分百能找到的,也可能找到错误的图片,如果2个大图和小图的相似度很高的话。
1.序
刚开始做这个功能的时候,我一直在往误区上找,认为这是Android的项目,然后一直在找android方面的东西,也确实找到了,但这方面根本没有相关的DEMO(其实也是因为个人有点懒,有现成的,总是想直接用。)
然后想到了其实可以从java方面图片,这样就发现很多都是通过像素点进行查找的,但原理上是没错的就是查找的过程就有点慢了。在电脑上运行当然很快,但放在android上就很慢了,毕竟你需要对比每个像素点。
最后是通过计算哈希值的方法,来进行图片的查找。虽然也需要一块一块的查(就是根据原图片的大小,然后在目标图片上查找),然后得出结论是否是属于目标图片的。
2.代码
/** 小图是否属于大图* @param mubiao 目标图片(小图)地址* @param yuantu 源图片(大图)地址* @return* @throws IOException*/private static boolean FindImg(String mubiao, String yuantu) throws IOException{boolean isFind = false;Bitmap yuantusource = BitmapFactory.decodeFile(yuantu, null); Bitmap mubiaosource = BitmapFactory.decodeFile(mubiao, null); // huidu("yuantu" , yuantu); // huidu("mubiao" , mubiao);String mubiaoHashCode;String yuantuHashCode;Bitmap jiequsource;int width = yuantusource.getWidth();int height = yuantusource.getHeight();int Mwidth = mubiaosource.getWidth();int Mheight = mubiaosource.getHeight();mubiaoHashCode = BufproduceFingerPrint(mubiaosource);//通过循环来查找图片(就是从左上到右下)for(int i=0;i<width-Mwidth;i++){for(int j= 0;j<height-Mheight;j++){jiequsource = Bitmap.createBitmap(yuantusource, i, j, Mwidth, Mheight, null, false);yuantuHashCode = BufproduceFingerPrint(jiequsource);int difference = hammingDistance(mubiaoHashCode, yuantuHashCode);if(difference == 0 ){String.valueOf(j)); // LogInfo.ceshi("找到2:x="+ i + "y=" + j);isFind = true;break;} else{ // LogInfo.ceshi("没找到2:x="+ i + "y=" + j); // ToastUtil.showToast(context, "正在查找中···");}} } if(isFind){return true;}else{return false;}}/*** 处理图片* @param source* @return*/public static String BufproduceFingerPrint(Bitmap source) { // BufferedImage source = ImageHelper.readPNGImage(filename);// 读取文件int width = 8;int height = 8;int pixelColor;// 第一步,缩小尺寸。// 将图片缩小到8x8的尺寸,总共64个像素。这一步的作用是去除图片的细节,只保留结构、明暗等基本信息,摒弃不同尺寸、比例带来的图片差异。Bitmap thumb = ImageHelper.zoomImage(source, width,height);// 第二步,简化色彩。// 将缩小后的图片,转为64级灰度。也就是说,所有像素点总共只有64种颜色。int[] pixels = new int[width * height];for (int i = 0; i < width; i++) {for (int j = 0; j < height; j++) { // System.out.println("i=" + i +";y=" + j); // pixelColor = thumb.getPixel(i, j); // R = Color.red(pixelColor); // G = Color.green(pixelColor); // B = Color.blue(pixelColor);pixels[i * height + j] = ImageHelper.rgbToGray(thumb.getPixel(i, j));}}// 第三步,计算平均值。// 计算所有64个像素的灰度平均值。int avgPixel = ImageHelper.average(pixels);// 第四步,比较像素的灰度。// 将每个像素的灰度,与平均值进行比较。大于或等于平均值,记为1;小于平均值,记为0。int[] comps = new int[width * height];for (int i = 0; i < comps.length; i++) {if (pixels[i] >= avgPixel) {comps[i] = 1;} else {comps[i] = 0;}}// 第五步,计算哈希值。// 将上一步的比较结果,组合在一起,就构成了一个64位的整数,这就是这张图片的指纹。组合的次序并不重要,只要保证所有图片都采用同样次序就行了。StringBuffer hashCode = new StringBuffer();for (int i = 0; i < comps.length; i += 4) {int result = comps[i] * (int) Math.pow(2, 3) + comps[i + 1]* (int) Math.pow(2, 2) + comps[i + 2] * (int) Math.pow(2, 1)+ comps[i + 2];hashCode.append(binaryToHex(result));}// 得到指纹以后,就可以对比不同的图片,看看64位中有多少位是不一样的。return hashCode.toString();}private static char binaryToHex(int binary) {char ch = ' ';switch (binary) {case 0:ch = '0';break;case 1:ch = '1';break;case 2:ch = '2';break;case 3:ch = '3';break;case 4:ch = '4';break;case 5:ch = '5';break;case 6:ch = '6';break;case 7:ch = '7';break;case 8:ch = '8';break;case 9:ch = '9';break;case 10:ch = 'a';break;case 11:ch = 'b';break;case 12:ch = 'c';break;case 13:ch = 'd';break;case 14:ch = 'e';break;case 15:ch = 'f';break;default:ch = ' ';}return ch;}/*** 2个是否相同,0为相同* @param sourceHashCode* @param hashCode* @return*/public static int hammingDistance(String sourceHashCode, String hashCode) {int difference = 0;int len = sourceHashCode.length();for (int i = 0; i < len; i++) {if (sourceHashCode.charAt(i) != hashCode.charAt(i)) {difference++;}}return difference;}
import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream;import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.BitmapFactory; import android.graphics.Matrix;public class ImageHelper {public static Bitmap zoomImage(Bitmap bgimage, double newWidth, double newHeight) { // 获取这个图片的宽和高 float width = bgimage.getWidth(); float height = bgimage.getHeight(); // 创建操作图片用的matrix对象 Matrix matrix = new Matrix(); // 计算宽高缩放率 float scaleWidth = ((float) newWidth) / width; float scaleHeight = ((float) newHeight) / height; // 缩放图片动作 matrix.postScale(scaleWidth, scaleHeight); Bitmap bitmap = Bitmap.createBitmap(bgimage, 0, 0, (int) width, (int) height, matrix, true); return bitmap; } private Bitmap compressImage(Bitmap image) { ByteArrayOutputStream baos = new ByteArrayOutputStream(); image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中 int options = 100; while ( baos.toByteArray().length / 1024>100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩 baos.reset();//重置baos即清空baos image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中 options -= 10;//每次都减少10 } ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中 Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片 return bitmap; } public static int rgbToGray(int pixels) {// int _alpha = (pixels >> 24) & 0xFF;int _red = (pixels >> 16) & 0xFF;int _green = (pixels >> 8) & 0xFF;int _blue = (pixels) & 0xFF;return (int) (0.3 * _red + 0.59 * _green + 0.11 * _blue);}//// public static int average(int[] pixels) {float m = 0;for (int i = 0; i < pixels.length; ++i) {m += pixels[i];}m = m / pixels.length;return (int) m;} }
3.结束
恩,这就是以图找图的所有代码=-=恩,是通过网上方法总结出来了的=-=就这样了。
总结
以上是生活随笔为你收集整理的Android 以图找图功能的全部内容,希望文章能够帮你解决所遇到的问题。
- 上一篇: idea紫色主题+背景图配置
- 下一篇: 关于Android中Button的Bac