From 5e15b80e801a0110bc1bad1190f02cb9c7d22e37 Mon Sep 17 00:00:00 2001 From: Chien-Yu Chen Date: Thu, 13 Nov 2014 13:41:23 -0800 Subject: CameraService: normalize face rectangles properly Use android.scaler.cropRegion reported in the capture result to normalize face rectangles instead of using the one in current capture request. Bug: 11460393 Change-Id: Id21834bf6ae1f7cc106b4dffb98f9f249a75034b --- .../api1/client2/FrameProcessor.cpp | 49 ++++++++---- .../libcameraservice/api1/client2/Parameters.cpp | 86 +++++++++++----------- .../libcameraservice/api1/client2/Parameters.h | 28 ++++--- 3 files changed, 90 insertions(+), 73 deletions(-) (limited to 'services') diff --git a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp index 312a78c..40d53b3 100644 --- a/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp +++ b/services/camera/libcameraservice/api1/client2/FrameProcessor.cpp @@ -168,6 +168,19 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, faceIds = entry.data.i32; } + entry = frame.find(ANDROID_SCALER_CROP_REGION); + if (entry.count < 4) { + ALOGE("%s: Camera %d: Unable to read crop region (count = %d)", + __FUNCTION__, client->getCameraId(), entry.count); + return res; + } + + Parameters::CropRegion scalerCrop = { + static_cast(entry.data.i32[0]), + static_cast(entry.data.i32[1]), + static_cast(entry.data.i32[2]), + static_cast(entry.data.i32[3])}; + faces.setCapacity(metadata.number_of_faces); size_t maxFaces = metadata.number_of_faces; @@ -183,26 +196,30 @@ status_t FrameProcessor::processFaceDetect(const CameraMetadata &frame, camera_face_t face; - face.rect[0] = l.mParameters.arrayXToNormalized(faceRects[i*4 + 0]); - face.rect[1] = l.mParameters.arrayYToNormalized(faceRects[i*4 + 1]); - face.rect[2] = l.mParameters.arrayXToNormalized(faceRects[i*4 + 2]); - face.rect[3] = l.mParameters.arrayYToNormalized(faceRects[i*4 + 3]); + face.rect[0] = l.mParameters.arrayXToNormalizedWithCrop( + faceRects[i*4 + 0], scalerCrop); + face.rect[1] = l.mParameters.arrayYToNormalizedWithCrop( + faceRects[i*4 + 1], scalerCrop); + face.rect[2] = l.mParameters.arrayXToNormalizedWithCrop( + faceRects[i*4 + 2], scalerCrop); + face.rect[3] = l.mParameters.arrayYToNormalizedWithCrop( + faceRects[i*4 + 3], scalerCrop); face.score = faceScores[i]; if (faceDetectMode == ANDROID_STATISTICS_FACE_DETECT_MODE_FULL) { face.id = faceIds[i]; - face.left_eye[0] = - l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 0]); - face.left_eye[1] = - l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 1]); - face.right_eye[0] = - l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 2]); - face.right_eye[1] = - l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 3]); - face.mouth[0] = - l.mParameters.arrayXToNormalized(faceLandmarks[i*6 + 4]); - face.mouth[1] = - l.mParameters.arrayYToNormalized(faceLandmarks[i*6 + 5]); + face.left_eye[0] = l.mParameters.arrayXToNormalizedWithCrop( + faceLandmarks[i*6 + 0], scalerCrop); + face.left_eye[1] = l.mParameters.arrayYToNormalizedWithCrop( + faceLandmarks[i*6 + 1], scalerCrop); + face.right_eye[0] = l.mParameters.arrayXToNormalizedWithCrop( + faceLandmarks[i*6 + 2], scalerCrop); + face.right_eye[1] = l.mParameters.arrayYToNormalizedWithCrop( + faceLandmarks[i*6 + 3], scalerCrop); + face.mouth[0] = l.mParameters.arrayXToNormalizedWithCrop( + faceLandmarks[i*6 + 4], scalerCrop); + face.mouth[1] = l.mParameters.arrayYToNormalizedWithCrop( + faceLandmarks[i*6 + 5], scalerCrop); } else { face.id = 0; face.left_eye[0] = face.left_eye[1] = -2000; diff --git a/services/camera/libcameraservice/api1/client2/Parameters.cpp b/services/camera/libcameraservice/api1/client2/Parameters.cpp index 42a5507..74bbb9d 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.cpp +++ b/services/camera/libcameraservice/api1/client2/Parameters.cpp @@ -2619,75 +2619,71 @@ int Parameters::normalizedYToCrop(int y) const { return (y + 1000) * (previewCrop.height - 1) / 2000; } -int Parameters::arrayXToCrop(int x) const { - CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW); - return x - previewCrop.left; -} - -int Parameters::arrayYToCrop(int y) const { - CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW); - return y - previewCrop.top; -} +int Parameters::normalizedXToArray(int x) const { -int Parameters::cropXToNormalized(int x) const { - CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW); - return x * 2000 / (previewCrop.width - 1) - 1000; -} + // Work-around for HAL pre-scaling the coordinates themselves + if (quirks.meteringCropRegion) { + return (x + 1000) * (fastInfo.arrayWidth - 1) / 2000; + } -int Parameters::cropYToNormalized(int y) const { - CropRegion previewCrop = calculateCropRegion(CropRegion::OUTPUT_PREVIEW); - return y * 2000 / (previewCrop.height - 1) - 1000; + return cropXToArray(normalizedXToCrop(x)); } -int Parameters::arrayXToNormalized(int width) const { - int ret = cropXToNormalized(arrayXToCrop(width)); - - ALOG_ASSERT(ret >= -1000, "Calculated normalized value out of " - "lower bounds %d", ret); - ALOG_ASSERT(ret <= 1000, "Calculated normalized value out of " - "upper bounds %d", ret); - +int Parameters::normalizedYToArray(int y) const { // Work-around for HAL pre-scaling the coordinates themselves if (quirks.meteringCropRegion) { - return width * 2000 / (fastInfo.arrayWidth - 1) - 1000; + return (y + 1000) * (fastInfo.arrayHeight - 1) / 2000; } - return ret; + return cropYToArray(normalizedYToCrop(y)); } -int Parameters::arrayYToNormalized(int height) const { - int ret = cropYToNormalized(arrayYToCrop(height)); - ALOG_ASSERT(ret >= -1000, "Calculated normalized value out of lower bounds" - " %d", ret); - ALOG_ASSERT(ret <= 1000, "Calculated normalized value out of upper bounds" - " %d", ret); +Parameters::CropRegion Parameters::calculatePreviewCrop( + const CropRegion &scalerCrop) const { + float left, top, width, height; + float previewAspect = static_cast(previewWidth) / previewHeight; + float cropAspect = scalerCrop.width / scalerCrop.height; - // Work-around for HAL pre-scaling the coordinates themselves - if (quirks.meteringCropRegion) { - return height * 2000 / (fastInfo.arrayHeight - 1) - 1000; + if (previewAspect > cropAspect) { + width = scalerCrop.width; + height = cropAspect * scalerCrop.height / previewAspect; + + left = scalerCrop.left; + top = scalerCrop.top + (scalerCrop.height - height) / 2; + } else { + width = previewAspect * scalerCrop.width / cropAspect; + height = scalerCrop.height; + + left = scalerCrop.left + (scalerCrop.width - width) / 2; + top = scalerCrop.top; } - return ret; -} + CropRegion previewCrop = {left, top, width, height}; -int Parameters::normalizedXToArray(int x) const { + return previewCrop; +} +int Parameters::arrayXToNormalizedWithCrop(int x, + const CropRegion &scalerCrop) const { // Work-around for HAL pre-scaling the coordinates themselves if (quirks.meteringCropRegion) { - return (x + 1000) * (fastInfo.arrayWidth - 1) / 2000; + return x * 2000 / (fastInfo.arrayWidth - 1) - 1000; + } else { + CropRegion previewCrop = calculatePreviewCrop(scalerCrop); + return (x - previewCrop.left) * 2000 / (previewCrop.width - 1) - 1000; } - - return cropXToArray(normalizedXToCrop(x)); } -int Parameters::normalizedYToArray(int y) const { +int Parameters::arrayYToNormalizedWithCrop(int y, + const CropRegion &scalerCrop) const { // Work-around for HAL pre-scaling the coordinates themselves if (quirks.meteringCropRegion) { - return (y + 1000) * (fastInfo.arrayHeight - 1) / 2000; + return y * 2000 / (fastInfo.arrayHeight - 1) - 1000; + } else { + CropRegion previewCrop = calculatePreviewCrop(scalerCrop); + return (y - previewCrop.top) * 2000 / (previewCrop.height - 1) - 1000; } - - return cropYToArray(normalizedYToCrop(y)); } status_t Parameters::getFilteredSizes(Size limit, Vector *sizes) { diff --git a/services/camera/libcameraservice/api1/client2/Parameters.h b/services/camera/libcameraservice/api1/client2/Parameters.h index 815cc55..389cb92 100644 --- a/services/camera/libcameraservice/api1/client2/Parameters.h +++ b/services/camera/libcameraservice/api1/client2/Parameters.h @@ -325,13 +325,17 @@ struct Parameters { // Note that this doesn't apply to the (deprecated) single FPS value. static const int kFpsToApiScale = 1000; - // Transform between (-1000,-1000)-(1000,1000) normalized coords from camera - // API and HAL2 (0,0)-(activePixelArray.width/height) coordinates - int arrayXToNormalized(int width) const; - int arrayYToNormalized(int height) const; + // Transform from (-1000,-1000)-(1000,1000) normalized coords from camera + // API to HAL2 (0,0)-(activePixelArray.width/height) coordinates int normalizedXToArray(int x) const; int normalizedYToArray(int y) const; + // Transform from HAL3 (0,0)-(activePixelArray.width/height) coordinates to + // (-1000,-1000)-(1000,1000) normalized coordinates given a scaler crop + // region. + int arrayXToNormalizedWithCrop(int x, const CropRegion &scalerCrop) const; + int arrayYToNormalizedWithCrop(int y, const CropRegion &scalerCrop) const; + struct Range { int min; int max; @@ -341,20 +345,20 @@ struct Parameters { private: - // Convert between HAL2 sensor array coordinates and - // viewfinder crop-region relative array coordinates + // Convert from viewfinder crop-region relative array coordinates + // to HAL2 sensor array coordinates int cropXToArray(int x) const; int cropYToArray(int y) const; - int arrayXToCrop(int x) const; - int arrayYToCrop(int y) const; - // Convert between viewfinder crop-region relative array coordinates - // and camera API (-1000,1000)-(1000,1000) normalized coords - int cropXToNormalized(int x) const; - int cropYToNormalized(int y) const; + // Convert from camera API (-1000,1000)-(1000,1000) normalized coords + // to viewfinder crop-region relative array coordinates int normalizedXToCrop(int x) const; int normalizedYToCrop(int y) const; + // Given a scaler crop region, calculate preview crop region based on + // preview aspect ratio. + CropRegion calculatePreviewCrop(const CropRegion &scalerCrop) const; + Vector availablePreviewSizes; Vector availableVideoSizes; // Get size list (that are no larger than limit) from static metadata. -- cgit v1.1