-
Notifications
You must be signed in to change notification settings - Fork 780
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Barcode ML kit not working on specific android device #700
Comments
After I added this nv21 converting function it worked! So somehow in some android devices even you give NV21 image format to controller it is not returning nv21, or it is not proper nv21. But in somewhere we should get format exception. Here my convert function extension Nv21Converter on CameraImage {
Uint8List getNv21Uint8List() {
var width = this.width;
var height = this.height;
var yPlane = planes[0];
var uPlane = planes[1];
var vPlane = planes[2];
var yBuffer = yPlane.bytes;
var uBuffer = uPlane.bytes;
var vBuffer = vPlane.bytes;
var numPixels = (width * height * 1.5).toInt();
var nv21 = List<int>.filled(numPixels, 0);
// Full size Y channel and quarter size U+V channels.
int idY = 0;
int idUV = width * height;
var uvWidth = width ~/ 2;
var uvHeight = height ~/ 2;
// Copy Y & UV channel.
// NV21 format is expected to have YYYYVU packaging.
// The U/V planes are guaranteed to have the same row stride and pixel stride.
// getRowStride analogue??
var uvRowStride = uPlane.bytesPerRow;
// getPixelStride analogue
var uvPixelStride = uPlane.bytesPerPixel ?? 0;
var yRowStride = yPlane.bytesPerRow;
var yPixelStride = yPlane.bytesPerPixel ?? 0;
for (int y = 0; y < height; ++y) {
var uvOffset = y * uvRowStride;
var yOffset = y * yRowStride;
for (int x = 0; x < width; ++x) {
nv21[idY++] = yBuffer[yOffset + x * yPixelStride];
if (y < uvHeight && x < uvWidth) {
var bufferIndex = uvOffset + (x * uvPixelStride);
//V channel
nv21[idUV++] = vBuffer[bufferIndex];
//V channel
nv21[idUV++] = uBuffer[bufferIndex];
}
}
}
return Uint8List.fromList(nv21);
}
}
|
I can contribute on this issue , can you please assign it to me @flutter-ml |
@SuryaAbyss: Assigned to you. Thanks. |
where did you used it because i m still getting error
|
Before convert input image. |
Ah, I see! The issue was with the format being InputImageFormat.yuv_420_888, which was passed to the metadata and caused the error. |
where did you put the code for the nv21 conversion? @gauravRNDev |
Here is a more complete example using the code from @cagrialta in case anyone is still struggling with where to put it and how to make it work. The following code works on both Android and iOS. extension Nv21Converter on CameraImage {
// Code from @cagrialta
}
const _orientations = {
DeviceOrientation.portraitUp: 0,
DeviceOrientation.landscapeLeft: 90,
DeviceOrientation.portraitDown: 180,
DeviceOrientation.landscapeRight: 270,
};
InputImage? cameraImageToInputImage(
CameraImage image,
CameraDescription camera,
DeviceOrientation deviceOrientation,
) {
final format = InputImageFormatValue.fromRawValue(image.format.raw);
if (format == null) {
return null;
}
final plane = image.planes.firstOrNull;
if (plane == null) {
return null;
}
final sensorOrientation = camera.sensorOrientation;
final InputImageRotation? rotation;
if (Platform.isIOS) {
rotation = InputImageRotationValue.fromRawValue(sensorOrientation);
} else if (Platform.isAndroid) {
var rotationCompensation = _orientations[deviceOrientation];
if (rotationCompensation == null) {
return null;
}
if (camera.lensDirection == CameraLensDirection.front) {
// front-facing
rotationCompensation = (sensorOrientation + rotationCompensation) % 360;
} else {
// back-facing
rotationCompensation = (sensorOrientation - rotationCompensation + 360) % 360;
}
rotation = InputImageRotationValue.fromRawValue(rotationCompensation);
} else {
rotation = null;
}
if (rotation == null) {
return null;
}
final Uint8List bytes;
if (Platform.isAndroid) {
bytes = image.getNv21Uint8List();
} else {
final allBytes = WriteBuffer();
for (final plane in image.planes) {
allBytes.putUint8List(plane.bytes);
}
bytes = allBytes.done().buffer.asUint8List();
}
return InputImage.fromBytes(
bytes: bytes,
metadata: InputImageMetadata(
size: Size(image.width.toDouble(), image.height.toDouble()),
rotation: rotation, // used only in Android
format: Platform.isAndroid ? InputImageFormat.nv21 : format, // Hardcode format for Android
bytesPerRow: plane.bytesPerRow, // used only in iOS
),
);
} Then simply call it wherever you have the input image like this final inputImage = cameraImageToInputImage(image, camera, cameraController.value.deviceOrientation);
if (inputImage == null) {
return;
}
final barcodes = await _barcodeScanner.processImage(inputImage); Don't forget to hardcode the image format for Android otherwise it uses |
This solution is quite good but still have issues when testing on Android - google_mlkit_object_detection: ^0.14.0 It looks like using Camera 0.10.6 - image.planes has only one item in the array instead of 3. CameraImage? img;
} E/flutter (17521): #0 _Array.[] (dart:core-patch/array.dart) I fixed it initializing the controller with yuv420 instead of nv21
|
@simeonangelov94 Thanks! Actually I run into the same issue right now when tested on different physical device. I applied your suggestions and it works great. |
This issue is stale because it has been open for 30 days with no activity. |
btw this is also occurring on iOS devices here is my issue #738 |
Describe your issue. If applicable, add screenshots to help explain your problem.
In some android devices barcode scan is not working! (For now samsung galaxy tab a7 Android 12 and tab s9+ Android 13) There is no specific error just return empty barcode list. But there is specific log on devices which not working.
This logs are not showing on working devices.
Here my camera controller how initialized
Steps to reproduce.
Run on specific devices ( now we only know Tab A7 & Tab s9)
What is the expected result?
Normal barcode scanning behaviout
Did you try our example app?
Yes
Is it reproducible in the example app?
Yes
Reproducible in which OS?
Android
Flutter/Dart Version?
[✓] Flutter (Channel stable, 3.22.1, on macOS 14.4 23E214 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 34.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 15.4)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2023.3)
[✓] VS Code (version 1.89.1)
Plugin Version?
google_mlkit_barcode_scanning: ^0.12.0
camera: ^0.11.0
The text was updated successfully, but these errors were encountered: