如何解决CameraX 使用 ZXing 一维条码阅读器实现,ImageProxy 从目标旋转 90 度,找不到旋转它的方法
我正在尝试使用带有 ZXing 库的 CameraX 来识别条形码, 我正在使用 ImageAnalyzer 获取 ImageProxy 并将其字节数组提供给 PlanarYUVLuminanceSource 以通过 ZXing 处理它。 我的目标旋转是 0 并且来自相机的 imageProxy 是 90 度,所以条形码在我旋转 90 度之前是不可读的。 这是代码:
private void buildAnalyzer() {
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
imageAnalysis = new ImageAnalysis.Builder()
.setTargetResolution(new Size(1080,720))
.setTargetRotation(Surface.ROTATION_0)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build();
}
MultiFormatReader reader = new MultiFormatReader();
Hashtable<DecodeHintType,Object> hints = new Hashtable<DecodeHintType,Object>(
2);
Vector<BarcodeFormat> decodeFormats = new Vector<BarcodeFormat>();
decodeFormats = new Vector<BarcodeFormat>();
decodeFormats.add(BarcodeFormat.EAN_13);
hints.put(DecodeHintType.POSSIBLE_FORMATS,decodeFormats);
hints.put(DecodeHintType.TRY_HARDER,Boolean.TRUE);
reader.setHints(hints);
imageAnalysis.setAnalyzer(Executors.newFixedThreadPool(1),new ImageAnalysis.Analyzer() {
@Override
public void analyze(@NonNull ImageProxy imageProxy) {
int rotationDegrees = imageProxy.getImageInfo().getRotationDegrees();
Log.v(TAG,"Rotation + " + rotationDegrees);
Log.v(TAG,"format + " + imageProxy.getFormat());
ImageProxy.PlaneProxy[] planes = imageProxy.getPlanes();
Log.v(TAG,"planes " + planes.length);
ByteBuffer yBuffer = planes[0].getBuffer();
ByteBuffer uBuffer = planes[1].getBuffer();
ByteBuffer vBuffer = planes[2].getBuffer();
int ySize = yBuffer.remaining();
int uSize = uBuffer.remaining();
int vSize = vBuffer.remaining();
byte[] data = new byte[ySize + uSize + vSize];
//U and V are swapped
yBuffer.get(data,ySize);
vBuffer.get(data,ySize,vSize);
uBuffer.get(data,ySize + vSize,uSize);
Log.v(TAG,"width : " + imageProxy.getWidth());
Log.v(TAG,"height : " + imageProxy.getHeight());
Log.v(TAG,"planes 1 size : " + ySize + " remaining: " + yBuffer.remaining());
Log.v(TAG,"planes 2 size : " + uSize + " remaining: " + uBuffer.remaining());
Log.v(TAG,"planes 3 size : " + vSize + " remaining: " + vBuffer.remaining());
Log.v(TAG,"data length : " + data.length);
PlanarYUVLuminanceSource source = new PlanarYUVLuminanceSource(data,imageProxy.getWidth(),imageProxy.getHeight(),false);
BinaryBitmap binary = new BinaryBitmap(new HybridBinarizer(source));
try {
Result result = reader.decodeWithState(binary);
Log.d(TAG,"reader read " + result.getText());
Looper looper = Looper.getMainLooper();
Handler handler = new Handler(looper);
handler.post(new Runnable() {
@Override
public void run() {
Toast.makeText(con,result.getText() + "\n" + result.getNumBits(),Toast.LENGTH_LONG).show();
}
});
} catch (NotFoundException e) {
Log.d(TAG,"exception " + e.getMessage());
}
imageProxy.close();
}
});
}
上面的代码工作正常,这表明字节没有任何问题,也就是说,这是我尝试过但从未奏效的解决方案:
1- 旋转字节数组:我使用此方法 https://stackoverflow.com/a/15775173/4674191 旋转我从 ImageProxy 中提取的字节数组“数据”,但它返回了一个错误数组,超出了绑定异常, 此方法适用于因子为 4 的数组,而我的字节数组不满足此条件。 逻辑上字节数组是 yuv420 图像格式,由具有一定宽度和高度的 3 层组成。 但是让我发疯的是宽度和高度与数组不兼容:
宽度 = 1440,高度 = 1080,飞机 1 尺寸:1589728, 飞机 2 尺寸:794847, 飞机 3 尺寸:794847
看看它们不能被 1440 或 1080 整除的数字,也不能被 4 整除。
2- 从字节数组中创建一个位图并旋转它,然后从新位图中提取旋转后的字节数组: 也不起作用,因为宽度和高度就像之前一样未知,分辨率与字节数组编号不兼容,结果位图是一堆扭曲的绿色混乱。
3- 活动在清单 android:screenOrientation="portrait"
中被锁定为纵向模式:同样的问题,imageProxy 旋转仍为 90
4- PlanarYUVLuminanceSource 不支持旋转 :( 不知道为什么。
我尝试了几乎所有 StackOverFlow 上的解决方案,并阅读了 cameraX 的所有文档,但似乎没有任何解决方案可以解决这个问题。 如果有办法知道 byteArray 的实际分辨率,它会解决我猜的问题。
解决方法
byte[] data = ImageUtil.imageToJpegByteArray(imageProxy);
Bitmap bitmap= BitmapFactory.decodeByteArray(data,data.size)
您可以通过上面的代码获取位图。 ImageUtil 类在 androidx.camera.core
androidx.camera.core.internal.utils.ImageUtil
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。