原文地址
前言
效果图走一波(用的gif大师,录制的质量比较低,质量过高的传不上去,见谅)

需求分析
代码实现
弱光检测
上面分析完后,就知道了,咱们要实时的分析图片的颜色平均值(agb平均值),既然说到了实时的分析,我们就要找到二维码处理解码实时帧的方法,zxing使用decodeThread,decodeHanlder,decodeThread线程不断的分析流并解码.
/ * Decode the data within the viewfinder rectangle, and time how long it took. For efficiency, * reuse the same reader objects from one decode to the next. * * @param data The YUV preview frame. * @param width The width of the preview frame. * @param height The height of the preview frame. */ private void decode(byte[] data, int width, int height)
private int[] decodeYUV420SP(byte[] yuv420sp, int width, int height) { final int frameSize = width * height; int rgb[] = new int[width * height]; for (int j = 0, yp = 0; j < height; j++) { int uvp = frameSize + (j >> 1) * width, u = 0, v = 0; for (int i = 0; i < width; i++, yp++) { int y = (0xff & ((int) yuv420sp[yp])) - 16; if (y < 0) y = 0; if ((i & 1) == 0) { v = (0xff & yuv420sp[uvp++]) - 128; u = (0xff & yuv420sp[uvp++]) - 128; } int y1192 = 1192 * y; int r = (y1192 + 1634 * v); int g = (y1192 - 833 * v - 400 * u); int b = (y1192 + 2066 * u); if (r < 0) r = 0; else if (r > ) r = ; if (g < 0) g = 0; else if (g > ) g = ; if (b < 0) b = 0; else if (b > ) b = ; rgb[yp] = 0xff000000 | ((r << 6) & 0xff0000) | ((g >> 2) & 0xff00) | ((b >> 10) & 0xff); } } return rgb; }
private int getAverageColor(Bitmap bitmap) { int redBucket = 0; int greenBucket = 0; int blueBucket = 0; int pixelCount = 0; for (int y = 0; y < bitmap.getHeight(); y++) { for (int x = 0; x < bitmap.getWidth(); x++) { int c = bitmap.getPixel(x, y); pixelCount++; redBucket += Color.red(c); greenBucket += Color.green(c); blueBucket += Color.blue(c); } } int averageColor = Color.rgb(redBucket / pixelCount, greenBucket / pixelCount, blueBucket / pixelCount); return averageColor; }
private void analysisBitmapColor(byte[] data, int width, int height) { int[] rgb = decodeYUV420SP(data, width, height); Bitmap bmp = null; if (null != frameRect) { //取矩形扫描框frameRect的2分之一创建为bitmap来分析 bmp = Bitmap.createBitmap(rgb, frameRect.left + (frameRect.right - frameRect.left) / 4, frameRect.width() / 2, frameRect.width() / 2, frameRect.height() / 2, Bitmap.Config.ARGB_4444); } if (bmp != null) { float color = getAverageColor(bmp); DecimalFormat decimalFormat1 = new DecimalFormat("0.00"); String percent = decimalFormat1.format(color / -); float floatPercent = Float.parseFloat(percent); Log.e(TAG, " color= " + color + " floatPercent= " + floatPercent + " bmp width= " + bmp.getWidth() + " bmp height= " + bmp.getHeight()); Constants.isWeakLight = (color == - || (floatPercent >= 0.95 && floatPercent <= 1.00)); bmp.recycle(); } }
上述代码基本实现了弱光的检测,代码还可以进行优化,比如我在YUV转换为AGB时,我只转换矩形扫描框内的图片,只分析这块的图片AGB平均值,目前,这一帧的图片我全部转换了AGB,你会发现,color 永远不会等于-(black),因为最优的做法就是只decode矩形扫描框内的图片将其转换为agb数组,然后再进行图片的agb分析,这样也仅仅有可能color会等于-.
扫一扫自动放大的功能
我也只能先这样,后续可以根据扫描时间来优化进行放大或修改吧.自动放大代码如下:
if (rawResult != null) { // Don't log the barcode contents for security. long end = System.currentTimeMillis(); Log.d(TAG, "Found barcode in " + (end - start) + " ms"); if (handler != null) { float point1X = rawResult.getResultPoints()[0].getX(); float point1Y = rawResult.getResultPoints()[0].getY(); float point2X = rawResult.getResultPoints()[1].getX(); float point2Y = rawResult.getResultPoints()[1].getY(); int len = (int) Math.sqrt(Math.abs(point1X - point2X) * Math.abs(point1X - point2X) + Math.abs(point1Y - point2Y) * Math.abs(point1Y - point2Y)); if (frameRect != null) { int frameWidth = frameRect.right - frameRect.left; Camera camera = activity.getCameraManager().getCameraNotStatic(); Camera.Parameters parameters = camera.getParameters(); final int maxZoom = parameters.getMaxZoom(); int zoom = parameters.getZoom(); if (parameters.isZoomSupported()) { if (len <= frameWidth / 4) { if (zoom == 0) { zoom = maxZoom / 3; } else { zoom = zoom + 10; } if (zoom > maxZoom) { zoom = maxZoom; } parameters.setZoom(zoom); camera.setParameters(parameters); final Result finalRawResult = rawResult; postDelayed(new Runnable() { @Override public void run() { Message message = Message.obtain(handler, R.id.decode_succeeded, finalRawResult); Bundle bundle = new Bundle(); bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap()); message.setData(bundle); message.sendToTarget(); } }, 1000); } else { Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult); Bundle bundle = new Bundle(); bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap()); message.setData(bundle); message.sendToTarget(); } } } else { Message message = Message.obtain(handler, R.id.decode_succeeded, rawResult); Bundle bundle = new Bundle(); bundle.putParcelable(DecodeThread.BARCODE_BITMAP, source.renderCroppedGreyscaleBitmap()); message.setData(bundle); message.sendToTarget(); } } } else { if (handler != null) { Message message = Message.obtain(handler, R.id.decode_failed); message.sendToTarget(); // if (!Constants.isWeakLight) { // long failedTimeStamp = System.currentTimeMillis(); // if (failedTimeStamp - intervalTime > INTERVAL) { // isResetTime = true; // intervalTime = System.currentTimeMillis(); // Camera camera = activity.getCameraManager().getCameraNotStatic(); // Camera.Parameters parameters = camera.getParameters(); // final int maxZoom = parameters.getMaxZoom(); // int zoom = parameters.getZoom(); // if (parameters.isZoomSupported()) { // if (zoom == 0) { // zoom = maxZoom / 2; // } else { // zoom = zoom + 10; // } // if (zoom > maxZoom) { // zoom = maxZoom; // } // parameters.setZoom(zoom); // camera.setParameters(parameters); // } // } // } } }
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/224281.html原文链接:https://javaforall.net
