From patchwork Tue Sep 24 11:02: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: 21343 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 DC814C0F1B for ; Tue, 24 Sep 2024 11:04:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 158D263513; Tue, 24 Sep 2024 13:04:05 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="FahYZNLq"; dkim-atps=neutral Received: from mail-pg1-x52d.google.com (mail-pg1-x52d.google.com [IPv6:2607:f8b0:4864:20::52d]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E695063500 for ; Tue, 24 Sep 2024 13:04:01 +0200 (CEST) Received: by mail-pg1-x52d.google.com with SMTP id 41be03b00d2f7-7d4f85766f0so4412500a12.2 for ; Tue, 24 Sep 2024 04:04:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1727175840; x=1727780640; 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=tBhL4xEvsxdss/ASWIxhXN6eYcF3o/Wyd4aQEAOsBrg=; b=FahYZNLqt2rl4hJLp0x1jjUNeqSLPFsH2t5RbNwmwBRI+cc/c849W3RY8oej05U6W3 h0Hapo0gDSkgbvGWVke+evAdLjdwFZhtob5Ar8drZO24rvcenEfEuNOO4LpvM6SBcaoX s7MwnnSH/lOXu0y/PKkDe+eOQnXX1fp8uJgkI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727175840; x=1727780640; 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=tBhL4xEvsxdss/ASWIxhXN6eYcF3o/Wyd4aQEAOsBrg=; b=BHIsgZfHhX2cWgwqlV8vE2y9WXNHQ/e5e1jyMHqadNBfEy0Y2A4E6+aWuls1/EQ8Yu o5EKLS+9mYeWAFUjI3MjQ36L92U0A1Qi8WpDq18e6eKqbFcQ0IzZlKrCNS4q+X04vdqK GAtjOKJoUABeYDEcJA9foyPZ5rWWOQVmxuz5Mc4gVU1aNtmEqaabu6gmfZ1r2/M59eI7 ZzSebejlKNYhwJCkWcLvZxk0ZXX9y5zoNXL2X62/G4fOk8IPRvXaLgmcC7W2ExUtZGDq TNOzo5V4wmhuzepA+ah511rJrINHD1a/bUIZ2Nj8wxrj7hCt4jQ1r7m+bSFpoCeTrb0w pPvg== X-Gm-Message-State: AOJu0YzA93dP1TKs9ihh0RhypH76h4XD7fBE1RFXEr5HUel7vdY/PCYO fU/RwO5NaYB46vuMfOB6BTDXSrmn8BKX6jgymrMCh+IhMF8EdQ3qEBcbdyXUItTb+T6/LQxZ8fk = X-Google-Smtp-Source: AGHT+IG1M9lyMeWoMjzcxqNis2T6ntd6MqQMTJ80QPDeKDr5IqagisbDRoIp0jiWlXhj1ywg+ZnxyQ== X-Received: by 2002:a05:6a21:1193:b0:1d2:e1cc:649c with SMTP id adf61e73a8af0-1d30a91f295mr19977155637.15.1727175840127; Tue, 24 Sep 2024 04:04:00 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (208.158.221.35.bc.googleusercontent.com. [35.221.158.208]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71afc9833c3sm993326b3a.182.2024.09.24.04.03.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Sep 2024 04:03:59 -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 v7 1/3] libcamera: Add rectangle two-point constructor Date: Tue, 24 Sep 2024 11:02:44 +0000 Message-ID: <20240924110353.2025397-2-chenghaoyang@google.com> X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog In-Reply-To: <20240924110353.2025397-1-chenghaoyang@google.com> References: <20240924110353.2025397-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 --- 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..3c47dcdc 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 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 Tue Sep 24 11:02: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: 21344 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 D025EC0F1B for ; Tue, 24 Sep 2024 11:04:09 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 68BB663510; Tue, 24 Sep 2024 13:04:09 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="F7J2m8eL"; dkim-atps=neutral Received: from mail-pg1-x530.google.com (mail-pg1-x530.google.com [IPv6:2607:f8b0:4864:20::530]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B1B146350B for ; Tue, 24 Sep 2024 13:04:03 +0200 (CEST) Received: by mail-pg1-x530.google.com with SMTP id 41be03b00d2f7-7e6b738acd5so280989a12.0 for ; Tue, 24 Sep 2024 04:04:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1727175842; x=1727780642; 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=nD1aTGFoZhor1a0602dxtuqbeRDiOtQLq2EYFIgL/IE=; b=F7J2m8eLCTBdWzZ43yMy3urRtz4MYQ47Nz/DYznWLjyTh2Ds3DTCydaiXBiAb8fwj9 tyb+0VRloAPddmxo16RyPCMhbTa9AX0RdE0xT56zPYG9Grq7dCIpCksmLE+gYoo2w6Ht 5kLv/v0obggtfNuHFOatKSRYuuXT4wUm8hBtw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727175842; x=1727780642; 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=nD1aTGFoZhor1a0602dxtuqbeRDiOtQLq2EYFIgL/IE=; b=TCL/q4aAZtpesat6GjcfBCzFGOPUbN94CJoN6s486mM0EOCev5vFcPh7ZWU47P16Ob Ha8hIeePcqmE0PvhJkxuHYWHK2kRJlUqmSWJUINj/7pbJfGELc4q73WkaixErswKaffj mdx6ISMOuXN9kqqMtqgj7r0UqXPytJFGCDXitnwfeRy51y9jyWvxXuFiguQqnsXTCYai awl0fuiZXVajno9fAnHLC8aFnxfua2VKppKNxrdyz6dBuZwnsVeJz6ZBAMrGwsVDy/m4 k0L26TRKD1rOIeJaG/KVwESpoh+teo5vbEeFQFMpwW0ep/qgo8bfVHBvE5kzhZzg/W1k mOiw== X-Gm-Message-State: AOJu0YwIafGsx/2JFKCFp+ZdlEmaayb/I6zXGbQmrbvhk6pj4SsmnwWC 6/gDHa/2jC4SsQlUhq8hnl3hMurWlTtRXpwwRr7To5lYJ9ltJdZ9lMNEoMzjAEdMaVyScq2mwb4 = X-Google-Smtp-Source: AGHT+IGzvYP/LLry8S2fgbwzQ4FQ/tzj8rWvO5lQeLg/d5ilMhUDHOWDSARKHCGXrio72lSAVzks1Q== X-Received: by 2002:a05:6a20:e605:b0:1d1:13de:68c6 with SMTP id adf61e73a8af0-1d30ca220ddmr18164417637.29.1727175841658; Tue, 24 Sep 2024 04:04:01 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (208.158.221.35.bc.googleusercontent.com. [35.221.158.208]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71afc9833c3sm993326b3a.182.2024.09.24.04.04.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Sep 2024 04:04:01 -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 v7 2/3] libcamera: Add face detection controls Date: Tue, 24 Sep 2024 11:02:45 +0000 Message-ID: <20240924110353.2025397-3-chenghaoyang@google.com> X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog In-Reply-To: <20240924110353.2025397-1-chenghaoyang@google.com> References: <20240924110353.2025397-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 ++ include/libcamera/meson.build | 3 +- src/libcamera/control_ids_android.yaml | 98 ++++++++++++++++++++++++++ src/libcamera/control_ranges.yaml | 4 +- src/libcamera/controls.cpp | 6 ++ 5 files changed, 115 insertions(+), 2 deletions(-) create mode 100644 src/libcamera/control_ids_android.yaml 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/include/libcamera/meson.build b/include/libcamera/meson.build index a969a95d..4fff14d2 100644 --- a/include/libcamera/meson.build +++ b/include/libcamera/meson.build @@ -34,6 +34,7 @@ libcamera_headers_install_dir = get_option('includedir') / libcamera_include_dir controls_map = { 'controls': { + 'android': 'control_ids_android.yaml', 'draft': 'control_ids_draft.yaml', 'core': 'control_ids_core.yaml', 'rpi/vc4': 'control_ids_rpi.yaml', @@ -55,7 +56,7 @@ foreach mode, entry : controls_map files_list = [] input_files = [] foreach vendor, header : entry - if vendor != 'core' and vendor != 'draft' + if vendor != 'core' and vendor != 'draft' and vendor != 'android' if vendor not in pipelines continue endif diff --git a/src/libcamera/control_ids_android.yaml b/src/libcamera/control_ids_android.yaml new file mode 100644 index 00000000..8b0d624f --- /dev/null +++ b/src/libcamera/control_ids_android.yaml @@ -0,0 +1,98 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later +# +# Copyright (C) 2024, Google Inc. +# +%YAML 1.1 +--- +# Unless otherwise stated, all controls are bi-directional, i.e. they can be +# set through Request::controls() and returned out through Request::metadata(). +vendor: android +controls: + - FaceDetectMode: + type: uint8_t + description: | + Reporting mode of face detection. + + 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 reported in + FaceDetectFaceRectangles. + + 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 reported in + FaceDetectFaceRectangles. + + 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 reported in + FaceDetectFaceRectangles. + + 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 reported in + FaceDetectFaceRectangles. + + The FaceDetectFaceIds control can only be returned in metadata. + + Currently identical to ANDROID_STATISTICS_FACE_IDS. + + size: [n] + +... diff --git a/src/libcamera/control_ranges.yaml b/src/libcamera/control_ranges.yaml index d42447d0..9d406f10 100644 --- a/src/libcamera/control_ranges.yaml +++ b/src/libcamera/control_ranges.yaml @@ -13,6 +13,8 @@ ranges: draft: 10000 # Raspberry Pi vendor controls rpi: 20000 - # Next range starts at 30000 + # Android metadata related controls + android: 30000 + # Next range starts at 40000 ... 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 Tue Sep 24 11:02: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: 21345 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 3E550C32D4 for ; Tue, 24 Sep 2024 11:04:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A01AA63512; Tue, 24 Sep 2024 13:04:10 +0200 (CEST) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="L8IUGEpz"; dkim-atps=neutral Received: from mail-pf1-x433.google.com (mail-pf1-x433.google.com [IPv6:2607:f8b0:4864:20::433]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 89D3A63515 for ; Tue, 24 Sep 2024 13:04:05 +0200 (CEST) Received: by mail-pf1-x433.google.com with SMTP id d2e1a72fcca58-718d6ad6050so3931280b3a.0 for ; Tue, 24 Sep 2024 04:04:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; t=1727175844; x=1727780644; 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=BBYIDOTmFw8r0qJaHkYpTkkfYv9NhuFdtJGkrKUY5TI=; b=L8IUGEpzFBpV2XzXDjDNsKa97jEB8ABfCaJ/+gZFv+zUcQSxDiz1Hin9m553mWdrtQ Yo+DjFze4LrpiqDSuOZSyG5aTcGPyZpiKIddXUokqhmqNwnHOxk5mAXJiUG5oPyx+Q/+ pVuQ9Dtvln2Y07Dcc4t4ahRF8N5aijzlXLUBM= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727175844; x=1727780644; 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=BBYIDOTmFw8r0qJaHkYpTkkfYv9NhuFdtJGkrKUY5TI=; b=ixkUEbsdlEm6NIcnLvVdLmZ2gd9XjnhDRuwO91T+TkgxJy/Bk0XeINtE7O3CIBSoV4 V1RvU9X7dwT02w59rJc8YB1a1SitkN74YQmzyIRfWBO2oCVI2aciP9snJ5OKWJNxpxid pyL3Nrvn9ArUgsNzszsQZ0AymdRfn3J5cJrmlx7y6MPpgiRdzfFyZcmQb3KVG73lL6cL 6rko2yZ0mhzt9TtioLhV4IxRFMYd0q7UGZYiaOCyPR9/WYr/x/NMjBZGWj/9PjKTfQ+8 VQLjc8y8X3pvTzVSqfrTVBRv/Dr7ONeelAdOfF0kCQQBB3Owk591ike+xAkUSu7roXDB U3Ow== X-Gm-Message-State: AOJu0Yxu+KeXSlvq4Gc+FilqxophPbjz56+wTBVantkYjigm+hXA1Mps EsXzw1htTFpz7kLsi6kgjopOFV8bQiPj/IyBSlsUFkj9TJN7xQC8Pv6MQlWVUoRBm5lr+x3ClJ0 = X-Google-Smtp-Source: AGHT+IHGxkzGqX3jAyLqjY6/uBOHXHKy2YN4yFmL8sPlSehS69zefcGvduFZhabDsEhyTpk3ox72JQ== X-Received: by 2002:a05:6a00:b92:b0:70d:21d9:e2ae with SMTP id d2e1a72fcca58-7199c9393d1mr24946490b3a.6.1727175843451; Tue, 24 Sep 2024 04:04:03 -0700 (PDT) Received: from chenghaoyang-low.c.googlers.com.com (208.158.221.35.bc.googleusercontent.com. [35.221.158.208]) by smtp.gmail.com with ESMTPSA id d2e1a72fcca58-71afc9833c3sm993326b3a.182.2024.09.24.04.04.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 24 Sep 2024 04:04:03 -0700 (PDT) From: Harvey Yang X-Google-Original-From: Harvey Yang To: libcamera-devel@lists.libcamera.org Cc: Harvey Yang , Yudhistira Erlandinata Subject: [PATCH v7 3/3] libcamera: android: Add face detection control support Date: Tue, 24 Sep 2024 11:02:46 +0000 Message-ID: <20240924110353.2025397-4-chenghaoyang@google.com> X-Mailer: git-send-email 2.46.0.792.g87dc391469-goog In-Reply-To: <20240924110353.2025397-1-chenghaoyang@google.com> References: <20240924110353.2025397-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 | 73 ++++++++++++++++++++++++++++- 2 files changed, 112 insertions(+), 6 deletions(-) diff --git a/src/android/camera_capabilities.cpp b/src/android/camera_capabilities.cpp index 71043e12..d52d58ed 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::android::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::android::FaceDetectModeOff: + androidMode = ANDROID_STATISTICS_FACE_DETECT_MODE_OFF; + break; + case controls::android::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..1982509d 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::android::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,67 @@ CameraDevice::getResultMetadata(const Camera3RequestDescriptor &descriptor) cons resultMetadata->addEntry(ANDROID_SENSOR_FRAME_DURATION, *frameDuration * 1000); + const auto &faceDetectRectangles = + metadata.get(controls::android::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::android::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::android::FaceDetectFaceLandmarks); + if (faceDetectRectangles && 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::android::FaceDetectFaceIds); + if (faceDetectRectangles && 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;