Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5e15b80e authored by Chien-Yu Chen's avatar Chien-Yu Chen
Browse files

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
parent 745602d8
Loading
Loading
Loading
Loading
+33 −16
Original line number Diff line number Diff line
@@ -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<float>(entry.data.i32[0]),
            static_cast<float>(entry.data.i32[1]),
            static_cast<float>(entry.data.i32[2]),
            static_cast<float>(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;
+41 −45
Original line number Diff line number Diff line
@@ -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<float>(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;

    return ret;
        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;
    }

int Parameters::normalizedXToArray(int x) const {
    CropRegion previewCrop = {left, top, width, height};

    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<Size> *sizes) {
+16 −12
Original line number Diff line number Diff line
@@ -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<Size> availablePreviewSizes;
    Vector<Size> availableVideoSizes;
    // Get size list (that are no larger than limit) from static metadata.