Google Vision API - 空对象引用上的人脸方法
Posted
技术标签:
【中文标题】Google Vision API - 空对象引用上的人脸方法【英文标题】:Google Vision API - Face methods on null object references 【发布时间】:2016-07-20 21:28:37 【问题描述】:我正在尝试更改 Google 为 android 上的人脸检测提供的示例应用。
FaceDetector detector = new FaceDetector.Builder(getApplicationContext())
.setTrackingEnabled(false)
.setMode(FaceDetector.ACCURATE_MODE) // Accurate mode allows to get better face detection and better position (but the detection will be slower)
.setLandmarkType(FaceDetector.ALL_LANDMARKS)
.build();
// This is a temporary workaround for a bug in the face detector with respect to operating
// on very small images. This will be fixed in a future release. But in the near term, use
// of the SafeFaceDetector class will patch the issue.
Detector<Face> safeDetector = new SafeFaceDetector(detector);
// Create a frame from the bitmap and run face detection on the frame.
Bitmap bitmap = ((BitmapDrawable)ivPhoto.getDrawable()).getBitmap();
Frame frame = new Frame.Builder().setBitmap(bitmap).build();
SparseArray<Face> faces = safeDetector.detect(frame);
if (!safeDetector.isOperational())
Log.w(TAG, "Face detector dependencies are not yet available.");
// Check for low storage. If there is low storage, the library will not be
// downloaded, so detection will not become operational.
IntentFilter lowStorageFilter = new IntentFilter(Intent.ACTION_DEVICE_STORAGE_LOW);
boolean hasLowStorage = registerReceiver(null, lowStorageFilter) != null;
if (hasLowStorage)
Toast.makeText(this, R.string.low_storage_error, Toast.LENGTH_LONG).show();
Log.w(TAG, getString(R.string.low_storage_error));
我的问题是,当我尝试在检测到的人脸上调用方法时,例如:
for(int i = 0; i < faces.size(); i++)
Face face = faces.get(i);
float x = face.getPosition().x + (face.getWidth() / 2);
float y = face.getPosition().y + (face.getHeight() / 2);
然后有时我会在应用崩溃时收到此异常:
04-01 09:07:23.154 30199-30199/ch.epfl.proshare E/AndroidRuntime: FATAL EXCEPTION: main
Process: ch.epfl.proshare, PID: 30199
java.lang.RuntimeException: Unable to start activity ComponentInfoch.epfl.proshare/ch.epfl.proshare.main.MainActivity: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.app.AppCompatActivity.setSupportActionBar(android.support.v7.widget.Toolbar)' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2306)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2366)
at android.app.ActivityThread.access$800(ActivityThread.java:149)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5297)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v7.app.AppCompatActivity.setSupportActionBar(android.support.v7.widget.Toolbar)' on a null object reference
at ch.epfl.proshare.main.MainFragment.onCreateView(MainFragment.java:169)
at android.support.v4.app.Fragment.performCreateView(Fragment.java:1962)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1248)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1230)
at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:2042)
at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:165)
at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:543)
at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1220)
at android.app.Activity.performStart(Activity.java:6036)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2269)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2366)
at android.app.ActivityThread.access$800(ActivityThread.java:149)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1284)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5297)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:908)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:703)
我真的不明白为什么 SafeDetector 会返回一个包含空人脸的 SparseArray。有人遇到过这个问题吗?
【问题讨论】:
【参考方案1】:实际上我刚刚找到了解决问题的方法。 面存储在 SparseArray 中,实际上类似于从整数 (id) 到面的映射。因此,获取一张脸应该通过以下方式完成:
Face face = faces.valueAt(i);
而不是
Face face = faces.get(i);
【讨论】:
以上是关于Google Vision API - 空对象引用上的人脸方法的主要内容,如果未能解决你的问题,请参考以下文章
是否可以使用 Google 的 Vision API 或 Amazon 的 Rekognition 来获取对象的数量?
json Google Cloud Vision API OpenAPI
IndexError:带有 Google Cloud Vision API 的字节数组
Google Cloud Vision API PDF 文本提取