Android 二维码生成,扫描,近距离识别优化,从相册选择二维码识别

本文主要是介绍Android 二维码生成,扫描,近距离识别优化,从相册选择二维码识别,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

做了一个二维码扫描图片,主要是扫描不出来,看到一篇博客,其中的第二种方法可以扫描到,在此做笔记,以备后用,前面的进入相册,返回,到获取图片路径方法都一样;

(1):二维码生成的方法顺便贴上:

	private   Bitmap createQRImage(String url, final int width, final int height) {try {// 判断URL合法性if (url == null || "".equals(url) || url.length() < 1) {return null;}Hashtable<EncodeHintType, String> hints = new Hashtable<EncodeHintType, String>();hints.put(EncodeHintType.CHARACTER_SET, "utf-8");// 图像数据转换,使用了矩阵转换BitMatrix bitMatrix = new QRCodeWriter().encode(url,BarcodeFormat.QR_CODE, width, height, hints);int[] pixels = new int[width * height];// 下面这里按照二维码的算法,逐个生成二维码的图片,// 两个for循环是图片横列扫描的结果for (int y = 0; y < height; y++) {for (int x = 0; x < width; x++) {if (bitMatrix.get(x, y)) {pixels[y * width + x] = 0xff000000;} else {pixels[y * width + x] = 0xffffffff;}}}// 生成二维码图片的格式,使用ARGB_8888Bitmap bitmap = Bitmap.createBitmap(width, height,Bitmap.Config.ARGB_8888);bitmap.setPixels(pixels, 0, width, 0, 0, width, height);return bitmap;} catch (WriterException e) {e.printStackTrace();}return null;}

(2)二维码扫描的方法:https://blog.csdn.net/qq_25815655/article/details/79927786

 

(3)下面从相册选择二维码 

1.项目需求:知道项目需求,才知道先从哪里入手,见图一。(点击相册,打开图库)

这里写图片描述

2.代码:

1.打开图库代码:

mBtnOpenPicture.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {//打开相册openGallery();}});/**打开相册*/
private void openGallery() {Intent picture = new Intent(Intent.ACTION_PICK,   android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);startActivityForResult(picture, PICTURE);}

2.获取图片路径和解析。

(1). 获取图片路径:getPath(uri);由于Android版本不同,返回的uri会有所不同,需要做特殊处理。

@SuppressLint("NewApi")private String getPath(Uri uri) {int sdkVersion = Build.VERSION.SDK_INT;if (sdkVersion >= 19) {//Log.e("hxy", "uri auth: " + uri.getAuthority());if (isExternalStorageDocument(uri)) {String docId = DocumentsContract.getDocumentId(uri);String[] split = docId.split(":");String type = split[0];if ("primary".equalsIgnoreCase(type)) {return Environment.getExternalStorageDirectory() + "/" + split[1];}} else if (isDownloadsDocument(uri)) {final String id = DocumentsContract.getDocumentId(uri);final Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),Long.valueOf(id));return getDataColumn(this, contentUri, null, null);} else if (isMediaDocument(uri)) {final String docId = DocumentsContract.getDocumentId(uri);final String[] split = docId.split(":");final String type = split[0];Uri contentUri = null;if ("image".equals(type)) {contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;} else if ("video".equals(type)) {contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;} else if ("audio".equals(type)) {contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;}final String selection = "_id=?";final String[] selectionArgs = new String[]{split[1]};return getDataColumn(this, contentUri, selection, selectionArgs);} else if (isMedia(uri)) {String[] proj = {MediaStore.Images.Media.DATA};Cursor actualimagecursor = this.managedQuery(uri, proj, null, null, null);int actual_image_column_index = actualimagecursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);actualimagecursor.moveToFirst();return actualimagecursor.getString(actual_image_column_index);}} else if ("content".equalsIgnoreCase(uri.getScheme())) {if (isGooglePhotosUri(uri))return uri.getLastPathSegment();return getDataColumn(this, uri, null, null);}// Fileelse if ("file".equalsIgnoreCase(uri.getScheme())) {return uri.getPath();}return null;}public static String getDataColumn(Context context, Uri uri,String selection, String[] selectionArgs) {Cursor cursor = null;final String column = "_data";final String[] projection = { column };try {cursor = context.getContentResolver().query(uri, projection,selection, selectionArgs, null);if (cursor != null && cursor.moveToFirst()) {final int column_index = cursor.getColumnIndexOrThrow(column);return cursor.getString(column_index);}} finally {if (cursor != null)cursor.close();}return null;}private static boolean isExternalStorageDocument(Uri uri) {return "com.android.externalstorage.documents".equals(uri.getAuthority());}public static boolean isDownloadsDocument(Uri uri) {return "com.android.providers.downloads.documents".equals(uri.getAuthority());}public static boolean isMediaDocument(Uri uri) {return "com.android.providers.media.documents".equals(uri.getAuthority());}public static boolean isMedia(Uri uri) {return "media".equals(uri.getAuthority());}public static boolean isGooglePhotosUri(Uri uri) {return "com.google.android.apps.photos.content".equals(uri.getAuthority());}

(2).开辟线程,解析图片,封装到Result中:我看了网上的demo,大致上有2种方法。如下是第一种,稍后会把第二种方法也贴出来。

/*** 解析二维码图片* @param path* @return*/protected Result scanningImage(String path) {if (TextUtils.isEmpty(path)) {return null;}Hashtable<DecodeHintType, String> hints = new Hashtable();hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 设置二维码内容的编码BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true; // 先获取原大小scanBitmap = BitmapFactory.decodeFile(path,options);options.inJustDecodeBounds = false;int sampleSize = (int) (options.outHeight / (float) 200);if (sampleSize <= 0)sampleSize = 1;options.inSampleSize = sampleSize;scanBitmap = BitmapFactory.decodeFile(path, options);int[] data = new int[scanBitmap.getWidth() * scanBitmap.getHeight()];scanBitmap.getPixels(data, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), scanBitmap.getHeight());RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(scanBitmap.getWidth(),scanBitmap.getHeight(),data);BinaryBitmap binaryBitmap = new BinaryBitmap(new HybridBinarizer(rgbLuminanceSource));QRCodeReader reader = new QRCodeReader();Result result = null;try {result = reader.decode(binaryBitmap, hints);} catch (NotFoundException e) {Log.e("hxy","NotFoundException");}catch (ChecksumException e){Log.e("hxy","ChecksumException");}catch(FormatException e){Log.e("hxy","FormatException");}return result;}
  •  

注意:上面方法中有个关键的类,RGBLuminanceSource。 我把这个类的构造方法贴出来,因为我做的时候,发现网上demo 这个类中构造传递的都是Bitmap, 而我这个类却不是。分析传递的参数之后,我做了个转化:见如下,然后会发现报:NotFoundException. 这个异常是在QRCodeReader类:private static BitMatrix extractPureBits(BitMatrix image) throws NotFoundException 。(到这里我已经不是很懂了,然后又去网上搜索了下,最后自己探索出加scanBitmap.getPixels(data, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), scanBitmap.getHeight());),运行正常,能解析出来。

int[] data = new int[scanBitmap.getWidth() * scanBitmap.getHeight()];
//一定要加以下这个代码:
//scanBitmap.getPixels(data, 0, scanBitmap.getWidth(), 0, 0, scanBitmap.getWidth(), //scanBitmap.getHeight());
RGBLuminanceSource rgbLuminanceSource = new RGBLuminanceSource(scanBitmap.getWidth(),scanBitmap.getHeight(),data);
public RGBLuminanceSource(int width, int height, int[] pixels) {super(width, height);this.dataWidth = width;this.dataHeight = height;this.left = 0;this.top = 0;this.luminances = new byte[width * height];for(int y = 0; y < height; ++y) {int offset = y * width;for(int x = 0; x < width; ++x) {int pixel = pixels[offset + x];int r = pixel >> 16 & 255;int g = pixel >> 8 & 255;int b = pixel & 255;if(r == g && g == b) {this.luminances[offset + x] = (byte)r;} else {this.luminances[offset + x] = (byte)((r + 2 * g + b) / 4);}}}}

 

现在来看第二种解析方法:

protected Result scanningImage(String path) {if (TextUtils.isEmpty(path)) {return null;}BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true; // 先获取原大小scanBitmap = BitmapFactory.decodeFile(path,options);options.inJustDecodeBounds = false;int sampleSize = (int) (options.outHeight / (float) 200);if (sampleSize <= 0)sampleSize = 1;options.inSampleSize = sampleSize;scanBitmap = BitmapFactory.decodeFile(path, options);byte[] data = getYUV420sp(scanBitmap.getWidth(), scanBitmap.getHeight(), scanBitmap);Hashtable<DecodeHintType, Object> hints = new Hashtable();hints.put(DecodeHintType.CHARACTER_SET, "UTF-8"); // 设置二维码内容的编码hints.put(DecodeHintType.TRY_HARDER,Boolean.TRUE);hints.put(DecodeHintType.POSSIBLE_FORMATS, BarcodeFormat.QR_CODE);PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data,scanBitmap.getWidth(),scanBitmap.getHeight(),0, 0,scanBitmap.getWidth(),scanBitmap.getHeight(),false);BinaryBitmap bitmap1 = new BinaryBitmap(new HybridBinarizer(source));QRCodeReader reader2= new QRCodeReader();Result result = null;try {result = reader2.decode(bitmap1, hints);Log.e("hxy",result.getText());} catch (NotFoundException e) {Log.e("hxy","NotFoundException");}catch (ChecksumException e){Log.e("hxy","ChecksumException");}catch(FormatException e){Log.e("hxy","FormatException");}return result;}public  byte[] getYUV420sp(int inputWidth, int inputHeight,Bitmap scaled) {int[] argb = new int[inputWidth * inputHeight];scaled.getPixels(argb, 0, inputWidth, 0, 0, inputWidth, inputHeight);byte[] yuv = new byte[inputWidth * inputHeight * 3 / 2];encodeYUV420SP(yuv, argb, inputWidth, inputHeight);scaled.recycle();return yuv;}private void encodeYUV420SP(byte[] yuv420sp, int[] argb, int width,int height) {// 帧图片的像素大小final int frameSize = width * height;// ---YUV数据---int Y, U, V;// Y的index从0开始int yIndex = 0;// UV的index从frameSize开始int uvIndex = frameSize;// ---颜色数据---
//      int a, R, G, B;int R, G, B;//int argbIndex = 0;//// ---循环所有像素点,RGB转YUV---for (int j = 0; j < height; j++) {for (int i = 0; i < width; i++) {// a is not used obviously
//              a = (argb[argbIndex] & 0xff000000) >> 24;R = (argb[argbIndex] & 0xff0000) >> 16;G = (argb[argbIndex] & 0xff00) >> 8;B = (argb[argbIndex] & 0xff);//argbIndex++;// well known RGB to YUV algorithmY = ((66 * R + 129 * G + 25 * B + 128) >> 8) + 16;U = ((-38 * R - 74 * G + 112 * B + 128) >> 8) + 128;V = ((112 * R - 94 * G - 18 * B + 128) >> 8) + 128;//Y = Math.max(0, Math.min(Y, 255));U = Math.max(0, Math.min(U, 255));V = Math.max(0, Math.min(V, 255));// NV21 has a plane of Y and interleaved planes of VU each// sampled by a factor of 2// meaning for every 4 Y pixels there are 1 V and 1 U. Note the// sampling is every other// pixel AND every other scanline.// ---Y---yuv420sp[yIndex++] = (byte) Y;// ---UV---
//              if ((j % 2 == 0) && (i % 2 == 0)) {
//                  
//
// 
//                  yuv420sp[uvIndex++] = (byte) V;
//                  
//                  yuv420sp[uvIndex++] = (byte) U;
//              }}}}

最后2行代码在实际运行的时候,如果是拿一个二维码图片,能正常解析,但是如果不是二维码图片,数组越界。然后我将其注释掉之后,一切正常了。在这里的转化,我没有看懂,只是提供一种解析方案,期待对这方面了解之人能我和探讨。

3.将解析结果回调给调用Activity.:

@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if(resultCode==RESULT_OK&&data != null&&requestCode == PICTURE){Uri selectedImage = data.getData();final String pathResult = getPath(selectedImage);Log.e("hxy","pathResult:"+pathResult);new Thread(new Runnable() {@Overridepublic void run() {Result result = scanningImage(pathResult);if(result==null){Looper.prepare();Toast.makeText(CaptureActivity.this, "未识别到二维码",Toast.LENGTH_LONG).show();Looper.loop();}else{handleDecode(result,new Bundle());
//                      String recode = recode(result.toString());
//                      Log.e("hxy","recode:"+recode);
//                      Intent data = new Intent();
//                      data.putExtra("result", recode);
//                      setResult(300, data);//finish();}}}).start();}}
  •  

在这里调用handleDecode。是由于CaptureActivity中,将结果就是通过handleDecode回调的

/*** A valid barcode has been found, so give an indication of success and show* the results.* * @param rawResult*            The contents of the barcode.* * @param bundle*            The extras*/public void handleDecode(Result rawResult, Bundle bundle) {inactivityTimer.onActivity();beepManager.playBeepSoundAndVibrate();bundle.putInt("width", mCropRect.width());bundle.putInt("height", mCropRect.height());bundle.putString("result", rawResult.getText());//      startActivity(new Intent(CaptureActivity.this, ResultActivity.class).putExtras(bundle));setResult(RESULT_OK, new Intent().putExtras(bundle));
//      Toast.makeText(this, rawResult.getText(), Toast.LENGTH_LONG);finish();}

以上就是解析二维码图片的两种方法,借鉴的博客如下:

http://blog.csdn.net/a102111/article/details/48377537 
http://blog.csdn.net/aaawqqq/article/details/24880209

这篇关于Android 二维码生成,扫描,近距离识别优化,从相册选择二维码识别的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/313153

相关文章

Vue3 的 shallowRef 和 shallowReactive:优化性能

大家对 Vue3 的 ref 和 reactive 都很熟悉,那么对 shallowRef 和 shallowReactive 是否了解呢? 在编程和数据结构中,“shallow”(浅层)通常指对数据结构的最外层进行操作,而不递归地处理其内部或嵌套的数据。这种处理方式关注的是数据结构的第一层属性或元素,而忽略更深层次的嵌套内容。 1. 浅层与深层的对比 1.1 浅层(Shallow) 定义

如何选择适合孤独症兄妹的学校?

在探索适合孤独症儿童教育的道路上,每一位家长都面临着前所未有的挑战与抉择。当这份责任落在拥有孤独症兄妹的家庭肩上时,选择一所能够同时满足两个孩子特殊需求的学校,更显得尤为关键。本文将探讨如何为这样的家庭做出明智的选择,并介绍星贝育园自闭症儿童寄宿制学校作为一个值得考虑的选项。 理解孤独症儿童的独特性 孤独症,这一复杂的神经发育障碍,影响着儿童的社交互动、沟通能力以及行为模式。对于拥有孤独症兄

HDFS—存储优化(纠删码)

纠删码原理 HDFS 默认情况下,一个文件有3个副本,这样提高了数据的可靠性,但也带来了2倍的冗余开销。 Hadoop3.x 引入了纠删码,采用计算的方式,可以节省约50%左右的存储空间。 此种方式节约了空间,但是会增加 cpu 的计算。 纠删码策略是给具体一个路径设置。所有往此路径下存储的文件,都会执行此策略。 默认只开启对 RS-6-3-1024k

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人,是不是经常需要制作各种PPT来分享我的生活和想法。但是,你们知道,有时候灵感来了,时间却不够用了!😩直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手!🌟 什么是Kimi? 一款月之暗面科技有限公司开发的AI办公工具,帮助用户快速生成高质量的演示文稿。 无论你是职场人士、学生还是教师,Kimi都能够为你的办公文

使用opencv优化图片(画面变清晰)

文章目录 需求影响照片清晰度的因素 实现降噪测试代码 锐化空间锐化Unsharp Masking频率域锐化对比测试 对比度增强常用算法对比测试 需求 对图像进行优化,使其看起来更清晰,同时保持尺寸不变,通常涉及到图像处理技术如锐化、降噪、对比度增强等 影响照片清晰度的因素 影响照片清晰度的因素有很多,主要可以从以下几个方面来分析 1. 拍摄设备 相机传感器:相机传

阿里开源语音识别SenseVoiceWindows环境部署

SenseVoice介绍 SenseVoice 专注于高精度多语言语音识别、情感辨识和音频事件检测多语言识别: 采用超过 40 万小时数据训练,支持超过 50 种语言,识别效果上优于 Whisper 模型。富文本识别:具备优秀的情感识别,能够在测试数据上达到和超过目前最佳情感识别模型的效果。支持声音事件检测能力,支持音乐、掌声、笑声、哭声、咳嗽、喷嚏等多种常见人机交互事件进行检测。高效推

Android实现任意版本设置默认的锁屏壁纸和桌面壁纸(两张壁纸可不一致)

客户有些需求需要设置默认壁纸和锁屏壁纸  在默认情况下 这两个壁纸是相同的  如果需要默认的锁屏壁纸和桌面壁纸不一样 需要额外修改 Android13实现 替换默认桌面壁纸: 将图片文件替换frameworks/base/core/res/res/drawable-nodpi/default_wallpaper.*  (注意不能是bmp格式) 替换默认锁屏壁纸: 将图片资源放入vendo

pdfmake生成pdf的使用

实际项目中有时会有根据填写的表单数据或者其他格式的数据,将数据自动填充到pdf文件中根据固定模板生成pdf文件的需求 文章目录 利用pdfmake生成pdf文件1.下载安装pdfmake第三方包2.封装生成pdf文件的共用配置3.生成pdf文件的文件模板内容4.调用方法生成pdf 利用pdfmake生成pdf文件 1.下载安装pdfmake第三方包 npm i pdfma

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

Android平台播放RTSP流的几种方案探究(VLC VS ExoPlayer VS SmartPlayer)

技术背景 好多开发者需要遴选Android平台RTSP直播播放器的时候,不知道如何选的好,本文针对常用的方案,做个大概的说明: 1. 使用VLC for Android VLC Media Player(VLC多媒体播放器),最初命名为VideoLAN客户端,是VideoLAN品牌产品,是VideoLAN计划的多媒体播放器。它支持众多音频与视频解码器及文件格式,并支持DVD影音光盘,VCD影