java - 如何使用 Firebase ML 套件识别地标?

标签 java android firebase firebase-mlkit

我正在创建一个用于识别地标的应用程序。 当图像被识别时,结果应该是onSuccess,但是却是onFailure。

日志中显示以下消息:

If you have not set up billing, please go to the Firebase Console to set up billing: https://firebase.corp.google.com/u/0/project/_/overview?purchaseBillingPlan= true

If you are specifying a debug API Key override and turning on API Key restrictions, make sure the restrictions are set up correctly.

当我点击链接时,我看到以下页面: https://login.corp.google.com/request?s=firebase.corp.google.com:443/uberproxy/&d=https://firebase.corp.google.com/u/0/project/_/overview%3FpurchaseBillingPlan%3Dtrue%26upxsrf%3DAKKYJRc2HD6ROcy9V9DxnYxw-pd8yGnml-oEi37m5hKhkWurWQ:1557057663745&maxAge=1200&authLevel=2000000&keyIds=X-q,k02

我需要做什么?

公共(public)类 RecognizeLandmarks 扩展了 AppCompatActivity {

EditText mResultEt;
ImageView mPreviewIv;
TextView tvLName, tvLiD, tvLConfidence, tvLlatitude, tvLlongitude;

public static final int CAMERA_REQUEST_CODE = 200;
public static final int STORAGE_REQUEST_CODE = 400;
public static final int IMAGE_PIC_GALLERY_CODE = 1000;
public static final int IMAGE_PIC_CAMERA_CODE = 1001;

private static final String TAG = "MyLog";

String cameraPermission[];
String storagePermission[];

Uri image_uri;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_recognize_landmarks);

    androidx.appcompat.app.ActionBar actionBar = getSupportActionBar();
    actionBar.setSubtitle("Click image button to insert Image");

    mResultEt = findViewById(R.id.resultEt);
    mPreviewIv = findViewById(R.id.imageIv);
    tvLName = findViewById(R.id.tvLName);
    tvLiD = findViewById(R.id.tvLiD);
    tvLConfidence = findViewById(R.id.tvLConfidence);
    tvLlatitude = findViewById(R.id.tvLlatitude);
    tvLlongitude = findViewById(R.id.tvLlongitude);

    //camera permission
    cameraPermission = new String[]{Manifest.permission.CAMERA,
            Manifest.permission.WRITE_EXTERNAL_STORAGE};
    //storage permission
    storagePermission = new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE};
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    //inflate menu
    getMenuInflater().inflate(R.menu.menu_recognize_text, menu);
    return true;
}

//handle actionbar item clicks

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id = item.getItemId( );
    if (id == R.id.addImage) {
        showImageImportDialog( );
    }
    if (id == R.id.settings) {
        Toast.makeText(this, "Settings", Toast.LENGTH_SHORT).show( );
    }
    return super.onOptionsItemSelected(item);
}

private void showImageImportDialog() {
    // items to display in dialog
    String[] items = {" Camera", " Gallery"};
    AlertDialog.Builder dialog = new AlertDialog.Builder(this);
    dialog.setTitle("Select Image");
    dialog.setItems(items, new DialogInterface.OnClickListener( ) {
        @Override
        public void onClick(DialogInterface dialogInterface, int i) {
            if (i == 0) {
                //camera option clicked
                /*for os Marshmallow and above we need to ask runtime permission for camera and storage*/
                if (!checkCameraPermission()) {
                    //camera permission not allowed, request it
                    requestCameraPermission();
                } else {
                    //permission allowed, take picture
                    pickCamera();
                }
            }
            if (i == 1) {
                //gallery option clicked
                if (!checkStoragePermission()) {
                    //storage permission not allowed, request it
                    requestStoragePermission();
                } else {
                    //permission allowed, take picture
                    pickGallery();
                }
            }
        }
    });
    dialog.create().show();
}

private void pickGallery() {
    //intent to pick image from gallery
    Intent intent = new Intent(Intent.ACTION_PICK);
    //set intent type to image
    intent.setType("image/*");
    startActivityForResult(intent, IMAGE_PIC_GALLERY_CODE);
}

private void pickCamera() {
    //intent to take image from camera, it will also be save to storage to get high quality image
    ContentValues values = new ContentValues( );
    values.put(MediaStore.Images.Media.TITLE, "NewPic"); //title of the picture
    values.put(MediaStore.Images.Media.DESCRIPTION, "Image to text"); //description
    image_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);

    Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri);
    startActivityForResult(cameraIntent, IMAGE_PIC_CAMERA_CODE);
}

private void requestStoragePermission() {
    ActivityCompat.requestPermissions(this, storagePermission, STORAGE_REQUEST_CODE);
}

private boolean checkStoragePermission() {
    boolean result = ContextCompat.checkSelfPermission(this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED);
    return result;
}

private void requestCameraPermission() {
    ActivityCompat.requestPermissions(this, cameraPermission, CAMERA_REQUEST_CODE);
}

private boolean checkCameraPermission() {
    /*Check camera permission and return the result
     * in order to get high quality image we have to save image to external storage first
     * before inserting to image view that`s why storage permission will also be required */
    boolean result = ContextCompat.checkSelfPermission(this,
            Manifest.permission.CAMERA) == (PackageManager.PERMISSION_GRANTED);
    boolean result1 = ContextCompat.checkSelfPermission(this,
            Manifest.permission.WRITE_EXTERNAL_STORAGE) == (PackageManager.PERMISSION_GRANTED);
    return result && result1;
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case CAMERA_REQUEST_CODE:
            if (grantResults.length > 0) {
                boolean cameraAccepted = grantResults[0] ==
                        PackageManager.PERMISSION_GRANTED;
                boolean writeStorageAccepted = grantResults[0] ==
                        PackageManager.PERMISSION_GRANTED;
                if (cameraAccepted && writeStorageAccepted) {
                    pickCamera();
                } else {
                    Toast.makeText(this, "permission denied", Toast.LENGTH_SHORT).show( );
                }
            }
            break;
        case STORAGE_REQUEST_CODE:
            if (grantResults.length > 0) {
                boolean writeStorageAccepted = grantResults[0] ==
                        PackageManager.PERMISSION_GRANTED;
                if (writeStorageAccepted) {
                    pickGallery( );
                }
                else {
                    Toast.makeText(this, "permission denied", Toast.LENGTH_SHORT).show( );
                }
            }
            break;
    }
}

@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    //got image from camera or gallery
    super.onActivityResult(requestCode, resultCode, data);
    if (resultCode == RESULT_OK) {
        if (requestCode == IMAGE_PIC_GALLERY_CODE) {
            //got image from gallery now crop it
            CropImage.activity(data.getData( ))
                    .setGuidelines(CropImageView.Guidelines.ON) // enable image guidelines
                    .start(this);
        }
        if (requestCode == IMAGE_PIC_CAMERA_CODE) {
            //got image from camera crop it
            CropImage.activity(image_uri)
                    .setGuidelines(CropImageView.Guidelines.ON) // enable image guidelines
                    .start(this);
        }
    }
    //get cropped image
    if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
        CropImage.ActivityResult result1 = CropImage.getActivityResult(data);
        if (resultCode == RESULT_OK) {
            Uri resultUri = result1.getUri( ); // get image uri
            //set image to image view
            mPreviewIv.setImageURI(resultUri);// past image in iV


            //get drawable bitmap for text recognition
            BitmapDrawable bitmapDrawable = (BitmapDrawable) mPreviewIv.getDrawable( );
            Bitmap bitmap = bitmapDrawable.getBitmap( );

            FirebaseVisionImage image = FirebaseVisionImage.fromBitmap(bitmap);

            FirebaseVisionCloudDetectorOptions options =
                    new FirebaseVisionCloudDetectorOptions.Builder( )
                            .setModelType(FirebaseVisionCloudDetectorOptions.LATEST_MODEL)
                            .setMaxResults(15)
                            .build( );

            FirebaseVisionCloudLandmarkDetector detector = FirebaseVision.getInstance( )
                    .getVisionCloudLandmarkDetector(options);

            Task<List<FirebaseVisionCloudLandmark>> result = detector.detectInImage(image)
                    .addOnSuccessListener(new OnSuccessListener<List<FirebaseVisionCloudLandmark>>( ) {
                        @Override
                        public void onSuccess(List<FirebaseVisionCloudLandmark> firebaseVisionCloudLandmarks) {
                            // Task completed successfully
                            // ...
                            for(FirebaseVisionCloudLandmark landmark : firebaseVisionCloudLandmarks) {

                                //Rect bounds = landmark.getBoundingBox();
                                String landmarkName = landmark.getLandmark( );
                                tvLName.setText(landmarkName);
                                String entityId = landmark.getEntityId( );
                                tvLiD.setText(entityId);
                                float confidence = landmark.getConfidence( );
                                tvLConfidence.setText(Float.toString(confidence));

                                // Multiple locations are possible, e.g., the location of the depicted
                                // landmark and the location the picture was taken.
                                for(FirebaseVisionLatLng loc : landmark.getLocations( )) {
                                    double latitude = loc.getLatitude( );
                                    tvLlatitude.setText(Double.toString(latitude));
                                    double longitude = loc.getLongitude( );
                                    tvLlongitude.setText(Double.toString(longitude));
                                }
                            }

                        }
                    })
                    .addOnFailureListener(new OnFailureListener( ) {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            // Task failed with an exception
                            // ...
                            Log.d(TAG,e.getMessage());
                            Toast.makeText(RecognizeLandmarks.this, "Recognizing Failed", Toast.LENGTH_SHORT).show( );
                        }
                    });
            
        } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
            //if there is any error show it
            Exception error = result1.getError( );
            Toast.makeText(this, "" + error, Toast.LENGTH_SHORT).show( );
            }
        }
    }
}

Result

D/MyLog:如果您尚未设置结算,请前往 Firebase 控制台设置结算:https://firebase.corp.google.com/u/0/project/_/overview?purchaseBillingPlan=true 。如果您指定调试 Api Key 覆盖并打开 Api Key 限制,请确保限制设置正确

最佳答案

ML Kit 的地标检测不在设备本身上运行,而是使用 Google Cloud Vision。因此,您的项目需要采用付费计划,然后才能使用地标检测。前 1000 次通话免费,之后您将需要支付额外的通话费用。

关于java - 如何使用 Firebase ML 套件识别地标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55991868/

相关文章:

java - Android Studio 中的错误?无法访问子类中的 protected 成员

java - 使用parent.setChilds(null)显式删除子项

android - 如何从hotmail 和yahoo 发送电子邮件?

android - Espresso 找不到 View : NoMatchingViewException

java - 我遇到此错误 java.lang.IndexOutOfBoundsException : Index: 0, 大小:0

android - Firebase Firestore 如何列出授权文件?

java - SQLite 异常 : no such column in Android

javascript - 如何通过图像查找元素

java - Drools:字符串全局变量的奇怪行为

javascript - react native Firebase图像上传错误404