机器学习套件条形码扫描:图像数据大小无效
ML Kit Barcode scanning: Invalid image data size
我想在捕获的图像中检测条形码。我使用 android 的 camera2 拍摄图像。在此之后,检索图像的元数据并将图像保存到设备。元数据全部传递到下一个 activity,这是应用程序尝试检测条形码的地方。
下一个 activity 从先前保存的文件创建一个 byte[]。接下来,使用随意图传递的数据创建相关的 FirebaseVision 对象。最后,应用程序尝试调用 detectInImage()
方法,但抛出错误:
"java.lang.IllegalArgumentException: Invalid image data size."
我怀疑这是因为捕获的图像太大,但是我似乎无法弄清楚如何捕获较小的图像,而且我在参考文档中也找不到任何关于允许的最大尺寸的信息。非常感谢有关此错误及其解决方法的信息。以下是我认为相关的代码。
private final ImageReader.OnImageAvailableListener onImageAvailableListener
= new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader imageReader) {
try{
// Semaphore ensures date is recorded before starting next activity
storeData.acquire();
Image resultImg = imageReader.acquireNextImage(); // Image from camera
imgWidth = resultImg.getWidth();
imgHeight = resultImg.getHeight();
ByteBuffer buffer = resultImg.getPlanes()[0].getBuffer();
data = new byte[buffer.remaining()]; // Byte array with the images data
buffer.get(data);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
// Note: mediaFile directs to Pictures/"ThisProject" folder
File media = new File(mediaFile.getPath() +
File.separator + "IMG_" + timeStamp + ".jpg");
// Saving the image
FileOutputStream fos = null;
try {
fos = new FileOutputStream(media);
fos.write(data);
uri = Uri.fromFile(media);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
}
resultImg.close();
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage());
}
storeData.release();
}
};
这实际上是检索图像的高度和宽度,然后将其写入文件。
发送到下一个activity的数据包括:图像宽度、图像高度、图像旋转和指向文件的Uri。
使用这个,我尝试使用 Firebase ML Kit 检测条形码:
// uri is the uri referencing the saved image
File f = new File(uri.getPath());
data = new byte[(int) f.length()];
try{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
DataInputStream dis = new DataInputStream(bis);
dis.readFully(data);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
FirebaseVisionBarcodeDetectorOptions options = new FirebaseVisionBarcodeDetectorOptions.Builder().setBarcodeFormats(
FirebaseVisionBarcode.FORMAT_QR_CODE,
FirebaseVisionBarcode.FORMAT_DATA_MATRIX
).build();
FirebaseVisionBarcodeDetector detector = FirebaseVision.getInstance().getVisionBarcodeDetector(options);
FirebaseVisionImage image;
int rotationResult;
switch (imgRotation) {
case 0: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_0;
break;
}
case 90: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_90;
break;
}
case 180: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_180;
break;
}
case 270: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_270;
break;
}
default: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_0;
break;
}
}
FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
.setWidth(imgWidth)
.setHeight(imgHeight)
.setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
.setRotation(rotationResult)
.build();
image = FirebaseVisionImage.fromByteArray(data, metadata);
Task<List<FirebaseVisionBarcode>> result = detector.detectInImage(image)
几件事。
如果你使用camera2,你的图像格式不应该是NV21。请在此处查看所有 camera2 支持的图像格式:
https://developer.android.com/reference/android/media/Image#getFormat()
你的 byte[] 不是 NV21 并且你指定了 IMAGE_FORMAT_NV21 并导致错误
与 camera2 的最直观集成如下所示:
在实例化 ImageReader 时指定 JPEG 格式。
onImageAvailable 将返回一个 android.media.Image,您可以直接使用 FirebaseVisionImage.fromMediaImage(...) 创建一个 FirebaseVisionImage。 (你可以从官方文档中找到如何计算旋转信息here)
如果您必须执行两个活动,那么您需要解决 android.media.Image
不是 Parcelable 的事实。我建议您先将其转换为 Bitmap,这是 Parcelable,您可以直接将其设置为 Intent extra(由您决定。从最终用户的角度来看,看到条形码保存到我的图片库中并不常见。
所以你可能想考虑跳过将它保存到文件的步骤)。稍后,在您的第二个 Activity 中,您可以使用 FirebaseVisionImage.fromBitmap(...)
.
我想在捕获的图像中检测条形码。我使用 android 的 camera2 拍摄图像。在此之后,检索图像的元数据并将图像保存到设备。元数据全部传递到下一个 activity,这是应用程序尝试检测条形码的地方。
下一个 activity 从先前保存的文件创建一个 byte[]。接下来,使用随意图传递的数据创建相关的 FirebaseVision 对象。最后,应用程序尝试调用 detectInImage()
方法,但抛出错误:
"java.lang.IllegalArgumentException: Invalid image data size."
我怀疑这是因为捕获的图像太大,但是我似乎无法弄清楚如何捕获较小的图像,而且我在参考文档中也找不到任何关于允许的最大尺寸的信息。非常感谢有关此错误及其解决方法的信息。以下是我认为相关的代码。
private final ImageReader.OnImageAvailableListener onImageAvailableListener
= new ImageReader.OnImageAvailableListener() {
@Override
public void onImageAvailable(ImageReader imageReader) {
try{
// Semaphore ensures date is recorded before starting next activity
storeData.acquire();
Image resultImg = imageReader.acquireNextImage(); // Image from camera
imgWidth = resultImg.getWidth();
imgHeight = resultImg.getHeight();
ByteBuffer buffer = resultImg.getPlanes()[0].getBuffer();
data = new byte[buffer.remaining()]; // Byte array with the images data
buffer.get(data);
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
// Note: mediaFile directs to Pictures/"ThisProject" folder
File media = new File(mediaFile.getPath() +
File.separator + "IMG_" + timeStamp + ".jpg");
// Saving the image
FileOutputStream fos = null;
try {
fos = new FileOutputStream(media);
fos.write(data);
uri = Uri.fromFile(media);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
} finally {
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
}
}
resultImg.close();
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage());
}
storeData.release();
}
};
这实际上是检索图像的高度和宽度,然后将其写入文件。 发送到下一个activity的数据包括:图像宽度、图像高度、图像旋转和指向文件的Uri。
使用这个,我尝试使用 Firebase ML Kit 检测条形码:
// uri is the uri referencing the saved image
File f = new File(uri.getPath());
data = new byte[(int) f.length()];
try{
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(f));
DataInputStream dis = new DataInputStream(bis);
dis.readFully(data);
} catch (IOException e) {
Log.e(TAG, e.getMessage());
}
FirebaseVisionBarcodeDetectorOptions options = new FirebaseVisionBarcodeDetectorOptions.Builder().setBarcodeFormats(
FirebaseVisionBarcode.FORMAT_QR_CODE,
FirebaseVisionBarcode.FORMAT_DATA_MATRIX
).build();
FirebaseVisionBarcodeDetector detector = FirebaseVision.getInstance().getVisionBarcodeDetector(options);
FirebaseVisionImage image;
int rotationResult;
switch (imgRotation) {
case 0: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_0;
break;
}
case 90: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_90;
break;
}
case 180: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_180;
break;
}
case 270: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_270;
break;
}
default: {
rotationResult = FirebaseVisionImageMetadata.ROTATION_0;
break;
}
}
FirebaseVisionImageMetadata metadata = new FirebaseVisionImageMetadata.Builder()
.setWidth(imgWidth)
.setHeight(imgHeight)
.setFormat(FirebaseVisionImageMetadata.IMAGE_FORMAT_NV21)
.setRotation(rotationResult)
.build();
image = FirebaseVisionImage.fromByteArray(data, metadata);
Task<List<FirebaseVisionBarcode>> result = detector.detectInImage(image)
几件事。
如果你使用camera2,你的图像格式不应该是NV21。请在此处查看所有 camera2 支持的图像格式: https://developer.android.com/reference/android/media/Image#getFormat() 你的 byte[] 不是 NV21 并且你指定了 IMAGE_FORMAT_NV21 并导致错误
与 camera2 的最直观集成如下所示:
在实例化 ImageReader 时指定 JPEG 格式。
onImageAvailable 将返回一个 android.media.Image,您可以直接使用 FirebaseVisionImage.fromMediaImage(...) 创建一个 FirebaseVisionImage。 (你可以从官方文档中找到如何计算旋转信息here)
如果您必须执行两个活动,那么您需要解决
android.media.Image
不是 Parcelable 的事实。我建议您先将其转换为 Bitmap,这是 Parcelable,您可以直接将其设置为 Intent extra(由您决定。从最终用户的角度来看,看到条形码保存到我的图片库中并不常见。 所以你可能想考虑跳过将它保存到文件的步骤)。稍后,在您的第二个 Activity 中,您可以使用FirebaseVisionImage.fromBitmap(...)
.