解决Zxing解析本地图片二维码,识别率低,识别不出来的问题!

       (又做了一些优化,就是在原来的基础上添加上了zbar识别二维码的功能,就是先对图片进行处理,然后通过zxing识别,如果zxing识别失败,再通过zbar识别 20170329)

       最近项目里让添加本地图片扫描二维码的功能,本来已经加了扫一扫的功能,产品非得让加上本地图片扫码功能,我看了下搜狐和优酷,他们都是只有扫一扫,没有本地图片扫码,我就想着,产品让加就加吧。

在网上搜了搜,很快就搜到了一个demo,也很快就加到我的项目中了,截取了一张二维码的图片,识别出来了,OK,功能加好了,真开心。后来测试一测,说二维码功能没有添加,我就和他们理论,让他们过来复现,结果真的是识别不出来二维码,到底是啥原因啊,我就开始思考,因为他们是用手机拍得一张二维码图片,二维码在整个图片中占的比例很小,我那天自己测的时候,是整张图片基本上被二维码占完了,所以能扫描成功,接着就是解决问题。

一开始上网搜,zxing二维码本地图片识别不出来,识别率低,搜了半天搜出来一个把图片放大,比如放大一倍,这样就可以识别出来了,下面我把把图片放大的代码贴出来,

Bitmap scanBitmap;

     int sampleSize=(int)(options.outHeight/(float)200);
    options.inJustDecodeBounds=false;
    if(sampleSize<=0){
       options.inSampleSize=1;
       scanBitmap=BitmapFactory.decodeFile(path, options);
       Matrix matrix=new Matrix();
       matrix.postScale(1.5f,1.5f);
       scanBitmap=Bitmap.createBitmap(scanBitmap,0,0,scanBitmap.getWidth(),scanBitmap.getHeight(),matrix,true);
    }else{
       options.inSampleSize=sampleSize;
       scanBitmap=BitmapFactory.decodeFile(path,options);
    }
然而并没什么用,不仅没什么用,由于把图片放大了,还可能会造成outofmemory,然后就接着搜索,有人说用zbar,说它的图片二维码的识别率比zxing得高,我实在不想改,不过也没办法,就用zbar试了下,然而并没有什么用,这个时候,有点小崩溃,下班后回到家,就一直想到底是为什么呢,ios的就能识别出来,他们用的是他们系统自带的api来做的,难道是他们ios的扫一扫的apI里的算法比zxing和zbar的效率性能要好,肯定的了,不然为什么同样的图片他们的就能识别出二维码呢(猜得),接着继续想办法,然后就是回忆一下,自己手上的其他项目里有没有这些类似的功能参考下,想了一遍,也没有,但是有从相册中获取图片然后截取图片的功能,然后就又有思路了,对了,图片上的二维码识别不出,是因为二维码在整张图片中的占的比例太小,我能不能对这整张图片进行一下裁剪,把没用的多余的图片部分裁剪掉,接着就开始干,下面是对相册图片裁剪的代码:
 
  
public class ImageCropActivity extends BaseActivity {
   private static final int DEFAULT_ASPECT_RATIO_VALUES = 10;

   private CropImageView cropImageView;
   private String pre_path; 
   private boolean pre_flag;
   private int screen_width, screen_height;
   private TextView tv_ok, tv_canle;
   private int x;
   private int y;
   private TextView tv_crop;

   private RelativeLayout rl_layout;
   
@Override
protected void onCreate(Bundle savedInstanceState) {
   // TODO Auto-generated method stub
   super.onCreate(savedInstanceState);
   requestWindowFeature(Window.FEATURE_NO_TITLE);
   setContentView(R.layout.activity_image_crop);
   tv_ok = (TextView) findViewById(R.id.tv_ok);
   tv_canle = (TextView) findViewById(R.id.tv_canle);

   tv_ok.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View v) {
         // TODO Auto-generated method stub
         gotoNextStep();
      }
   });

   tv_canle.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View v) {

         finish();

      }
   });
   rl_layout = (RelativeLayout) findViewById(R.id.rl_image);
   tv_crop = (TextView) findViewById(R.id.tv_crop);
   tv_crop.setOnClickListener(new OnClickListener() {

      @Override
      public void onClick(View v) {
         int switchsize = switchsize();
         switch (switchsize) {
         case 0:
            x = y = 1;
            break;
         case 1:
            x = 4;
            y = 3;
            break;
         case 2:
            x = 3;
            y = 4;

            break;
         case 3:
            x = 674;
            y = 250;
            break;
         default:
            break;
         }
         cropImageView.setAspectRatio(x, y);
         tv_crop.setText(x + ":" + y);
      }
   });

   DisplayMetrics dm = new DisplayMetrics();
   getWindowManager().getDefaultDisplay().getMetrics(dm);
   screen_width = dm.widthPixels;
   screen_height = dm.heightPixels;
   cropImageView = (CropImageView) findViewById(R.id.CropImageView);

   Intent preIntent = this.getIntent();
   pre_path = preIntent.getStringExtra("path");
   pre_flag = preIntent.getBooleanExtra("flag", true);

   Bitmap bitmap = null;
   
      if (pre_path != null) {
         bitmap = BitmapUtil.getBitmapFromSDCard(pre_path);
      } else {
         bitmap = BitmapUtil.temp; 
      }

      

   
   if (bitmap != null) {
      bitmap = resizeSurfaceWithScreen(bitmap, screen_width, screen_height);
      int degree = readPictureDegree(pre_path);
      bitmap = rotaingImageView(degree, bitmap);
      cropImageView.setImageBitmap(bitmap);
   }
   if (pre_flag) {
      cropImageView.setAspectRatio(DEFAULT_ASPECT_RATIO_VALUES, DEFAULT_ASPECT_RATIO_VALUES);

   } else {
      cropImageView.setAspectRatio(1, 1);
      rl_layout.setVisibility(View.INVISIBLE);
   }
   
}
private int size_index = 0;

public int switchsize() {
   size_index++;
   if (size_index >= 3) {
      size_index = 0;
   }
   return size_index;
}


private Bitmap resizeSurfaceWithScreen(Bitmap bitmap, int screen_width, int screen_height) {

   int width = bitmap.getWidth();
   int height = bitmap.getHeight();


   if (width < screen_width && height < screen_height) {
      float scale_width = screen_width * 1.0f / width;
      float scale_height = screen_height * 1.0f / height;
      float scale = scale_width > scale_height ? scale_height : scale_width; 
      width *= scale;
      height *= scale;
   } else {
      if (width > screen_width) {
         height = height * screen_width / width;
         width = screen_width;
      }
      if (height > screen_height) {
         width = width * screen_height / height;
         height = screen_height;
      }
   }

   bitmap = Bitmap.createScaledBitmap(bitmap, width, height, false);

   bitmap = BitmapUtil.zoomBitmap(bitmap, width, height);

   ByteArrayOutputStream baos = new ByteArrayOutputStream();
   bitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
   while (baos.toByteArray().length > 1024 * 1024) {
      baos.reset();
      bitmap.compress(Bitmap.CompressFormat.JPEG, 50, baos);
   }

   ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
   Bitmap bitmap_new = BitmapFactory.decodeStream(isBm, null, null);

   return bitmap_new;

}

public String saveBitmap(Bitmap bm) {
   Long tolong = System.currentTimeMillis() / 1000;
   File f = new File(FileDownloadUtil.getDefaultLocalDir("/cntvScan/temp/"), tolong.toString());
   if (f.exists()) {
      f.delete();
   }
   try {
      FileOutputStream out = new FileOutputStream(f);
      bm.compress(Bitmap.CompressFormat.JPEG, 80, out);
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      while (baos.toByteArray().length > 1024 * 1024) {
         baos.reset();
         bm.compress(Bitmap.CompressFormat.JPEG, 50, out);
      }
      out.flush();
      out.close();
   } catch (FileNotFoundException e) {
      e.printStackTrace();
   } catch (IOException e) {
      e.printStackTrace();
   }
   return f.getAbsolutePath();
}

public void gotoNextStep() {

   try {
      Bitmap croppedImage = cropImageView.getCroppedImage();
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      croppedImage.compress(Bitmap.CompressFormat.JPEG, 80, baos);
      byte[] bitmapByte = baos.toByteArray();

      int width = croppedImage.getWidth();
      int heigth = croppedImage.getHeight();

      Intent data = new Intent();
      data.putExtra("bitmap", bitmapByte);
      data.putExtra("path", saveBitmap(croppedImage));
      data.putExtra("width", width);
      data.putExtra("heigth", heigth);
      setResult(20, data);
      finish();
   } catch (Exception e) {
      e.printStackTrace();
   }

}

/**
 * 
 * @param angle
 * @param bitmap
 * @return Bitmap
 */
public Bitmap rotaingImageView(int angle, Bitmap bitmap) {
   Matrix matrix = new Matrix();
   matrix.postRotate(angle);
   System.out.println("angle2=" + angle);
   Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
   return resizedBitmap;
}

public int readPictureDegree(String path) {
   int degree = 0;
   try {
      ExifInterface exifInterface = new ExifInterface(path);
      int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL);
      switch (orientation) {
      case ExifInterface.ORIENTATION_ROTATE_90:
         degree = 90;
         break;
      case ExifInterface.ORIENTATION_ROTATE_180:
         degree = 180;
         break;
      case ExifInterface.ORIENTATION_ROTATE_270:
         degree = 270;
         break;
      }
   } catch (IOException e) {
      e.printStackTrace();
   }
   return degree;
}
}
还有一些其他的工具类,比较多,我就不贴出来了,终于即使图片上二维码的占的比例比较低的图片,也能识别出来二维码了,如果不做这些处理,是识别不出来的,需要demo的人可以联系我,我给发过去,接下来贴出来几张效果图,这图片放的位置不好看哈!


 
  

demo下载地址:https://github.com/guoliuya/scant,花了一上午时间抽出来的!

 
 

你可能感兴趣的:(Android)