Я обучил модель обнаружения объектов SSD-MobileNet_V1_Coco для обнаружения определенных продуктов в супермаркете. У него был хороший результат обнаружения в моем эмуляторе P C и Android Studio. Однако при установке в реальное устройство android мои приложения не могут обнаружить какой-либо продукт или имеют очень низкий уровень достоверности.
Я использую natario1 (com.otaliastud ios .cameraview .CameraView) CameraView для захвата изображения для обнаружения и Firebase Custom Model для моей модели обнаружения объектов.
Изображение, снятое для обнаружения объекта в эмуляторе
Результат обнаружения объекта в эмуляторе
Android Манифест
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.example.finalyearproject">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:ignore="GoogleAppIndexingWarning">
<activity android:name=".FavouriteActivity" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_icon"
android:resource="@mipmap/ic_launcher" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_color"
android:resource="@color/colorAccent" />
<activity
android:name=".ProductDetails"
android:screenOrientation="sensorPortrait" />
<activity
android:name=".FirebaseDetection"
android:noHistory="true"
android:screenOrientation="sensorPortrait" />
<activity
android:name=".ScannedResultActivity"
android:screenOrientation="sensorPortrait" />
<activity
android:name=".BarcodeActivity"
android:noHistory="true"
android:screenOrientation="sensorPortrait" />
<activity
android:name=".MainActivity"
android:screenOrientation="sensorPortrait">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".MyFirebaseMessagingService">
<intent-filter>
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<meta-data
android:name="com.google.firebase.ml.vision.DEPENDENCIES"
android:value="barcode" />
</application>
</manifest>
Макет
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".BarcodeActivity">
<Button
android:id="@+id/btnScan"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginEnd="12dp"
android:layout_marginBottom="12dp"
android:text="Scan"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<FrameLayout
android:id="@+id/frameLayout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.otaliastudios.cameraview.CameraView
android:id="@+id/cameraView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Настройка CameraView
private void setupCamera(){
//Set up Camera
cameraView = findViewById(R.id.cameraView);
cameraView.setAudio(Audio.OFF);
cameraView.setPlaySounds(false);
cameraView.mapGesture(Gesture.TAP, GestureAction.AUTO_FOCUS);
cameraView.setLifecycleOwner(this);
}
onCreate
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detection);
cameraView = findViewById(R.id.cameraView);
btnScan = findViewById(R.id.btnScan);
isDetected = false;
cameraView.addCameraListener(new CameraListener() {
@Override
public void onPictureTaken(@NonNull PictureResult result) {
super.onPictureTaken(result);
result.toBitmap(new BitmapCallback() {
@Override
public void onBitmapReady(@Nullable Bitmap bitmap) {
objectDetection(bitmap);
}
});
}
});
//Scan Button function
btnScan.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
loadingDialog = ProgressDialog.show(FirebaseDetection.this, "",
"Processing. Please wait...", true);
cameraView.takePicture();
}
});
//Check Camera Permission
Dexter.withActivity(FirebaseDetection.this)
.withPermission(Manifest.permission.CAMERA)
.withListener(new PermissionListener() {
@Override
public void onPermissionGranted(PermissionGrantedResponse response) {
setupCamera();
}
@Override
public void onPermissionDenied(PermissionDeniedResponse response) {
Toast.makeText(FirebaseDetection.this, "Camera Permission is required.", Toast.LENGTH_SHORT).show();
finishAffinity();
}
@Override
public void onPermissionRationaleShouldBeShown(PermissionRequest permission, PermissionToken token) {
}
}).check();
}
Преобразование растрового изображения в плавающее [] [] [] []
private float[][][][] convertBitmapTo4dFloat(Bitmap bitmap) {
bitmap = Bitmap.createScaledBitmap(bitmap, 300, 300, false);
int batchNum = 0;
float[][][][] input = INPUT_FORMAT;
for (int x = 0; x < 300; x++) {
for (int y = 0; y < 300; y++) {
int pixel = bitmap.getPixel(x, y);
input[batchNum][x][y][0] = (Color.red(pixel) - 127.5f) / 127.5f;
input[batchNum][x][y][1] = (Color.green(pixel) - 127.5f) / 127.5f;
input[batchNum][x][y][2] = (Color.blue(pixel) - 127.5f) / 127.5f;
}
}
return input;
}
Обнаружение объекта
private void objectDetection(Bitmap bitmap){
FirebaseModelInterpreter interpreter;
try {
float [][][][] input = convertBitmapTo4dFloat(bitmap);
FirebaseCustomLocalModel localModel = new FirebaseCustomLocalModel.Builder()
.setAssetFilePath("model.tflite")
.build();
FirebaseModelInterpreterOptions options =
new FirebaseModelInterpreterOptions.Builder(localModel).build();
interpreter = FirebaseModelInterpreter.getInstance(options);
FirebaseModelInputOutputOptions inputOutputOptions =
new FirebaseModelInputOutputOptions.Builder()
.setInputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 300, 300, 3})
.setOutputFormat(0, FirebaseModelDataType.FLOAT32, new int[]{1, 10, 4}) // bounding box output
.setOutputFormat(1, FirebaseModelDataType.FLOAT32, new int[]{1, 10}) // classes number output
.setOutputFormat(2, FirebaseModelDataType.FLOAT32, new int[]{1, 10}) // confidence level output
.build();
FirebaseModelInputs inputs = new FirebaseModelInputs.Builder()
.add(input) // add() as many input arrays as your model requires
.build();
interpreter.run(inputs, inputOutputOptions)
.addOnSuccessListener(
new OnSuccessListener<FirebaseModelOutputs>() {
@Override
public void onSuccess(FirebaseModelOutputs result) {
float[][][] boxes_array = result.getOutput(0); // position of detected item
float[][] classes_array = result.getOutput(1); // classes number (item in label.txt)
float[][] confidence_array = result.getOutput(2); // confidence level on detected item
float[] classes = classes_array[0];
float[] confidence = confidence_array[0];
ArrayList<String> className = new ArrayList<>();
String[] item = new String[10];
try {
BufferedReader reader = new BufferedReader(
new InputStreamReader(getAssets().open("label.txt")));
String label;
while( (label = reader.readLine()) != null) {
className.add(label);
}
} catch (IOException e) {
e.printStackTrace();
}
for (int i = 0; i<item.length;i++){
int classId = (int) classes[i];
item[i] = className.get(classId);
Log.d("TAG_DETECT",item[i] + ": " + confidence[i]);
}
Bundle detectedProduct = new Bundle();
detectedProduct.putStringArray("name",item);
detectedProduct.putFloatArray("confidence",confidence);
Intent intent = new Intent(getBaseContext(),ScannedResultActivity.class);
intent.putExtra("detectedProduct",detectedProduct);
intent.putExtra("method","detect");
loadingDialog.dismiss();
startActivity(intent);
}
})
.addOnFailureListener(
new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
Log.d("TAG_ERROR2:", e.getMessage());
}
});
} catch (FirebaseMLException e) {
Log.d("TAG_ERROR:", e.getMessage());
}
}
Нужно ли что-то добавить в мои коды для реального Android для работы или что-то еще? Извините, если мои коды грязные. Спасибо