From patchwork Mon Sep 23 09:30:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cheng-Hao Yang X-Patchwork-Id: 21331 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 508B7C0F1B for ; Mon, 23 Sep 2024 09:33:30 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6B2A163511; Mon, 23 Sep 2024 11:33:29 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="S/cfbqZX"; dkim-atps=neutral Received: from mail-pl1-x62c.google.com (mail-pl1-x62c.google.com [IPv6:2607:f8b0:4864:20::62c]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D27ED6037E for ; Mon, 23 Sep 2024 11:33:25 +0200 (CEST) Received: by mail-pl1-x62c.google.com with SMTP id d9443c01a7336-2068bee21d8so40480015ad.2 for ; Mon, 23 Sep 2024 02:33:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1727084004; x=1727688804; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5+PG4w4fqPObQDpO2iRBORfJQmqvEOjWQ7wghuQIuCM=; b=S/cfbqZXsBs4ey33IDiIWG91t6mIneDP2DlPz2RG0/HqtCnab+BQnK6x8wrxXse2+S uWzeU5I4DYHpmtZutzbyLbjtUbeaOLy3mMH2kuHSdD7GyvC7IC59rnfSsXscKIOHoUg8 jlYvmCyLWaT78Red7+bB9n3y9AwoD5ohZI+PE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727084004; x=1727688804; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5+PG4w4fqPObQDpO2iRBORfJQmqvEOjWQ7wghuQIuCM=; b=Ij9iFUKXSqx/HndJdPyU/9mdKfexRVWiSNL3YesejAbwzZUs1RYMvigNdcKm9XsKTM oCsTh9clXpAw4+cig2MI9JH+XsE4mE531tFdP4UyKAmCUnizt802JLWTeNTsq1wPRMBF RzGHUBK8GR9UYBzaYjT+w1L4vCZsPWucCcxxJR/TEJeaZ7yg5Bd0DoUKRjiVUvnl88ky wNIogxAO8Ij+upuQga0tKcR/u0zZlmsXIUMaAsaOZhhX2t4DIaI1zCjGQJBT41Vhds/N MM48YoRm6V2SvWWEyey9sunksESahbBxnhrwhPYflJD8rlXhNI1E2jhOypHUxHnIlzOV BGKQ== X-Gm-Message-State: AOJu0YyQhBYqSEY/t5miKysCB5mam2qstX7RdBJzPSAfBU1MP2lL14rW kOto48dy/pRL+1QLG1O3nE0ZqIlMcqCehlnPdfK7VYcCzghU5Ps6FtFtk98pG0NWEw35T2oQ4yU = X-Google-Smtp-Source: AGHT+IHhmkt25rJXdm6nntouFJ0CvUSgVNvWVmX4qUGe6sXV0vepge2iRRfM8+GHlIApYh2N2TqF+g== X-Received: by 2002:a17:902:e88f:b0:207:1722:37d4 with SMTP id d9443c01a7336-208d83db3c9mr149242845ad.33.1727084004101; Mon, 23 Sep 2024 02:33:24 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (0.223.81.34.bc.googleusercontent.com. [34.81.223.0]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-207946d6673sm129864995ad.158.2024.09.23.02.33.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 02:33:23 -0700 (PDT) From: Harvey Yang X-Google-Original-From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Yudhistira Erlandinata , Harvey Yang , Jacopo Mondi Subject: [PATCH v5 1/3] libcamera: Add rectangle two-point constructor Date: Mon, 23 Sep 2024 09:30:44 +0000 Message-ID: <20240923093317.3500444-2-chenghaoyang@google.com> X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog In-Reply-To: <20240923093317.3500444-1-chenghaoyang@google.com> References: <20240923093317.3500444-1-chenghaoyang@google.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Yudhistira Erlandinata Add a Rectangle constructor that accepts two points: topLeft and bottomRight. Signed-off-by: Yudhistira Erlandinata Co-developed-by: Harvey Yang Reviewed-by: Jacopo Mondi Reviewed-by: Kieran Bingham --- include/libcamera/geometry.h | 7 +++++++ src/libcamera/geometry.cpp | 7 +++++++ test/geometry.cpp | 14 ++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/include/libcamera/geometry.h b/include/libcamera/geometry.h index 3e6f0f5d..5949d55c 100644 --- a/include/libcamera/geometry.h +++ b/include/libcamera/geometry.h @@ -262,6 +262,13 @@ public: { } + constexpr Rectangle(const Point &point1, const Point &point2) + : Rectangle(std::min(point1.x, point2.x), std::max(point1.y, point2.y), + std::max(point1.x, point2.x) - std::min(point1.x, point2.x), + std::max(point1.y, point2.y) - std::min(point1.y, point2.y)) + { + } + int x; int y; unsigned int width; diff --git a/src/libcamera/geometry.cpp b/src/libcamera/geometry.cpp index 00015136..b608e4f0 100644 --- a/src/libcamera/geometry.cpp +++ b/src/libcamera/geometry.cpp @@ -629,6 +629,13 @@ std::ostream &operator<<(std::ostream &out, const SizeRange &sr) * \param[in] size The desired Rectangle size */ +/** + * \fn Rectangle::Rectangle(const Point &point1, const Point &point2) + * \brief Construct a Rectangle with the two given points + * \param[in] point1 One of the corner point of the rectangle + * \param[in] point2 The diagonal corner point from \a point1 + */ + /** * \var Rectangle::x * \brief The horizontal coordinate of the rectangle's top-left corner diff --git a/test/geometry.cpp b/test/geometry.cpp index 64169206..3ed2cc23 100644 --- a/test/geometry.cpp +++ b/test/geometry.cpp @@ -481,6 +481,20 @@ protected: return TestFail; } + Point topLeft(3, 3); + Point bottomRight(30, 30); + Point topRight(30, 3); + Point bottomLeft(3, 30); + Rectangle rect1(topLeft, bottomRight); + Rectangle rect2(topRight, bottomLeft); + Rectangle rect3(bottomRight, topLeft); + Rectangle rect4(bottomLeft, topRight); + + if (rect1 != rect2 || rect1 != rect3 || rect1 != rect4) { + cout << "Point-from-point construction failed" << endl; + return TestFail; + } + return TestPass; } }; From patchwork Mon Sep 23 09:30:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cheng-Hao Yang X-Patchwork-Id: 21332 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 39018C0F1B for ; Mon, 23 Sep 2024 09:33:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C62E863515; Mon, 23 Sep 2024 11:33:32 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="O+ZXrX4Q"; dkim-atps=neutral Received: from mail-pl1-x62d.google.com (mail-pl1-x62d.google.com [IPv6:2607:f8b0:4864:20::62d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 667F66350D for ; Mon, 23 Sep 2024 11:33:27 +0200 (CEST) Received: by mail-pl1-x62d.google.com with SMTP id d9443c01a7336-2053f6b8201so35684135ad.2 for ; Mon, 23 Sep 2024 02:33:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1727084005; x=1727688805; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=t65ZdH9k3KpYKYy8IWDtxVVxE0TR5J85hSoLMh0Yk9Q=; b=O+ZXrX4Q/HdSZaIn63SopqboL3ivWLntbYuo20jKYAJElO97vl80ZbJsC1Y2hd2wu0 Rv69+fsst60/VjV46dOZ8FLKgMJ44cx2/2j+eZEgg3HlNAMhK1MKZ4PfLlNp1SiSf4t0 yDTyWtauHBuJU1GDMGrxKUm/lZdCMwRGgwtgM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727084005; x=1727688805; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=t65ZdH9k3KpYKYy8IWDtxVVxE0TR5J85hSoLMh0Yk9Q=; b=FzW7k/Ozd3aClGZ0knSWak0hhxMbx1KcXvkDwvVuNqJV8fqUgY0Gn+HoOk+ROlBJkb yyk/YaAWQV6S2qWwNF8RBj0dpVLXcpXZVOdNfsOpnpEjQB+t13PNUtGmz1uibW9NE6eU V7lruAyfvfTxyt1ELzvvDCLZDdHDe7VQ6dH7Sbie4PBHFqAZ+X7pnPPZCNQrV7hVpBip L9frKs0VQ1Hccz/4CLSZqwijgR+pYdj+oE3jN+oc5tAAL6CLgf3gQQnlDgJjah/hn8Z1 HmigseNPGIwFTfTdr/MXJdte9udtU3J0NuK9AeWcvOjaUbiCytR5/9xm4AM5AwujV0wA k4Eg== X-Gm-Message-State: AOJu0YyZmw91dOMHTeuQZWThm3+sItaEOfdDijhyQLaWadtxjxh6iV0Y 1E/RVnfEijirA4qDL3i+xx2Epjagwu+NMYJ2GjSbjVuOkT3ybydVjnOj0JM1yPWKPs6gcA3V8qM = X-Google-Smtp-Source: AGHT+IEkbLYZeRTdH+vdsWFcjTyXLMXXflVO4aZxayTiUTXAcVB2pwp1NaHcAMDzkvNzafn4AcN8yw== X-Received: by 2002:a17:902:ebc4:b0:202:508c:b598 with SMTP id d9443c01a7336-208d9874d94mr139975645ad.59.1727084005621; Mon, 23 Sep 2024 02:33:25 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (0.223.81.34.bc.googleusercontent.com. [34.81.223.0]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-207946d6673sm129864995ad.158.2024.09.23.02.33.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 02:33:25 -0700 (PDT) From: Harvey Yang X-Google-Original-From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Yudhistira Erlandinata , becker hsieh , Harvey Yang Subject: [PATCH v5 2/3] libcamera: Add face detection controls Date: Mon, 23 Sep 2024 09:30:45 +0000 Message-ID: <20240923093317.3500444-3-chenghaoyang@google.com> X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog In-Reply-To: <20240923093317.3500444-1-chenghaoyang@google.com> References: <20240923093317.3500444-1-chenghaoyang@google.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Yudhistira Erlandinata Add FaceDetectMode, FaceDetectFaceRectangles, FaceDetectFaceScores, and FaceDetectFaceLandmark. Also add ControlTypePoint for supporting FaceDetectFaceLandmark. Signed-off-by: Yudhistira Erlandinata Co-developed-by: becker hsieh Co-developed-by: Harvey Yang Reviewed-by: Jacopo Mondi --- include/libcamera/controls.h | 6 ++ src/libcamera/control_ids_draft.yaml | 85 ++++++++++++++++++++++++++++ src/libcamera/controls.cpp | 6 ++ 3 files changed, 97 insertions(+) diff --git a/include/libcamera/controls.h b/include/libcamera/controls.h index 7c2bb287..bf1b8609 100644 --- a/include/libcamera/controls.h +++ b/include/libcamera/controls.h @@ -34,6 +34,7 @@ enum ControlType { ControlTypeString, ControlTypeRectangle, ControlTypeSize, + ControlTypePoint, }; namespace details { @@ -87,6 +88,11 @@ struct control_type { static constexpr ControlType value = ControlTypeSize; }; +template<> +struct control_type { + static constexpr ControlType value = ControlTypePoint; +}; + template struct control_type> : public control_type> { }; diff --git a/src/libcamera/control_ids_draft.yaml b/src/libcamera/control_ids_draft.yaml index 9bef5bf1..c0cf5320 100644 --- a/src/libcamera/control_ids_draft.yaml +++ b/src/libcamera/control_ids_draft.yaml @@ -227,4 +227,89 @@ controls: value. All of the custom test patterns will be static (that is the raw image must not vary from frame to frame). + - FaceDetectMode: + type: uint8_t + description: | + Reporting mode of face detection. + + The number of faces in each list must be the same. + + Currently identical to ANDROID_STATISTICS_FACE_DETECT_MODE. + + \sa FaceDetectFaceRectangles + \sa FaceDetectFaceScores + \sa FaceDetectFaceLandmarks + \sa FaceDetectFaceIds + + enum: + - name: FaceDetectModeOff + value: 0 + description: | + Pipeline should not report face detection result. + - name: FaceDetectModeSimple + value: 1 + description: | + Pipeline should at least report FaceDetectFaceRectangles and + FaceDetectFaceScores for each detected faces. + FaceDetectFaceLandmarks and FaceDetectFaceIds is optional. + + - name: FaceDetectModeFull + value: 2 + description: | + Pipeline should report all face controls, including + FaceDetectFaceRectangles, FaceDetectFaceScores, + FaceDetectFaceLandmarks, and FaceDeteceFaceIds. + + - FaceDetectFaceRectangles: + type: Rectangle + description: | + Boundary rectangles of the detected faces. + The number of values should be the number of faces. + + The FaceDetectFaceRectangles control can only be returned in metadata. + + Currently identical to ANDROID_STATISTICS_FACE_RECTANGLES. + + size: [n] + + - FaceDetectFaceScores: + type: uint8_t + description: | + Confidence score of each of the detected faces by face detector. + The range of score is [0, 100]. + The FaceDetectFaceScores control can only be returned in metadata. + The number of values should be the number of faces. + + Currently identical to ANDROID_STATISTICS_FACE_SCORES. + + size: [n] + + - FaceDetectFaceLandmarks: + type: Point + description: | + Array of human face landmark coordinates in format: + [..., left_eye_i, right_eye_i, mouth_i, left_eye_i+1, ...], + with i = index of face. + The number of values should be 3 * the number of faces. + + The FaceDetectFaceLandmarks control can only be returned in metadata. + + Currently identical to ANDROID_STATISTICS_FACE_LANDMARKS. + + size: [n] + + - FaceDetectFaceIds: + type: int32_t + description: | + Each detected face is given a unique ID that is valid for as long as + the face is visible to the camera device. A face that leaves the field + of view and later returns may be assigned a new ID. + The number of values should be the number of faces. + + The FaceDetectFaceIds control can only be returned in metadata. + + Currently identical to ANDROID_STATISTICS_FACE_IDS. + + size: [n] + ... diff --git a/src/libcamera/controls.cpp b/src/libcamera/controls.cpp index dba74404..c452e607 100644 --- a/src/libcamera/controls.cpp +++ b/src/libcamera/controls.cpp @@ -60,6 +60,7 @@ static constexpr size_t ControlValueSize[] = { [ControlTypeString] = sizeof(char), [ControlTypeRectangle] = sizeof(Rectangle), [ControlTypeSize] = sizeof(Size), + [ControlTypePoint] = sizeof(Point), }; } /* namespace */ @@ -254,6 +255,11 @@ std::string ControlValue::toString() const str += value->toString(); break; } + case ControlTypePoint: { + const Point *value = reinterpret_cast(data); + str += value->toString(); + break; + } case ControlTypeNone: case ControlTypeString: break; From patchwork Mon Sep 23 09:30:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cheng-Hao Yang X-Patchwork-Id: 21333 Return-Path: X-Original-To: parsemail@patchwork.libcamera.org Delivered-To: parsemail@patchwork.libcamera.org Received: from lancelot.ideasonboard.com (lancelot.ideasonboard.com [92.243.16.209]) by patchwork.libcamera.org (Postfix) with ESMTPS id 4E145C0F1B for ; Mon, 23 Sep 2024 09:33:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F037663511; Mon, 23 Sep 2024 11:33:35 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="lfINlWdX"; dkim-atps=neutral Received: from mail-pl1-x629.google.com (mail-pl1-x629.google.com [IPv6:2607:f8b0:4864:20::629]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7C67C63512 for ; Mon, 23 Sep 2024 11:33:29 +0200 (CEST) Received: by mail-pl1-x629.google.com with SMTP id d9443c01a7336-20543fdb7acso32164775ad.1 for ; Mon, 23 Sep 2024 02:33:29 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1727084007; x=1727688807; darn=lists.libcamera.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=E/ouNh/kwG+GNdwoclRM6KB8psYsFquTmInQtIIqDoo=; b=lfINlWdX0uepLGFx2Rm0v+xBB7sADGcc1W93gpdKcv2vC6xaFDQSJXxrRvBTaeaqze oviDYh2zeCNpCD1VET3IdMJ3fLGkOvSYjmr9JbR3YR1qMH9HVF6+8sQ70rjJAi3CDxRn 7nP6vsfT+hWYdD/nYzxL+fHeov3Dxi99KW9GU= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727084007; x=1727688807; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=E/ouNh/kwG+GNdwoclRM6KB8psYsFquTmInQtIIqDoo=; b=gg0Z8gQIf/NQOxS+/fBu8pu6nNupxIfbRF00L+UvWeP+Yz9dGZIdlZUjbGhaonfDKq Nv3gAkpInuczOeP46kmAraRuFL83fAa9H142ivecW6MU2oAYiYlwA/CDhJRGpXX31FTE 1jhTgH+fFGXI5rLWjq6+M1NtLWYSfIBKkedvsuINYCyGEANq2WdWSw2FKqlZ0H6p0i23 PJN/FQDDb+D0Id4XUfjtwI62M92rmQ+m6SLavId2Zzpkd8kDJzqPUdre0YSfZl6iuyz2 tG7E6VpHa1Ok2nGJFF++NGmiJ1mHKza7vhMO4iM9kzVQk3+muSfuSjdnnryCenVJt6xZ sQYA== X-Gm-Message-State: AOJu0YxXBzql14ST7zJ3R5UJfvAOP+xyWaSiN2xOHzQpNV+740hGiwpP FpFE0kKnEK/vI0MPBgy0kfCRlRLOjEac3mogxOuYPk4JxsKqWbJ3yiB6DRWaIDWh8U1biqiiQ4o = X-Google-Smtp-Source: AGHT+IEuwNS3OjMSCvrsgnygm4MnF/XedDDmd38zkxL/UQ4xfdkldOECJwo6L+sBzhv/w9l3kQE5sA== X-Received: by 2002:a17:902:cf4b:b0:200:869c:95e3 with SMTP id d9443c01a7336-208d8370e93mr191608335ad.4.1727084007163; Mon, 23 Sep 2024 02:33:27 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (0.223.81.34.bc.googleusercontent.com. [34.81.223.0]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-207946d6673sm129864995ad.158.2024.09.23.02.33.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 23 Sep 2024 02:33:26 -0700 (PDT) From: Harvey Yang X-Google-Original-From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Harvey Yang , Yudhistira Erlandinata Subject: [PATCH v5 3/3] libcamera: android: Add face detection control support Date: Mon, 23 Sep 2024 09:30:46 +0000 Message-ID: <20240923093317.3500444-4-chenghaoyang@google.com> X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog In-Reply-To: <20240923093317.3500444-1-chenghaoyang@google.com> References: <20240923093317.3500444-1-chenghaoyang@google.com> MIME-Version: 1.0 X-BeenThere: libcamera-devel@lists.libcamera.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libcamera-devel-bounces@lists.libcamera.org Sender: "libcamera-devel" From: Harvey Yang Allow Android HAL adapter to pass the face detection metadata control to the pipeline and also send face detection metadata to the camera client if the pipeline generates it. Signed-off-by: Yudhistira Erlandinata Co-developed-by: Harvey Yang Reviewed-by: Jacopo Mondi --- src/android/camera_capabilities.cpp | 45 +++++++++++++++-- src/android/camera_device.cpp | 75 ++++++++++++++++++++++++++++- 2 files changed, 114 insertions(+), 6 deletions(-) diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index 71043e12..a89a3115 100644 --- a/src/android/camera_capabilities.cpp +++ b/src/android/camera_capabilities.cpp @@ -7,6 +7,8 @@ #include "camera_capabilities.h" +#include + #include #include #include @@ -1176,11 +1178,46 @@ int CameraCapabilities::initializeStaticMetadata() maxFrameDuration_); /* Statistics static metadata. */ - uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; - staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, - faceDetectMode); - int32_t maxFaceCount = 0; + auto iter = camera_->controls().find(controls::draft::FaceDetectMode.id()); + if (iter != camera_->controls().end()) { + const ControlInfo &faceDetectCtrlInfo = iter->second; + std::vector faceDetectModes; + bool hasFaceDetection = false; + + for (const auto &value : faceDetectCtrlInfo.values()) { + uint8_t mode = value.get(); + uint8_t androidMode = 0; + + switch (mode) { + case controls::draft::FaceDetectModeOff: + androidMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; + break; + case controls::draft::FaceDetectModeSimple: + androidMode = ANDROID_STATISTICS_FACE_DETECT_MODE_SIMPLE; + hasFaceDetection = true; + break; + default: + LOG(HAL, Fatal) << "Received invalid face detect mode: " << mode; + } + faceDetectModes.push_back(androidMode); + } + if (hasFaceDetection) { + /* + * \todo Create new libcamera controls to query max + * possible faces detected. + */ + maxFaceCount = 10; + staticMetadata_->addEntry( + ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, + faceDetectModes.data(), faceDetectModes.size()); + } + } else { + uint8_t faceDetectMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; + staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_AVAILABLE_FACE_DETECT_MODES, + faceDetectMode); + } + staticMetadata_->addEntry(ANDROID_STATISTICS_INFO_MAX_FACE_COUNT, maxFaceCount); diff --git a/src/android/camera_device.cpp b/src/android/camera_device.cpp index 493f66e7..50caa14a 100644 --- a/src/android/camera_device.cpp +++ b/src/android/camera_device.cpp @@ -15,6 +15,7 @@ #include #include +#include #include #include @@ -22,6 +23,7 @@ #include #include #include +#include #include #include "system/graphics.h" @@ -813,6 +815,11 @@ int CameraDevice::processControls(Camera3RequestDescriptor *descriptor) controls.set(controls::ScalerCrop, cropRegion); } + if (settings.getEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, &entry)) { + const uint8_t *data = entry.data.u8; + controls.set(controls::draft::FaceDetectMode, data[0]); + } + if (settings.getEntry(ANDROID_SENSOR_TEST_PATTERN_MODE, &entry)) { const int32_t data = *entry.data.i32; int32_t testPatternMode = controls::draft::TestPatternModeOff; @@ -1540,8 +1547,9 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons value32 = ANDROID_SENSOR_TEST_PATTERN_MODE_OFF; resultMetadata->addEntry(ANDROID_SENSOR_TEST_PATTERN_MODE, value32); - value = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; - resultMetadata->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, value); + settings.getEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, &entry); + resultMetadata->addEntry(ANDROID_STATISTICS_FACE_DETECT_MODE, + entry.data.u8, 1); value = ANDROID_STATISTICS_LENS_SHADING_MAP_MODE_OFF; resultMetadata->addEntry(ANDROID_STATISTICS_LENS_SHADING_MAP_MODE, @@ -1580,6 +1588,69 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons resultMetadata->addEntry(ANDROID_SENSOR_FRAME_DURATION, *frameDuration * 1000); + const auto &faceDetectRectangles = + metadata.get(controls::draft::FaceDetectFaceRectangles); + if (faceDetectRectangles) { + const Span rectangles = *faceDetectRectangles; + std::vector flatRectangles; + for (const Rectangle &rect : rectangles) { + flatRectangles.push_back(rect.x); + flatRectangles.push_back(rect.y); + flatRectangles.push_back(rect.x + rect.width); + flatRectangles.push_back(rect.y + rect.height); + } + resultMetadata->addEntry( + ANDROID_STATISTICS_FACE_RECTANGLES, flatRectangles); + } + + const auto &faceDetectFaceScores = + metadata.get(controls::draft::FaceDetectFaceScores); + if (faceDetectRectangles && faceDetectFaceScores) { + const Span &scores = *faceDetectFaceScores; + if (scores.size() != faceDetectRectangles->size()) { + LOG(HAL, Error) << "Pipeline returned wrong number of face scores; " + << "Expected: " + << faceDetectRectangles->size() + << ", got:" << scores.size(); + } + resultMetadata->addEntry(ANDROID_STATISTICS_FACE_SCORES, scores); + } + + const auto &faceDetectFaceLandmarks = + metadata.get(controls::draft::FaceDetectFaceLandmarks); + if (faceDetectRectangles && faceDetectFaceScores && + faceDetectFaceLandmarks) { + const auto &landmarks = *faceDetectFaceLandmarks; + size_t expectedLandmarks = faceDetectRectangles->size() * 3; + if (landmarks.size() != expectedLandmarks) { + LOG(HAL, Error) << "Pipeline returned wrong number of face landmarks; " + << "Expected: " << expectedLandmarks + << ", got: " << landmarks.size(); + } + + std::vector androidLandmarks; + for (const auto &landmark : landmarks) { + androidLandmarks.push_back(landmark.x); + androidLandmarks.push_back(landmark.y); + } + resultMetadata->addEntry( + ANDROID_STATISTICS_FACE_LANDMARKS, androidLandmarks); + } + + const auto &faceDetectFaceIds = + metadata.get(controls::draft::FaceDetectFaceIds); + if (faceDetectRectangles && faceDetectFaceScores && + faceDetectFaceLandmarks && faceDetectFaceIds) { + const Span &ids = *faceDetectFaceIds; + if (ids.size() != faceDetectRectangles->size()) { + LOG(HAL, Error) << "Pipeline returned wrong number of face ids; " + << "Expected: " + << faceDetectRectangles->size() + << ", got:" << ids.size(); + } + resultMetadata->addEntry(ANDROID_STATISTICS_FACE_IDS, ids); + } + const auto &scalerCrop = metadata.get(controls::ScalerCrop); if (scalerCrop) { const Rectangle &crop = *scalerCrop;