Android 以图找图功能

来源:互联网 发布:kali linux安装到u盘 编辑:程序博客网 时间:2024/06/05 00:17
     


      到2016年的最后一个月了,总得写点什么或者记录点什么。恩,就记录一下,我当时做以图找图,这个功能的过程和结果吧。以图找图简而言之就是确认小图是否属于大图的一部分。


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, width, height, null, false);  yuantuHashCode = BufproduceFingerPrint(jiequsource);  int difference = hammingDistance(mubiaoHashCode, yuantuHashCode);  if(difference == 0 ){  ImageUtils.savePhotoToSDCard(context, "找到", jiequsource);  SharedUtil.saveData(context, "Find", "x", String.valueOf(backX));  SharedUtil.saveData(context, "Find", "y", String.valueOf(j));//  LogInfo.ceshi("找到2:x="+ backX + "y=" + j);  isFind = true;  break;  }  else{//  LogInfo.ceshi("没找到2:x="+ backX + "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;  }

3.结束

  恩,这就是以图找图的所有代码=-=恩,是通过网上方法总结出来了的=-=就这样了。

  


    

0 0
原创粉丝点击