Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package org.chromium.content.browser.shapedetection; | |
| 6 | |
| 7 import android.graphics.Bitmap; | |
| 8 import android.graphics.PointF; | |
| 9 import android.media.FaceDetector; | |
| 10 import android.media.FaceDetector.Face; | |
| 11 | |
| 12 import org.chromium.blink.mojom.FaceDetectionResult; | |
| 13 import org.chromium.blink.mojom.ShapeDetection; | |
| 14 import org.chromium.gfx.mojom.RectF; | |
| 15 import org.chromium.mojo.system.MojoException; | |
| 16 import org.chromium.mojo.system.SharedBufferHandle; | |
| 17 import org.chromium.mojo.system.SharedBufferHandle.MapFlags; | |
| 18 | |
| 19 import java.nio.ByteBuffer; | |
| 20 | |
| 21 /** | |
| 22 * Android implementation of the shapedetection service defined in | |
| 23 * third_party/WebKit/public/platform/modules/shapedetection/shapedetection.mojo m | |
| 24 */ | |
| 25 public class ShapeDetectionImpl implements ShapeDetection { | |
| 26 private static final String TAG = "ShapeDetectionImpl"; | |
| 27 // By default, there is no limit in the number of faces detected. | |
| 28 private static final int MAX_FACES = 10; | |
| 29 | |
| 30 public ShapeDetectionImpl() {} | |
| 31 | |
| 32 @Override | |
| 33 public void detectFace( | |
| 34 SharedBufferHandle frameData, int width, int height, DetectFaceRespo nse callback) { | |
| 35 final int numBytes = width * height * 4; | |
|
ncarter (slow)
2016/10/12 20:08:35
You definitely need a security review here.
The p
Tom Sepez
2016/10/12 20:46:01
Exactly. For example, they could be < 0. Or the
| |
| 36 | |
| 37 ByteBuffer imageBuffer = frameData.map(0, numBytes, MapFlags.none()); | |
|
Tom Sepez
2016/10/12 20:46:01
Even if the previous didn't overflow, I'd expect t
xianglu
2016/10/13 00:02:32
Done.
| |
| 38 Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_88 88); | |
|
Tom Sepez
2016/10/12 20:46:01
ditto here.
xianglu
2016/10/13 00:02:32
createBitmap() will throw IllegalArgumentException
| |
| 39 | |
| 40 // An int array is needed to construct a Bitmap. However the Bytebuffer | |
| 41 // we get from |sharedBufferHandle| is directly allocated and does not | |
| 42 // have a supporting array. Therefore we need to copy from |imageBuffer| | |
| 43 // to create this intermediate Bitmap. | |
| 44 bitmap.copyPixelsFromBuffer(imageBuffer); | |
|
ncarter (slow)
2016/10/12 20:08:35
What thread does this run on?
xianglu
2016/10/13 00:02:33
It runs on the default thread.
ncarter (slow)
2016/10/13 21:54:09
The worker pool sounds like a appropriate thread f
| |
| 45 | |
| 46 // A Bitmap must be in 565 format for findFaces() to work. See | |
| 47 // http://androidxref.com/7.0.0_r1/xref/frameworks/base/media/java/andro id/media/FaceDetector.java#124 | |
| 48 // | |
| 49 // It turns out that FaceDetector is not able to detect correctly if | |
| 50 // simply using pixmap.setConfig(). The reason might be that findFaces() | |
| 51 // needs non-premultiplied ARGB arrangement, while the alpha type in the | |
| 52 // original image is premultiplied. We can use getPixels() which does | |
| 53 // the unmultiplication while copying to a new array. See | |
| 54 // http://androidxref.com/7.0.0_r1/xref/frameworks/base/graphics/java/an droid/graphics/Bitmap.java#538 | |
| 55 int[] pixels = new int[width * height]; | |
| 56 bitmap.getPixels(pixels, 0, width, 0, 0, width, height); | |
| 57 Bitmap unPremultipliedBitmap = | |
| 58 Bitmap.createBitmap(pixels, width, height, Bitmap.Config.RGB_565 ); | |
|
ncarter (slow)
2016/10/12 20:08:35
This looks really slow. Couldn't the renderer supp
xianglu
2016/10/13 00:02:33
The renderer can preconvert to 565, but SkImage li
| |
| 59 | |
| 60 FaceDetector detector = new FaceDetector(width, height, MAX_FACES); | |
| 61 Face[] detectedFaces = new Face[MAX_FACES]; | |
| 62 final int numberOfFaces = detector.findFaces(unPremultipliedBitmap, dete ctedFaces); | |
|
Tom Sepez
2016/10/12 20:46:01
does findFaces throw if the detectedFaces array is
xianglu
2016/10/13 00:02:33
It will stop at 10.
| |
| 63 | |
| 64 FaceDetectionResult faceDetectionResult = new FaceDetectionResult(); | |
| 65 faceDetectionResult.boundingBoxes = new RectF[numberOfFaces]; | |
| 66 for (int i = 0; i < numberOfFaces; i++) { | |
| 67 final Face face = detectedFaces[i]; | |
| 68 final PointF midPoint = new PointF(); | |
| 69 face.getMidPoint(midPoint); | |
| 70 final float eyesDistance = face.eyesDistance(); | |
| 71 | |
| 72 RectF boundingBox = new RectF(); | |
| 73 boundingBox.x = midPoint.x - eyesDistance; | |
| 74 boundingBox.y = midPoint.y - eyesDistance; | |
| 75 boundingBox.width = 2 * eyesDistance; | |
| 76 boundingBox.height = 2 * eyesDistance; | |
| 77 | |
| 78 // TODO(xianglu): Consider adding Face.confidence and Face.pose. | |
| 79 faceDetectionResult.boundingBoxes[i] = boundingBox; | |
| 80 } | |
| 81 | |
| 82 callback.call(faceDetectionResult); | |
| 83 } | |
| 84 | |
| 85 @Override | |
| 86 public void close() {} | |
| 87 | |
| 88 @Override | |
| 89 public void onConnectionError(MojoException e) { | |
| 90 close(); | |
| 91 } | |
| 92 } | |
| OLD | NEW |