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