Android 以图找图功能
生活随笔
收集整理的這篇文章主要介紹了
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紫色主题+背景图配置
- 下一篇: 【网络知识】千兆网传输速度125MB/s