1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 18 package android.hardware.camera2.params; 19 20 import android.graphics.Point; 21 import android.graphics.Rect; 22 import android.hardware.camera2.CameraCharacteristics; 23 import android.hardware.camera2.CameraMetadata; 24 import android.hardware.camera2.CaptureResult; 25 26 /** 27 * Describes a face detected in an image. 28 */ 29 public final class Face { 30 31 /** 32 * The ID is {@code -1} when the optional set of fields is unsupported. 33 * 34 * @see Face#Face(Rect, int) 35 * @see #getId() 36 */ 37 public static final int ID_UNSUPPORTED = -1; 38 39 /** 40 * The minimum possible value for the confidence level. 41 * 42 * @see #getScore() 43 */ 44 public static final int SCORE_MIN = 1; 45 46 /** 47 * The maximum possible value for the confidence level. 48 * 49 * @see #getScore() 50 */ 51 public static final int SCORE_MAX = 100; 52 53 private final Rect mBounds; 54 private final int mScore; 55 private final int mId; 56 private final Point mLeftEye; 57 private final Point mRightEye; 58 private final Point mMouth; 59 60 /** 61 * Create a new face with all fields set. 62 * 63 * <p>The id, leftEyePosition, rightEyePosition, and mouthPosition are considered optional. 64 * They are only required when the {@link CaptureResult} reports that the value of key 65 * {@link CaptureResult#STATISTICS_FACE_DETECT_MODE} is 66 * {@link CameraMetadata#STATISTICS_FACE_DETECT_MODE_FULL}. 67 * If the id is {@value #ID_UNSUPPORTED} then the leftEyePosition, rightEyePosition, and 68 * mouthPositions are guaranteed to be {@code null}. Otherwise, each of leftEyePosition, 69 * rightEyePosition, and mouthPosition may be independently null or not-null.</p> 70 * 71 * @param bounds Bounds of the face. 72 * @param score Confidence level between {@value #SCORE_MIN}-{@value #SCORE_MAX}. 73 * @param id A unique ID per face visible to the tracker. 74 * @param leftEyePosition The position of the left eye. 75 * @param rightEyePosition The position of the right eye. 76 * @param mouthPosition The position of the mouth. 77 * 78 * @throws IllegalArgumentException 79 * if bounds is {@code null}, 80 * or if the confidence is not in the range of 81 * {@value #SCORE_MIN}-{@value #SCORE_MAX}, 82 * or if id is {@value #ID_UNSUPPORTED} and 83 * leftEyePosition/rightEyePosition/mouthPosition aren't all null, 84 * or else if id is negative. 85 * 86 * @hide 87 */ Face(Rect bounds, int score, int id, Point leftEyePosition, Point rightEyePosition, Point mouthPosition)88 public Face(Rect bounds, int score, int id, 89 Point leftEyePosition, Point rightEyePosition, Point mouthPosition) { 90 checkNotNull("bounds", bounds); 91 if (score < SCORE_MIN || score > SCORE_MAX) { 92 throw new IllegalArgumentException("Confidence out of range"); 93 } else if (id < 0 && id != ID_UNSUPPORTED) { 94 throw new IllegalArgumentException("Id out of range"); 95 } 96 if (id == ID_UNSUPPORTED) { 97 checkNull("leftEyePosition", leftEyePosition); 98 checkNull("rightEyePosition", rightEyePosition); 99 checkNull("mouthPosition", mouthPosition); 100 } 101 102 mBounds = bounds; 103 mScore = score; 104 mId = id; 105 mLeftEye = leftEyePosition; 106 mRightEye = rightEyePosition; 107 mMouth = mouthPosition; 108 } 109 110 /** 111 * Create a new face without the optional fields. 112 * 113 * <p>The id, leftEyePosition, rightEyePosition, and mouthPosition are considered optional. 114 * If the id is {@value #ID_UNSUPPORTED} then the leftEyePosition, rightEyePosition, and 115 * mouthPositions are guaranteed to be {@code null}. Otherwise, each of leftEyePosition, 116 * rightEyePosition, and mouthPosition may be independently null or not-null. When devices 117 * report the value of key {@link CaptureResult#STATISTICS_FACE_DETECT_MODE} as 118 * {@link CameraMetadata#STATISTICS_FACE_DETECT_MODE_SIMPLE} in {@link CaptureResult}, 119 * the face id of each face is expected to be {@value #ID_UNSUPPORTED}, the leftEyePosition, 120 * rightEyePosition, and mouthPositions are expected to be {@code null} for each face.</p> 121 * 122 * @param bounds Bounds of the face. 123 * @param score Confidence level between {@value #SCORE_MIN}-{@value #SCORE_MAX}. 124 * 125 * @throws IllegalArgumentException 126 * if bounds is {@code null}, 127 * or if the confidence is not in the range of 128 * {@value #SCORE_MIN}-{@value #SCORE_MAX}. 129 * 130 * @hide 131 */ Face(Rect bounds, int score)132 public Face(Rect bounds, int score) { 133 this(bounds, score, ID_UNSUPPORTED, 134 /*leftEyePosition*/null, /*rightEyePosition*/null, /*mouthPosition*/null); 135 } 136 137 /** 138 * Bounds of the face. 139 * 140 * <p>A rectangle relative to the sensor's 141 * {@link CameraCharacteristics#SENSOR_INFO_ACTIVE_ARRAY_SIZE}, with (0,0) 142 * representing the top-left corner of the active array rectangle.</p> 143 * 144 * <p>There is no constraints on the the Rectangle value other than it 145 * is not-{@code null}.</p> 146 */ getBounds()147 public Rect getBounds() { 148 return mBounds; 149 } 150 151 /** 152 * The confidence level for the detection of the face. 153 * 154 * <p>The range is {@value #SCORE_MIN} to {@value #SCORE_MAX}. 155 * {@value #SCORE_MAX} is the highest confidence.</p> 156 * 157 * <p>Depending on the device, even very low-confidence faces may be 158 * listed, so applications should filter out faces with low confidence, 159 * depending on the use case. For a typical point-and-shoot camera 160 * application that wishes to display rectangles around detected faces, 161 * filtering out faces with confidence less than half of {@value #SCORE_MAX} 162 * is recommended.</p> 163 * 164 * @see #SCORE_MAX 165 * @see #SCORE_MIN 166 */ getScore()167 public int getScore() { 168 return mScore; 169 } 170 171 /** 172 * An unique id per face while the face is visible to the tracker. 173 * 174 * <p> 175 * If the face leaves the field-of-view and comes back, it will get a new 176 * id.</p> 177 * 178 * <p>This is an optional field, may not be supported on all devices. 179 * If the id is {@value #ID_UNSUPPORTED} then the leftEyePosition, rightEyePosition, and 180 * mouthPositions are guaranteed to be {@code null}. Otherwise, each of leftEyePosition, 181 * rightEyePosition, and mouthPosition may be independently null or not-null. When devices 182 * report the value of key {@link CaptureResult#STATISTICS_FACE_DETECT_MODE} as 183 * {@link CameraMetadata#STATISTICS_FACE_DETECT_MODE_SIMPLE} in {@link CaptureResult}, 184 * the face id of each face is expected to be {@value #ID_UNSUPPORTED}.</p> 185 * 186 * <p>This value will either be {@value #ID_UNSUPPORTED} or 187 * otherwise greater than {@code 0}.</p> 188 * 189 * @see #ID_UNSUPPORTED 190 */ getId()191 public int getId() { 192 return mId; 193 } 194 195 /** 196 * The coordinates of the center of the left eye. 197 * 198 * <p>The coordinates are in 199 * the same space as the ones for {@link #getBounds}. This is an 200 * optional field, may not be supported on all devices. If not 201 * supported, the value will always be set to null. 202 * This value will always be null only if {@link #getId()} returns 203 * {@value #ID_UNSUPPORTED}.</p> 204 * 205 * @return The left eye position, or {@code null} if unknown. 206 */ getLeftEyePosition()207 public Point getLeftEyePosition() { 208 return mLeftEye; 209 } 210 211 /** 212 * The coordinates of the center of the right eye. 213 * 214 * <p>The coordinates are 215 * in the same space as the ones for {@link #getBounds}.This is an 216 * optional field, may not be supported on all devices. If not 217 * supported, the value will always be set to null. 218 * This value will always be null only if {@link #getId()} returns 219 * {@value #ID_UNSUPPORTED}.</p> 220 * 221 * @return The right eye position, or {@code null} if unknown. 222 */ getRightEyePosition()223 public Point getRightEyePosition() { 224 return mRightEye; 225 } 226 227 /** 228 * The coordinates of the center of the mouth. 229 * 230 * <p>The coordinates are in 231 * the same space as the ones for {@link #getBounds}. This is an optional 232 * field, may not be supported on all devices. If not 233 * supported, the value will always be set to null. 234 * This value will always be null only if {@link #getId()} returns 235 * {@value #ID_UNSUPPORTED}.</p> 236 * </p> 237 * 238 * @return The mouth position, or {@code null} if unknown. 239 */ getMouthPosition()240 public Point getMouthPosition() { 241 return mMouth; 242 } 243 244 /** 245 * Represent the Face as a string for debugging purposes. 246 */ 247 @Override toString()248 public String toString() { 249 return String.format("{ bounds: %s, score: %s, id: %d, " + 250 "leftEyePosition: %s, rightEyePosition: %s, mouthPosition: %s }", 251 mBounds, mScore, mId, mLeftEye, mRightEye, mMouth); 252 } 253 checkNotNull(String name, Object obj)254 private static void checkNotNull(String name, Object obj) { 255 if (obj == null) { 256 throw new IllegalArgumentException(name + " was required, but it was null"); 257 } 258 } 259 checkNull(String name, Object obj)260 private static void checkNull(String name, Object obj) { 261 if (obj != null) { 262 throw new IllegalArgumentException(name + " was required to be null, but it wasn't"); 263 } 264 } 265 } 266