From patchwork Tue Nov 19 12:19:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21999 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 3A5AAC32F1 for ; Tue, 19 Nov 2024 12:19:49 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6661765F14; Tue, 19 Nov 2024 13:19:47 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="O7NrmZJy"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8918B658A2 for ; Tue, 19 Nov 2024 13:19:44 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id EE2D93A2 for ; Tue, 19 Nov 2024 13:19:25 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018766; bh=lJueRwBNzjpiJQlhtcpN480w+7bcg8ejQDd/rX8HRXY=; h=From:To:Subject:Date:In-Reply-To:References:From; b=O7NrmZJymW+3BVo8MO1ZRIvoK0qAoDRU/wNzkOl5bTb3Hi6d2Mk5GBIqQTqKHT/Tz bjdrB1bcy456v6Wvxzpduv9GvwRpZ1YqbBlUqoRXSSXJotLYr7yuWzHMaPfPbGadk+ zzoLZTPjLx4ZdJKeLvr00xoa8w3mEu7XKxMgRTXo= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 01/17] ipa: libipa: vector: Add mutable x(), y() and z() accessors Date: Tue, 19 Nov 2024 14:19:12 +0200 Message-ID: <20241119121928.30939-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" The x(), y() and z() functions of the Vector class are convenience accessors for the first, second and third element of the vector respectively, meant to improve readability of class users when a vector represents coordinates in 1D, 2D or 3D space. Those accessors are limited to immutable access to the vector elements, as they return a copy. Extend the API with mutable accessors. The immutable accessors are modified to return a reference to the vector elements instead of a copy for consistency. As they are inline functions, this should make no difference in terms of performance as the compiler can perform the same optimizations in their case. While at it, reorder functions to declare operators before other member functions, to be consistent with the usual coding style. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v3: - Make non-const accessors constexpr --- src/ipa/libipa/vector.cpp | 51 +++++++++++++++++++++++++-------------- src/ipa/libipa/vector.h | 49 +++++++++++++++++++------------------ 2 files changed, 58 insertions(+), 42 deletions(-) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index bd00b01961d5..b650fcc1fe35 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -52,24 +52,6 @@ namespace ipa { * \copydoc Vector::operator[](size_t i) const */ -/** - * \fn Vector::x() - * \brief Convenience function to access the first element of the vector - * \return The first element of the vector - */ - -/** - * \fn Vector::y() - * \brief Convenience function to access the second element of the vector - * \return The second element of the vector - */ - -/** - * \fn Vector::z() - * \brief Convenience function to access the third element of the vector - * \return The third element of the vector - */ - /** * \fn Vector::operator-() const * \brief Negate a Vector by negating both all of its coordinates @@ -111,6 +93,39 @@ namespace ipa { * \return The vector divided by \a factor */ +/** + * \fn constexpr T &Vector::x() + * \brief Convenience function to access the first element of the vector + * \return The first element of the vector + */ + +/** + * \fn constexpr T &Vector::y() + * \brief Convenience function to access the second element of the vector + * \return The second element of the vector + */ + +/** + * \fn constexpr T &Vector::z() + * \brief Convenience function to access the third element of the vector + * \return The third element of the vector + */ + +/** + * \fn constexpr const T &Vector::x() const + * \copydoc Vector::x() + */ + +/** + * \fn constexpr const T &Vector::y() const + * \copydoc Vector::y() + */ + +/** + * \fn constexpr const T &Vector::z() const + * \copydoc Vector::z() + */ + /** * \fn Vector::length2() * \brief Get the squared length of the vector diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 8612a06a2ab2..b91e50b2e0ca 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -53,30 +53,6 @@ public: return data_[i]; } -#ifndef __DOXYGEN__ - template= 1>> -#endif /* __DOXYGEN__ */ - constexpr T x() const - { - return data_[0]; - } - -#ifndef __DOXYGEN__ - template= 2>> -#endif /* __DOXYGEN__ */ - constexpr T y() const - { - return data_[1]; - } - -#ifndef __DOXYGEN__ - template= 3>> -#endif /* __DOXYGEN__ */ - constexpr T z() const - { - return data_[2]; - } - constexpr Vector operator-() const { Vector ret; @@ -125,6 +101,31 @@ public: return ret; } +#ifndef __DOXYGEN__ + template= 1>> +#endif /* __DOXYGEN__ */ + constexpr const T &x() const { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + constexpr const T &y() const { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + constexpr const T &z() const { return data_[2]; } +#ifndef __DOXYGEN__ + template= 1>> +#endif /* __DOXYGEN__ */ + constexpr T &x() { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + constexpr T &y() { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + constexpr T &z() { return data_[2]; } + constexpr double length2() const { double ret = 0; From patchwork Tue Nov 19 12:19:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22000 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 CA1D5C32F3 for ; Tue, 19 Nov 2024 12:19:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 8A81B65F18; Tue, 19 Nov 2024 13:19:49 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="XPdfS2+X"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 68AD365F0B for ; Tue, 19 Nov 2024 13:19:46 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id BA86622E for ; Tue, 19 Nov 2024 13:19:28 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018768; bh=MsyZUPW6Dl4rDkqqA+BVqylCjodf0/V3CUtu7MoYCCg=; h=From:To:Subject:Date:In-Reply-To:References:From; b=XPdfS2+X+WRIlPfMveYydUpJK3S+ZBblmgbGExmZvARbqjcbBcMVXRg17oJ0L+JX3 4i8I+ra2yVJjmjsn5pW1yUoK6TJ/rUFps6A9hR136sG2FBfdCJpIDmGLwhypxsuLsF PZF909+PW+8v4Bo8hOxJlVo0ARu5S+o+jT7yptHE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 02/17] ipa: libipa: vector: Add r(), g() and b() accessors Date: Tue, 19 Nov 2024 14:19:13 +0200 Message-ID: <20241119121928.30939-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" The Vector class can be useful to represent RGB pixel values. Add r(), g() and b() accessors, similar to x(), y() and z(), along with an RGB type that aliases Vector. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v3: - Make non-const accessors constexpr --- src/ipa/libipa/vector.cpp | 38 ++++++++++++++++++++++++++++++++++++++ src/ipa/libipa/vector.h | 28 ++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index b650fcc1fe35..0f0511da151f 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -126,6 +126,39 @@ namespace ipa { * \copydoc Vector::z() */ +/** + * \fn constexpr T &Vector::r() + * \brief Convenience function to access the first element of the vector + * \return The first element of the vector + */ + +/** + * \fn constexpr T &Vector::g() + * \brief Convenience function to access the second element of the vector + * \return The second element of the vector + */ + +/** + * \fn constexpr T &Vector::b() + * \brief Convenience function to access the third element of the vector + * \return The third element of the vector + */ + +/** + * \fn constexpr const T &Vector::r() const + * \copydoc Vector::r() + */ + +/** + * \fn constexpr const T &Vector::g() const + * \copydoc Vector::g() + */ + +/** + * \fn constexpr const T &Vector::b() const + * \copydoc Vector::b() + */ + /** * \fn Vector::length2() * \brief Get the squared length of the vector @@ -149,6 +182,11 @@ namespace ipa { * \return Product of matrix \a m and vector \a v */ +/** + * \typedef RGB + * \brief A Vector of 3 elements representing an RGB pixel value + */ + /** * \fn bool operator==(const Vector &lhs, const Vector &rhs) * \brief Compare vectors for equality diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index b91e50b2e0ca..3168835bc13d 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -126,6 +126,31 @@ public: #endif /* __DOXYGEN__ */ constexpr T &z() { return data_[2]; } +#ifndef __DOXYGEN__ + template= 1>> +#endif /* __DOXYGEN__ */ + constexpr const T &r() const { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + constexpr const T &g() const { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + constexpr const T &b() const { return data_[2]; } +#ifndef __DOXYGEN__ + template= 1>> +#endif /* __DOXYGEN__ */ + constexpr T &r() { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + constexpr T &g() { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + constexpr T &b() { return data_[2]; } + constexpr double length2() const { double ret = 0; @@ -143,6 +168,9 @@ private: std::array data_; }; +template +using RGB = Vector; + template Vector operator*(const Matrix &m, const Vector &v) { From patchwork Tue Nov 19 12:19:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22001 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 F2026C32F1 for ; Tue, 19 Nov 2024 12:19:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 56E9565F1C; Tue, 19 Nov 2024 13:19:53 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="KJtqClml"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 4099065F0F for ; Tue, 19 Nov 2024 13:19:49 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id AD3C93A2 for ; Tue, 19 Nov 2024 13:19:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018771; bh=x3yyJY2biqM3CiP/7f3m9bMOWo28lJ2IylXIXguAGUI=; h=From:To:Subject:Date:In-Reply-To:References:From; b=KJtqClmligz8D8MATt6bWIX0LdpqOEps8wDvvXY1fjbxxbpfHIXjsLmjv/TjaKIr9 XjLK3cuzk391D9877Ri+4iKCVLua/z9uIdESf2EzvsE3UHcz0opKQFD0GMnXFeCHS0 qn18A1i7dzLhJYaYT88inibHcWfq4aVRecfFBV88= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 03/17] ipa: libipa: vector: Add scalar constructor Date: Tue, 19 Nov 2024 14:19:14 +0200 Message-ID: <20241119121928.30939-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" The default constructor leaves the vector data uninitialized. Add a constructor to fill the vector with copies of a scalar value, and fix the documentation of the default constructor. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v3: - Make the constructor explicit --- src/ipa/libipa/vector.cpp | 8 +++++++- src/ipa/libipa/vector.h | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index 0f0511da151f..5851b9ae2ed3 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -29,7 +29,13 @@ namespace ipa { /** * \fn Vector::Vector() - * \brief Construct a zero vector + * \brief Construct an uninitialized vector + */ + +/** + * \fn Vector::Vector(T scalar) + * \brief Construct a vector filled with a \a scalar value + * \param[in] scalar The scalar value */ /** diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 3168835bc13d..5fb7ad7c95dd 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -35,6 +35,11 @@ class Vector public: constexpr Vector() = default; + constexpr explicit Vector(T scalar) + { + data_.fill(scalar); + } + constexpr Vector(const std::array &data) { for (unsigned int i = 0; i < Rows; i++) From patchwork Tue Nov 19 12:19:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22002 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 51C7EC32F3 for ; Tue, 19 Nov 2024 12:19:56 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E013065F1E; Tue, 19 Nov 2024 13:19:55 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="FS5SazD5"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 9733B65F17 for ; Tue, 19 Nov 2024 13:19:52 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 10E34D49 for ; Tue, 19 Nov 2024 13:19:34 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018775; bh=5Zv5KgDrmGIcqXYK6hyPDOV8YehMaKAZxQowAfWz/9c=; h=From:To:Subject:Date:In-Reply-To:References:From; b=FS5SazD51sXlLkttyV+dSxJQ0Yp/5GKKdrhzp9Qf35gldqkYslcXpS11l+ePcC2Gh ngGUU6wXPg4QzUdr851qhqtra+32e1CXpJj4iOhysb5BLMQxwghdzb71LsLAAeA75v WrE8Alz4yubFMnBS088c8yhkw249cHtM/P6RLP2c= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 04/17] ipa: libipa: vector: Add copy constructor and assignment operator Date: Tue, 19 Nov 2024 14:19:15 +0200 Message-ID: <20241119121928.30939-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" It is useful to assign a value to an existing vector. Define a copy constructor and a copy assignment operator. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v3: - Default both functions Changes since v2: - Make copy constructor constexpr - Drop #include --- src/ipa/libipa/vector.cpp | 13 +++++++++++++ src/ipa/libipa/vector.h | 4 ++++ 2 files changed, 17 insertions(+) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index 5851b9ae2ed3..a9779fa2b8e2 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -46,6 +46,19 @@ namespace ipa { * The size of \a data must be equal to the dimension size Rows of the vector. */ +/** + * \fn Vector::Vector(const Vector &other) + * \brief Construct a Vector by copying \a other + * \param[in] other The other Vector value + */ + +/** + * \fn Vector &Vector::operator=(const Vector &other) + * \brief Replace the content of the Vector with a copy of the content of \a other + * \param[in] other The other Vector value + * \return This Vector value + */ + /** * \fn T Vector::operator[](size_t i) const * \brief Index to an element in the vector diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 5fb7ad7c95dd..1022550e6170 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -46,6 +46,10 @@ public: data_[i] = data[i]; } + constexpr Vector(const Vector &other) = default; + + Vector &operator=(const Vector &other) = default; + const T &operator[](size_t i) const { ASSERT(i < data_.size()); From patchwork Tue Nov 19 12:19:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22003 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 BE625C32F5 for ; Tue, 19 Nov 2024 12:19:59 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 262AA65F22; Tue, 19 Nov 2024 13:19:59 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="JQfgUxao"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id F399065F14 for ; Tue, 19 Nov 2024 13:19:54 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 88C8ED49 for ; Tue, 19 Nov 2024 13:19:37 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018777; bh=8dQk9SQr1x/Gh45wEdyiVeTYZY16d5Ir9LJxw4yIUYY=; h=From:To:Subject:Date:In-Reply-To:References:From; b=JQfgUxaoO7AuYHWPiLoa3XipmHjTT5IHvxSvVx91WiMSaRbsQAu7MRX2tFEzwt96v SH6idUylFLaj1w/Cqw5TQbxkX6Aqj0eN6thogS8VAF7VaxKujGH3mh2/315NDJ9jpL etdwj2RB0t8Zf/02g6Zaow5t1UhWj1UsWxg71zws= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 05/17] ipa: libipa: vector: Rename the dot product operator*() to dot() Date: Tue, 19 Nov 2024 14:19:16 +0200 Message-ID: <20241119121928.30939-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" The Vector class defines a set of arithmetic operators between two vectors or a vector and a scalar. All the operators perform element-wise operations, except for the operator*() that computes the dot product. This is inconsistent and confusing. Replace the operator with a dot() function. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- src/ipa/libipa/vector.cpp | 14 +++++++------- src/ipa/libipa/vector.h | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index a9779fa2b8e2..473e6d8bad01 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -91,13 +91,6 @@ namespace ipa { * \return The sum of the two vectors */ -/** - * \fn Vector::operator*(const Vector &other) const - * \brief Compute the dot product - * \param[in] other The other vector - * \return The dot product of the two vectors - */ - /** * \fn Vector::operator*(T factor) const * \brief Multiply the vector by a scalar @@ -112,6 +105,13 @@ namespace ipa { * \return The vector divided by \a factor */ +/** + * \fn Vector::dot(const Vector &other) const + * \brief Compute the dot product + * \param[in] other The other vector + * \return The dot product of the two vectors + */ + /** * \fn constexpr T &Vector::x() * \brief Convenience function to access the first element of the vector diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 1022550e6170..b4eb19707063 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -86,14 +86,6 @@ public: return ret; } - constexpr T operator*(const Vector &other) const - { - T ret = 0; - for (unsigned int i = 0; i < Rows; i++) - ret += data_[i] * other[i]; - return ret; - } - constexpr Vector operator*(T factor) const { Vector ret; @@ -110,6 +102,14 @@ public: return ret; } + constexpr T dot(const Vector &other) const + { + T ret = 0; + for (unsigned int i = 0; i < Rows; i++) + ret += data_[i] * other[i]; + return ret; + } + #ifndef __DOXYGEN__ template= 1>> #endif /* __DOXYGEN__ */ From patchwork Tue Nov 19 12:19:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22004 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 8AB4DC32F1 for ; Tue, 19 Nov 2024 12:20:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id EEB8965F1E; Tue, 19 Nov 2024 13:20:00 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="Gji7WaNR"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id E393E65F1C for ; Tue, 19 Nov 2024 13:19:57 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 4B2C91211 for ; Tue, 19 Nov 2024 13:19:40 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018780; bh=fp0lTBlk5VDfOf4pZxT+cewG2ES+5ye9ffGTAWYZbKY=; h=From:To:Subject:Date:In-Reply-To:References:From; b=Gji7WaNR0v03+s308Z2pC9Ysk3Kp8PVxznO9iHOBmzoGvqkzU2fSxPaCq46wPZZnv TMrLvaq1OjmdbnNXuzEKVDWNKG9xXobCHh5obDJgbffIKZ0Z3WL1WLIuWI0n03DiS1 ZzN5n360Ub5pdJucrV7FB/JMAZQhQeg8dzUjsGIg= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 06/17] ipa: libipa: vector: Generalize arithmetic operators Date: Tue, 19 Nov 2024 14:19:17 +0200 Message-ID: <20241119121928.30939-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" Instead of hand-coding all arithmetic operators, implement them based on a generic apply() function that takes an operator-specific binary operators. This will simplify adding missing arithmetic operators. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v3: - Replace std::function with a templated argument Changes since v2: - Include - Use std::plus, std::minus, std::multiplies and std::divides --- src/ipa/libipa/vector.h | 52 +++++++++++++++++++++++++---------------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index b4eb19707063..10e16d41aa8b 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -6,8 +6,10 @@ */ #pragma once +#include #include #include +#include #include #include @@ -70,36 +72,24 @@ public: return ret; } - constexpr Vector operator-(const Vector &other) const + constexpr Vector operator-(const Vector &other) const { - Vector ret; - for (unsigned int i = 0; i < Rows; i++) - ret[i] = data_[i] - other[i]; - return ret; + return apply(*this, other, std::minus<>{}); } - constexpr Vector operator+(const Vector &other) const + constexpr Vector operator+(const Vector &other) const { - Vector ret; - for (unsigned int i = 0; i < Rows; i++) - ret[i] = data_[i] + other[i]; - return ret; + return apply(*this, other, std::plus<>{}); } - constexpr Vector operator*(T factor) const + constexpr Vector operator*(T factor) const { - Vector ret; - for (unsigned int i = 0; i < Rows; i++) - ret[i] = data_[i] * factor; - return ret; + return apply(*this, factor, std::multiplies<>{}); } - constexpr Vector operator/(T factor) const + constexpr Vector operator/(T factor) const { - Vector ret; - for (unsigned int i = 0; i < Rows; i++) - ret[i] = data_[i] / factor; - return ret; + return apply(*this, factor, std::divides<>{}); } constexpr T dot(const Vector &other) const @@ -174,6 +164,28 @@ public: } private: + template + static constexpr Vector apply(const Vector &lhs, const Vector &rhs, BinaryOp op) + { + Vector result; + std::transform(lhs.data_.begin(), lhs.data_.end(), + rhs.data_.begin(), result.data_.begin(), + op); + + return result; + } + + template + static constexpr Vector apply(const Vector &lhs, T rhs, BinaryOp op) + { + Vector result; + std::transform(lhs.data_.begin(), lhs.data_.end(), + result.data_.begin(), + [&op, rhs](T v) { return op(v, rhs); }); + + return result; + } + std::array data_; }; From patchwork Tue Nov 19 12:19:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22005 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 ED5EBC330B for ; Tue, 19 Nov 2024 12:20:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6D2D065F28; Tue, 19 Nov 2024 13:20:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="BrcNyrq0"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D14D865F26 for ; Tue, 19 Nov 2024 13:20:00 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 215591211 for ; Tue, 19 Nov 2024 13:19:43 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018783; bh=4N+++9E/T/t8o7/PaCBa/jkDDe51oLGMigWb6vPc+7s=; h=From:To:Subject:Date:In-Reply-To:References:From; b=BrcNyrq0Xw+GBOzU0tn9PLKMwy8DiMnTWitSE2OqOE1HSK6R5YFAEvQEPs0WzNytc zw4mBCagB++NsmJ2SfS09s9tgq1uYbPwxhDPHlgPXdBWmTsLR4QexcsQwHsrNMSXu0 68dqf1ZBrjXFqAmosEO9GXqKv3SwhQ/FTeHCaCv8= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 07/17] ipa: libipa: vector: Add missing binary arithemtic operators Date: Tue, 19 Nov 2024 14:19:18 +0200 Message-ID: <20241119121928.30939-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" The Vector class defines multiple element-wise arithmetic operators between vectors or between a vector and a scalar. A few variants are missing. Add them. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v2: - Use std::plus, std::minus, std::multiplies and std::divides --- src/ipa/libipa/vector.cpp | 54 +++++++++++++++++++++++++++++---------- src/ipa/libipa/vector.h | 38 ++++++++++++++++++++------- 2 files changed, 70 insertions(+), 22 deletions(-) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index 473e6d8bad01..13aaacbed20e 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -77,32 +77,60 @@ namespace ipa { * \return The negated vector */ +/** + * \fn Vector::operator+(Vector const &other) const + * \brief Calculate the sum of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise sum of this vector and \a other + */ + +/** + * \fn Vector::operator+(T scalar) const + * \brief Calculate the sum of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise sum of this vector and \a other + */ + /** * \fn Vector::operator-(Vector const &other) const - * \brief Subtract one vector from another + * \brief Calculate the difference of this vector and \a other element-wise * \param[in] other The other vector - * \return The difference of \a other from this vector + * \return The element-wise subtraction of \a other from this vector */ /** - * \fn Vector::operator+() - * \brief Add two vectors together + * \fn Vector::operator-(T scalar) const + * \brief Calculate the difference of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise subtraction of \a scalar from this vector + */ + +/** + * \fn Vector::operator*(const Vector &other) const + * \brief Calculate the product of this vector and \a other element-wise * \param[in] other The other vector - * \return The sum of the two vectors + * \return The element-wise product of this vector and \a other */ /** - * \fn Vector::operator*(T factor) const - * \brief Multiply the vector by a scalar - * \param[in] factor The factor - * \return The vector multiplied by \a factor + * \fn Vector::operator*(T scalar) const + * \brief Calculate the product of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise product of this vector and \a scalar */ /** - * \fn Vector::operator/() - * \brief Divide the vector by a scalar - * \param[in] factor The factor - * \return The vector divided by \a factor + * \fn Vector::operator/(const Vector &other) const + * \brief Calculate the quotient of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise division of this vector by \a other + */ + +/** + * \fn Vector::operator/(T scalar) const + * \brief Calculate the quotient of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise division of this vector by \a scalar */ /** diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 10e16d41aa8b..6e24cdcebec0 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -72,24 +72,44 @@ public: return ret; } - constexpr Vector operator-(const Vector &other) const - { - return apply(*this, other, std::minus<>{}); - } - constexpr Vector operator+(const Vector &other) const { return apply(*this, other, std::plus<>{}); } - constexpr Vector operator*(T factor) const + constexpr Vector operator+(T scalar) const { - return apply(*this, factor, std::multiplies<>{}); + return apply(*this, scalar, std::plus<>{}); } - constexpr Vector operator/(T factor) const + constexpr Vector operator-(const Vector &other) const { - return apply(*this, factor, std::divides<>{}); + return apply(*this, other, std::minus<>{}); + } + + constexpr Vector operator-(T scalar) const + { + return apply(*this, scalar, std::minus<>{}); + } + + constexpr Vector operator*(const Vector &other) const + { + return apply(*this, other, std::multiplies<>{}); + } + + constexpr Vector operator*(T scalar) const + { + return apply(*this, scalar, std::multiplies<>{}); + } + + constexpr Vector operator/(const Vector &other) const + { + return apply(*this, other, std::divides<>{}); + } + + constexpr Vector operator/(T scalar) const + { + return apply(*this, scalar, std::divides<>{}); } constexpr T dot(const Vector &other) const From patchwork Tue Nov 19 12:19:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22006 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 9A13DC32F3 for ; Tue, 19 Nov 2024 12:20:07 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 05D3D65F2B; Tue, 19 Nov 2024 13:20:06 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="IIWleVmf"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8E1A865F20 for ; Tue, 19 Nov 2024 13:20:03 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 107351624 for ; Tue, 19 Nov 2024 13:19:46 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018786; bh=hICb8bQOp8g75pM+UxOA+VpNvJncTdtc3A+j1qtsNBo=; h=From:To:Subject:Date:In-Reply-To:References:From; b=IIWleVmfk4RzrxZOBz3eJhmjjMkoJhhPRYu09lvBq0IkYp14UO8GQJMgXSzlwkHjH p1UKuUkHTmM6BinWEIH6MMCSC2zneCX8vYEkpL0+V2JRiJ0HbtcXCN11t1Rv5eYFrK TTvEjw2UbeJXWOZlGzyfVaoDCfX5glVoBR7HcW4E= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 08/17] ipa: libipa: vector: Add compound assignment operators Date: Tue, 19 Nov 2024 14:19:19 +0200 Message-ID: <20241119121928.30939-9-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" Extend the Vector class with compound assignment operators that match the binary arithmetic operators. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v3: - Replace std::function with a templated argument Changes since v2: - Use std::plus, std::minus, std::multiplies and std::divides --- src/ipa/libipa/vector.cpp | 56 +++++++++++++++++++++++++++++++++++++ src/ipa/libipa/vector.h | 59 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index 13aaacbed20e..3305dcb38e6b 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -133,6 +133,62 @@ namespace ipa { * \return The element-wise division of this vector by \a scalar */ +/** + * \fn Vector::operator+=(Vector const &other) + * \brief Add \a other element-wise to this vector + * \param[in] other The other vector + * \return This vector + */ + +/** + * \fn Vector::operator+=(T scalar) + * \brief Add \a scalar element-wise to this vector + * \param[in] scalar The scalar + * \return This vector + */ + +/** + * \fn Vector::operator-=(Vector const &other) + * \brief Subtract \a other element-wise from this vector + * \param[in] other The other vector + * \return This vector + */ + +/** + * \fn Vector::operator-=(T scalar) + * \brief Subtract \a scalar element-wise from this vector + * \param[in] scalar The scalar + * \return This vector + */ + +/** + * \fn Vector::operator*=(const Vector &other) + * \brief Multiply this vector by \a other element-wise + * \param[in] other The other vector + * \return This vector + */ + +/** + * \fn Vector::operator*=(T scalar) + * \brief Multiply this vector by \a scalar element-wise + * \param[in] scalar The scalar + * \return This vector + */ + +/** + * \fn Vector::operator/=(const Vector &other) + * \brief Divide this vector by \a other element-wise + * \param[in] other The other vector + * \return This vector + */ + +/** + * \fn Vector::operator/=(T scalar) + * \brief Divide this vector by \a scalar element-wise + * \param[in] scalar The scalar + * \return This vector + */ + /** * \fn Vector::dot(const Vector &other) const * \brief Compute the dot product diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 6e24cdcebec0..683bf9ee2564 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -112,6 +112,46 @@ public: return apply(*this, scalar, std::divides<>{}); } + Vector &operator+=(const Vector &other) + { + return apply(other, [](T a, T b) { return a + b; }); + } + + Vector &operator+=(T scalar) + { + return apply(scalar, [](T a, T b) { return a + b; }); + } + + Vector &operator-=(const Vector &other) + { + return apply(other, [](T a, T b) { return a - b; }); + } + + Vector &operator-=(T scalar) + { + return apply(scalar, [](T a, T b) { return a - b; }); + } + + Vector &operator*=(const Vector &other) + { + return apply(other, [](T a, T b) { return a * b; }); + } + + Vector &operator*=(T scalar) + { + return apply(scalar, [](T a, T b) { return a * b; }); + } + + Vector &operator/=(const Vector &other) + { + return apply(other, [](T a, T b) { return a / b; }); + } + + Vector &operator/=(T scalar) + { + return apply(scalar, [](T a, T b) { return a / b; }); + } + constexpr T dot(const Vector &other) const { T ret = 0; @@ -206,6 +246,25 @@ private: return result; } + template + Vector &apply(const Vector &other, BinaryOp op) + { + auto itOther = other.data_.begin(); + std::for_each(data_.begin(), data_.end(), + [&op, &itOther](T &v) { v = op(v, *itOther++); }); + + return *this; + } + + template + Vector &apply(T scalar, BinaryOp op) + { + std::for_each(data_.begin(), data_.end(), + [&op, scalar](T &v) { v = op(v, scalar); }); + + return *this; + } + std::array data_; }; From patchwork Tue Nov 19 12:19:20 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22007 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 BEC26C32F1 for ; Tue, 19 Nov 2024 12:20:11 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5440765F28; Tue, 19 Nov 2024 13:20:11 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="uJLMT+H7"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D495865F28 for ; Tue, 19 Nov 2024 13:20:06 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 327B91934 for ; Tue, 19 Nov 2024 13:19:49 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018789; bh=4fzdi9q8tpbnT+vsDUJ0qe/mYweGuMe/LZdAmn2Fg2M=; h=From:To:Subject:Date:In-Reply-To:References:From; b=uJLMT+H75A0Q3P3pX7QNsDvnIqDlEWXzASI5JRio3Y68roeG+wqBS9uZlFa9+NJhH Te+A8oW3RZvjXtJ3Vgqo9jhD00GjajS8Cl4anKuIGPnO02ND+JDg3i6Fps2ZMJQlMV bDVAKQ1DFyBytgWt6S7Eq2YYERB664eU2HdTJLgE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 09/17] ipa: libipa: vector: Add element-wise min() and max() functions Date: Tue, 19 Nov 2024 14:19:20 +0200 Message-ID: <20241119121928.30939-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" Add functions to calculate the element-wise minimum and maximum of two vectors or of a vector and a scalar. This will be used in algorithm implementations. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- src/ipa/libipa/vector.cpp | 28 ++++++++++++++++++++++++++++ src/ipa/libipa/vector.h | 20 ++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index 3305dcb38e6b..a506487c7b43 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -189,6 +189,34 @@ namespace ipa { * \return This vector */ +/** + * \fn Vector::min(const Vector &other) const + * \brief Calculate the minimum of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise minimum of this vector and \a other + */ + +/** + * \fn Vector::min(T scalar) const + * \brief Calculate the minimum of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise minimum of this vector and \a scalar + */ + +/** + * \fn Vector::max(const Vector &other) const + * \brief Calculate the maximum of this vector and \a other element-wise + * \param[in] other The other vector + * \return The element-wise maximum of this vector and \a other + */ + +/** + * \fn Vector::max(T scalar) const + * \brief Calculate the maximum of this vector and \a scalar element-wise + * \param[in] scalar The scalar + * \return The element-wise maximum of this vector and \a scalar + */ + /** * \fn Vector::dot(const Vector &other) const * \brief Compute the dot product diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 683bf9ee2564..85b7f6ee68a7 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -152,6 +152,26 @@ public: return apply(scalar, [](T a, T b) { return a / b; }); } + constexpr Vector min(const Vector &other) const + { + return apply(*this, other, [](T a, T b) { return std::min(a, b); }); + } + + constexpr Vector min(T scalar) const + { + return apply(*this, scalar, [](T a, T b) { return std::min(a, b); }); + } + + constexpr Vector max(const Vector &other) const + { + return apply(*this, other, [](T a, T b) { return std::max(a, b); }); + } + + constexpr Vector max(T scalar) const + { + return apply(*this, scalar, [](T a, T b) -> T { return std::max(a, b); }); + } + constexpr T dot(const Vector &other) const { T ret = 0; From patchwork Tue Nov 19 12:19:21 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22008 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 B0F1FC32F5 for ; Tue, 19 Nov 2024 12:20:14 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 50D5E65F31; Tue, 19 Nov 2024 13:20:14 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="kP/uo0AF"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id AB4D465F26 for ; Tue, 19 Nov 2024 13:20:09 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id F0847193C for ; Tue, 19 Nov 2024 13:19:51 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018792; bh=M/q/1RT8aY2M8BXgSR8MxOcsLqh14yKK7f9h/QkUSdo=; h=From:To:Subject:Date:In-Reply-To:References:From; b=kP/uo0AF+ZSxFBDOxC7qjeskf2CP1R/Z+lEQSGQBjXORYqXIYTMHtXKTuZtYgRK91 56Q6ZoIsZUwnH3FP4zwOMpfkMjZg17ZjCjBegjbaFho1y011Dj4W90RSsu0+s7DvIA ypyMG/te50w4nKfDm5+Di0ql5GucrDyILcN+4FqM= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 10/17] ipa: libipa: vector: Add sum() function Date: Tue, 19 Nov 2024 14:19:21 +0200 Message-ID: <20241119121928.30939-11-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" Add a function to calculate the sum of a vector. It will be useful for algorithms. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v1: - Drop Vector::normalize() --- src/ipa/libipa/vector.cpp | 12 ++++++++++++ src/ipa/libipa/vector.h | 7 +++++++ 2 files changed, 19 insertions(+) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index a506487c7b43..d6e25e3e722d 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -302,6 +302,18 @@ namespace ipa { * \return The length of the vector */ +/** + * \fn Vector::sum() const + * \brief Calculate the sum of all the vector elements + * \tparam R The type of the sum + * + * The type R of the sum defaults to the type T of the elements, but can be set + * explicitly to use a different type in case the type T would risk + * overflowing. + * + * \return The sum of all the vector elements + */ + /** * \fn Vector operator*(const Matrix &m, const Vector &v) * \brief Multiply a matrix by a vector diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 85b7f6ee68a7..5a2a29b53441 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -243,6 +244,12 @@ public: return std::sqrt(length2()); } + template + constexpr R sum() const + { + return std::accumulate(data_.begin(), data_.end(), R{}); + } + private: template static constexpr Vector apply(const Vector &lhs, const Vector &rhs, BinaryOp op) From patchwork Tue Nov 19 12:19:22 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22009 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 C23CFC32F3 for ; Tue, 19 Nov 2024 12:20:18 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2733565F37; Tue, 19 Nov 2024 13:20:18 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="awAZI1NE"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id B1E6065F2C for ; Tue, 19 Nov 2024 13:20:12 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 0F722193C for ; Tue, 19 Nov 2024 13:19:54 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018795; bh=5buo3fwsEH7UtzIWAB+ZiaYNVvSs8lcucQ+C69aj92A=; h=From:To:Subject:Date:In-Reply-To:References:From; b=awAZI1NEOJ+HWd6TjE6ax4EuDPcvSlOSddb1HwNgoyNTU04JgOILsm7P7SwMXT//E iv0GAo6IlsS3949aW8kpvn++RqdDzJn7zNiysFIwfMHgHq6tpsIYqbhb40WcJWtovJ E67LFl/iqNt1d0EYbzH6FHLdobXTyqQlXal3yFps= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 11/17] test: libipa: Add Vector class test Date: Tue, 19 Nov 2024 14:19:22 +0200 Message-ID: <20241119121928.30939-12-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" Add a unit test to exercize the API of the ipa::Vector class. The test binary being called 'vector', implicit includes cause the binary to be picked by '#include ', causing builds to fail. Set implicit_include_directories to false to avoid this, as done in commit 6cd849125888 ("test: Don't add current build directory to include path"). Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v2: - Fix initialization of 'v1' variable --- test/ipa/libipa/meson.build | 2 + test/ipa/libipa/vector.cpp | 100 ++++++++++++++++++++++++++++++++++++ 2 files changed, 102 insertions(+) create mode 100644 test/ipa/libipa/vector.cpp diff --git a/test/ipa/libipa/meson.build b/test/ipa/libipa/meson.build index 4d2427dbd4e7..f9b3c46d000f 100644 --- a/test/ipa/libipa/meson.build +++ b/test/ipa/libipa/meson.build @@ -2,11 +2,13 @@ libipa_test = [ {'name': 'interpolator', 'sources': ['interpolator.cpp']}, + {'name': 'vector', 'sources': ['vector.cpp']}, ] foreach test : libipa_test exe = executable(test['name'], test['sources'], dependencies : [libcamera_private, libipa_dep], + implicit_include_directories : false, link_with : [test_libraries], include_directories : [test_includes_internal, '../../../src/ipa/libipa/']) diff --git a/test/ipa/libipa/vector.cpp b/test/ipa/libipa/vector.cpp new file mode 100644 index 000000000000..8e4ec77d7820 --- /dev/null +++ b/test/ipa/libipa/vector.cpp @@ -0,0 +1,100 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * Copyright (C) 2024, Ideas on Board Oy + * + * Vector tests + */ + +#include "../src/ipa/libipa/vector.h" + +#include +#include + +#include "test.h" + +using namespace libcamera::ipa; + +#define ASSERT_EQ(a, b) \ +if ((a) != (b)) { \ + std::cout << #a " != " #b << " (line " << __LINE__ << ")" \ + << std::endl; \ + return TestFail; \ +} + +class VectorTest : public Test +{ +protected: + int run() + { + Vector v1{ 0.0 }; + + ASSERT_EQ(v1[0], 0.0); + ASSERT_EQ(v1[1], 0.0); + ASSERT_EQ(v1[2], 0.0); + + ASSERT_EQ(v1.length(), 0.0); + ASSERT_EQ(v1.length2(), 0.0); + + Vector v2{{ 1.0, 4.0, 8.0 }}; + + ASSERT_EQ(v2[0], 1.0); + ASSERT_EQ(v2[1], 4.0); + ASSERT_EQ(v2[2], 8.0); + + ASSERT_EQ(v2.x(), 1.0); + ASSERT_EQ(v2.y(), 4.0); + ASSERT_EQ(v2.z(), 8.0); + + ASSERT_EQ(v2.r(), 1.0); + ASSERT_EQ(v2.g(), 4.0); + ASSERT_EQ(v2.b(), 8.0); + + ASSERT_EQ(v2.length2(), 81.0); + ASSERT_EQ(v2.length(), 9.0); + ASSERT_EQ(v2.sum(), 13.0); + + Vector v3{ v2 }; + + ASSERT_EQ(v2, v3); + + v3 = Vector{{ 4.0, 4.0, 4.0 }}; + + ASSERT_EQ(v2 + v3, (Vector{{ 5.0, 8.0, 12.0 }})); + ASSERT_EQ(v2 + 4.0, (Vector{{ 5.0, 8.0, 12.0 }})); + ASSERT_EQ(v2 - v3, (Vector{{ -3.0, 0.0, 4.0 }})); + ASSERT_EQ(v2 - 4.0, (Vector{{ -3.0, 0.0, 4.0 }})); + ASSERT_EQ(v2 * v3, (Vector{{ 4.0, 16.0, 32.0 }})); + ASSERT_EQ(v2 * 4.0, (Vector{{ 4.0, 16.0, 32.0 }})); + ASSERT_EQ(v2 / v3, (Vector{{ 0.25, 1.0, 2.0 }})); + ASSERT_EQ(v2 / 4.0, (Vector{{ 0.25, 1.0, 2.0 }})); + + ASSERT_EQ(v2.min(v3), (Vector{{ 1.0, 4.0, 4.0 }})); + ASSERT_EQ(v2.min(4.0), (Vector{{ 1.0, 4.0, 4.0 }})); + ASSERT_EQ(v2.max(v3), (Vector{{ 4.0, 4.0, 8.0 }})); + ASSERT_EQ(v2.max(4.0), (Vector{{ 4.0, 4.0, 8.0 }})); + + ASSERT_EQ(v2.dot(v3), 52.0); + + v2 += v3; + ASSERT_EQ(v2, (Vector{{ 5.0, 8.0, 12.0 }})); + v2 -= v3; + ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); + v2 *= v3; + ASSERT_EQ(v2, (Vector{{ 4.0, 16.0, 32.0 }})); + v2 /= v3; + ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); + + v2 += 4.0; + ASSERT_EQ(v2, (Vector{{ 5.0, 8.0, 12.0 }})); + v2 -= 4.0; + ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); + v2 *= 4.0; + ASSERT_EQ(v2, (Vector{{ 4.0, 16.0, 32.0 }})); + v2 /= 4.0; + ASSERT_EQ(v2, (Vector{{ 1.0, 4.0, 8.0 }})); + + return TestPass; + } +}; + +TEST_REGISTER(VectorTest) From patchwork Tue Nov 19 12:19:23 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22010 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 5D8A2C32F1 for ; Tue, 19 Nov 2024 12:20:21 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id C807D65F2C; Tue, 19 Nov 2024 13:20:20 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="v4S9jlkM"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 2E23165F2C for ; Tue, 19 Nov 2024 13:20:15 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 8068A193C for ; Tue, 19 Nov 2024 13:19:57 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018797; bh=x92FWgz5sWXwcAsuTW8GFvy7arSFrnaSK63WkfOYu3I=; h=From:To:Subject:Date:In-Reply-To:References:From; b=v4S9jlkM887IK+5XdTDr9ZaHA8jmeTWEsGDsKMlBBOMxBFJfTSoRl5vU5eD2d7WrT ZDRTb9btVUxEcK4mM3ZksrlsTMZVR66eH2qxxiutsD8LW7ynPxvfcL+sa5mgZ5gZRw txRkRVckiTK6DvrNkbLNbJ9isy5ekh0dlGTFBIHI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 12/17] ipa: ipu3: awb: Replace Awb::RGB class with ipa::RGB Date: Tue, 19 Nov 2024 14:19:23 +0200 Message-ID: <20241119121928.30939-13-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" Now that libipa has a generic RGB class, replaces the local implementation from the IPU3 AWB algorithm. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- src/ipa/ipu3/algorithms/awb.cpp | 37 ++++++++++++++++++--------------- src/ipa/ipu3/algorithms/awb.h | 18 +++------------- 2 files changed, 23 insertions(+), 32 deletions(-) diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index c3c8b0740f36..7c6bff09147c 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -309,15 +309,18 @@ void Awb::generateZones() zones_.clear(); for (unsigned int i = 0; i < kAwbStatsSizeX * kAwbStatsSizeY; i++) { - RGB zone; double counted = awbStats_[i].counted; if (counted >= cellsPerZoneThreshold_) { - zone.G = awbStats_[i].sum.green / counted; - if (zone.G >= kMinGreenLevelInZone) { - zone.R = awbStats_[i].sum.red / counted; - zone.B = awbStats_[i].sum.blue / counted; + RGB zone{{ + static_cast(awbStats_[i].sum.red), + static_cast(awbStats_[i].sum.green), + static_cast(awbStats_[i].sum.blue) + }}; + + zone /= counted; + + if (zone.g() >= kMinGreenLevelInZone) zones_.push_back(zone); - } } } } @@ -384,32 +387,32 @@ void Awb::awbGreyWorld() * consider some variations, such as normalising all the zones first, or * doing an L2 average etc. */ - std::vector &redDerivative(zones_); - std::vector blueDerivative(redDerivative); + std::vector> &redDerivative(zones_); + std::vector> blueDerivative(redDerivative); std::sort(redDerivative.begin(), redDerivative.end(), - [](RGB const &a, RGB const &b) { - return a.G * b.R < b.G * a.R; + [](RGB const &a, RGB const &b) { + return a.g() * b.r() < b.g() * a.r(); }); std::sort(blueDerivative.begin(), blueDerivative.end(), - [](RGB const &a, RGB const &b) { - return a.G * b.B < b.G * a.B; + [](RGB const &a, RGB const &b) { + return a.g() * b.b() < b.g() * a.b(); }); /* Average the middle half of the values. */ int discard = redDerivative.size() / 4; - RGB sumRed(0, 0, 0); - RGB sumBlue(0, 0, 0); + RGB sumRed{ 0.0 }; + RGB sumBlue{ 0.0 }; for (auto ri = redDerivative.begin() + discard, bi = blueDerivative.begin() + discard; ri != redDerivative.end() - discard; ri++, bi++) sumRed += *ri, sumBlue += *bi; - double redGain = sumRed.G / (sumRed.R + 1), - blueGain = sumBlue.G / (sumBlue.B + 1); + double redGain = sumRed.g() / (sumRed.r() + 1), + blueGain = sumBlue.g() / (sumBlue.b() + 1); /* Color temperature is not relevant in Grey world but still useful to estimate it :-) */ - asyncResults_.temperatureK = estimateCCT(sumRed.R, sumRed.G, sumBlue.B); + asyncResults_.temperatureK = estimateCCT(sumRed.r(), sumRed.g(), sumBlue.b()); /* * Gain values are unsigned integer value ranging [0, 8) with 13 bit diff --git a/src/ipa/ipu3/algorithms/awb.h b/src/ipa/ipu3/algorithms/awb.h index a13c49acc1fe..1916990a5364 100644 --- a/src/ipa/ipu3/algorithms/awb.h +++ b/src/ipa/ipu3/algorithms/awb.h @@ -13,6 +13,8 @@ #include +#include "libipa/vector.h" + #include "algorithm.h" namespace libcamera { @@ -48,20 +50,6 @@ public: ControlList &metadata) override; private: - /* \todo Make these structs available to all the ISPs ? */ - struct RGB { - RGB(double _R = 0, double _G = 0, double _B = 0) - : R(_R), G(_G), B(_B) - { - } - double R, G, B; - RGB &operator+=(RGB const &other) - { - R += other.R, G += other.G, B += other.B; - return *this; - } - }; - struct AwbStatus { double temperatureK; double redGain; @@ -78,7 +66,7 @@ private: static constexpr uint16_t threshold(float value); static constexpr uint16_t gainValue(double gain); - std::vector zones_; + std::vector> zones_; Accumulator awbStats_[kAwbStatsSizeX * kAwbStatsSizeY]; AwbStatus asyncResults_; From patchwork Tue Nov 19 12:19:24 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22011 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 EDDF2C32F3 for ; Tue, 19 Nov 2024 12:20:23 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 54B5165F3C; Tue, 19 Nov 2024 13:20:23 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="trG5Apfu"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6DE0F65F2C for ; Tue, 19 Nov 2024 13:20:18 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 6F2561966 for ; Tue, 19 Nov 2024 13:20:00 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018800; bh=zTgkQcyqhA0MwXdm4Dk+7+zCF7yrtCGGJpOHatYitDQ=; h=From:To:Subject:Date:In-Reply-To:References:From; b=trG5ApfuB7vpAMk9xPsfKWLARsThRIkzcmHr13lBoyKfCK1qF/tDu+KCNyj/Stimj f2bgGc/fJfT4LpBe4GUmXgkqmdbsvJw5gS+OkGyY1b+iZIZID2x5U1CQ+z7jdyv+2+ 3E6ZtRXR+NT9mIdmy5Btd6Kcp6+olOa4qJMn68zw= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 13/17] ipa: libipa: colour: Use the RGB class to model RGB values Date: Tue, 19 Nov 2024 14:19:24 +0200 Message-ID: <20241119121928.30939-14-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" The rec601LuminanceFromRGB() and estimateCCT() functions take RGB triplets as three variables. Replace them with instances of the RGB class and adapt the users accordingly. Only variables passed directly to these functions are converted to RGB instances, further conversion of IPA modules to the RGB class will be performed separately. While at it, fix a typo in the documentation of the estimateCCT() function. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- src/ipa/ipu3/algorithms/agc.cpp | 14 +++---- src/ipa/ipu3/algorithms/awb.cpp | 2 +- src/ipa/libipa/colours.cpp | 22 +++++----- src/ipa/libipa/colours.h | 6 ++- src/ipa/rkisp1/algorithms/awb.cpp | 47 ++++++++++++---------- src/ipa/rpi/controller/rpi/agc_channel.cpp | 21 +++++----- 6 files changed, 55 insertions(+), 57 deletions(-) diff --git a/src/ipa/ipu3/algorithms/agc.cpp b/src/ipa/ipu3/algorithms/agc.cpp index 466b3fb31a6c..fda4daa6306c 100644 --- a/src/ipa/ipu3/algorithms/agc.cpp +++ b/src/ipa/ipu3/algorithms/agc.cpp @@ -178,18 +178,16 @@ Histogram Agc::parseStatistics(const ipu3_uapi_stats_3a *stats, */ double Agc::estimateLuminance(double gain) const { - double redSum = 0, greenSum = 0, blueSum = 0; + RGB sum{ 0.0 }; for (unsigned int i = 0; i < rgbTriples_.size(); i++) { - redSum += std::min(std::get<0>(rgbTriples_[i]) * gain, 255.0); - greenSum += std::min(std::get<1>(rgbTriples_[i]) * gain, 255.0); - blueSum += std::min(std::get<2>(rgbTriples_[i]) * gain, 255.0); + sum.r() += std::min(std::get<0>(rgbTriples_[i]) * gain, 255.0); + sum.g() += std::min(std::get<1>(rgbTriples_[i]) * gain, 255.0); + sum.b() += std::min(std::get<2>(rgbTriples_[i]) * gain, 255.0); } - double ySum = rec601LuminanceFromRGB(redSum * rGain_, - greenSum * gGain_, - blueSum * bGain_); - + RGB gains{{ rGain_, gGain_, bGain_ }}; + double ySum = rec601LuminanceFromRGB(sum * gains); return ySum / (bdsGrid_.height * bdsGrid_.width) / 255; } diff --git a/src/ipa/ipu3/algorithms/awb.cpp b/src/ipa/ipu3/algorithms/awb.cpp index 7c6bff09147c..55de05d9e39f 100644 --- a/src/ipa/ipu3/algorithms/awb.cpp +++ b/src/ipa/ipu3/algorithms/awb.cpp @@ -412,7 +412,7 @@ void Awb::awbGreyWorld() blueGain = sumBlue.g() / (sumBlue.b() + 1); /* Color temperature is not relevant in Grey world but still useful to estimate it :-) */ - asyncResults_.temperatureK = estimateCCT(sumRed.r(), sumRed.g(), sumBlue.b()); + asyncResults_.temperatureK = estimateCCT({{ sumRed.r(), sumRed.g(), sumBlue.b() }}); /* * Gain values are unsigned integer value ranging [0, 8) with 13 bit diff --git a/src/ipa/libipa/colours.cpp b/src/ipa/libipa/colours.cpp index 9fcb53b08ffb..6c597093ddf8 100644 --- a/src/ipa/libipa/colours.cpp +++ b/src/ipa/libipa/colours.cpp @@ -21,9 +21,7 @@ namespace ipa { /** * \brief Estimate luminance from RGB values following ITU-R BT.601 - * \param[in] r The red value - * \param[in] g The green value - * \param[in] b The blue value + * \param[in] rgb The RGB value * * This function estimates a luminance value from a triplet of Red, Green and * Blue values, following the formula defined by ITU-R Recommendation BT.601-7 @@ -31,21 +29,19 @@ namespace ipa { * * \return The estimated luminance value */ -double rec601LuminanceFromRGB(double r, double g, double b) +double rec601LuminanceFromRGB(const RGB &rgb) { - return (r * .299) + (g * .587) + (b * .114); + return (rgb.r() * .299) + (rgb.g() * .587) + (rgb.b() * .114); } /** * \brief Estimate correlated colour temperature from RGB color space input - * \param[in] red The input red value - * \param[in] green The input green value - * \param[in] blue The input blue value + * \param[in] rgb The RGB value * * This function estimates the correlated color temperature RGB color space * input. In physics and color science, the Planckian locus or black body locus * is the path or locus that the color of an incandescent black body would take - * in a particular chromaticity space as the blackbody temperature changes. + * in a particular chromaticity space as the black body temperature changes. * * If a narrow range of color temperatures is considered (those encapsulating * daylight being the most practical case) one can approximate the Planckian @@ -56,12 +52,12 @@ double rec601LuminanceFromRGB(double r, double g, double b) * * \return The estimated color temperature */ -uint32_t estimateCCT(double red, double green, double blue) +uint32_t estimateCCT(const RGB &rgb) { /* Convert the RGB values to CIE tristimulus values (XYZ) */ - double X = (-0.14282) * (red) + (1.54924) * (green) + (-0.95641) * (blue); - double Y = (-0.32466) * (red) + (1.57837) * (green) + (-0.73191) * (blue); - double Z = (-0.68202) * (red) + (0.77073) * (green) + (0.56332) * (blue); + double X = (-0.14282) * rgb.r() + (1.54924) * rgb.g() + (-0.95641) * rgb.b(); + double Y = (-0.32466) * rgb.r() + (1.57837) * rgb.g() + (-0.73191) * rgb.b(); + double Z = (-0.68202) * rgb.r() + (0.77073) * rgb.g() + (0.56332) * rgb.b(); /* Calculate the normalized chromaticity values */ double x = X / (X + Y + Z); diff --git a/src/ipa/libipa/colours.h b/src/ipa/libipa/colours.h index b42ed0ac1612..fa6a8b575cc7 100644 --- a/src/ipa/libipa/colours.h +++ b/src/ipa/libipa/colours.h @@ -9,12 +9,14 @@ #include +#include "vector.h" + namespace libcamera { namespace ipa { -double rec601LuminanceFromRGB(double r, double g, double b); -uint32_t estimateCCT(double red, double green, double blue); +double rec601LuminanceFromRGB(const RGB &rgb); +uint32_t estimateCCT(const RGB &rgb); } /* namespace ipa */ diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index 5c1d9511ce8b..dbeaf81565ff 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -192,9 +192,7 @@ void Awb::process(IPAContext &context, const rkisp1_cif_isp_stat *params = &stats->params; const rkisp1_cif_isp_awb_stat *awb = ¶ms->awb; IPAActiveState &activeState = context.activeState; - double greenMean; - double redMean; - double blueMean; + RGB rgbMeans; metadata.set(controls::AwbEnable, frameContext.awb.autoEnabled); metadata.set(controls::ColourGains, { @@ -209,9 +207,11 @@ void Awb::process(IPAContext &context, } if (rgbMode_) { - greenMean = awb->awb_mean[0].mean_y_or_g; - redMean = awb->awb_mean[0].mean_cr_or_r; - blueMean = awb->awb_mean[0].mean_cb_or_b; + rgbMeans = {{ + static_cast(awb->awb_mean[0].mean_y_or_g), + static_cast(awb->awb_mean[0].mean_cr_or_r), + static_cast(awb->awb_mean[0].mean_cb_or_b) + }}; } else { /* Get the YCbCr mean values */ double yMean = awb->awb_mean[0].mean_y_or_g; @@ -233,9 +233,11 @@ void Awb::process(IPAContext &context, yMean -= 16; cbMean -= 128; crMean -= 128; - redMean = 1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean; - greenMean = 1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean; - blueMean = 1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean; + rgbMeans = {{ + 1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean, + 1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean, + 1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean + }}; /* * Due to hardware rounding errors in the YCbCr means, the @@ -243,9 +245,7 @@ void Awb::process(IPAContext &context, * negative gains, messing up calculation. Prevent this by * clamping the means to positive values. */ - redMean = std::max(redMean, 0.0); - greenMean = std::max(greenMean, 0.0); - blueMean = std::max(blueMean, 0.0); + rgbMeans = rgbMeans.max(0.0); } /* @@ -253,19 +253,22 @@ void Awb::process(IPAContext &context, * divide by the gains that were used to get the raw means from the * sensor. */ - redMean /= frameContext.awb.gains.red; - greenMean /= frameContext.awb.gains.green; - blueMean /= frameContext.awb.gains.blue; + RGB gains{{ + frameContext.awb.gains.red, + frameContext.awb.gains.green, + frameContext.awb.gains.blue + }}; + rgbMeans /= gains; /* * If the means are too small we don't have enough information to * meaningfully calculate gains. Freeze the algorithm in that case. */ - if (redMean < kMeanMinThreshold && greenMean < kMeanMinThreshold && - blueMean < kMeanMinThreshold) + if (rgbMeans.r() < kMeanMinThreshold && rgbMeans.g() < kMeanMinThreshold && + rgbMeans.b() < kMeanMinThreshold) return; - activeState.awb.temperatureK = estimateCCT(redMean, greenMean, blueMean); + activeState.awb.temperatureK = estimateCCT(rgbMeans); /* Metadata shall contain the up to date measurement */ metadata.set(controls::ColourTemperature, activeState.awb.temperatureK); @@ -275,8 +278,8 @@ void Awb::process(IPAContext &context, * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the * divisor to a minimum value of 1.0. */ - double redGain = greenMean / std::max(redMean, 1.0); - double blueGain = greenMean / std::max(blueMean, 1.0); + double redGain = rgbMeans.g() / std::max(rgbMeans.r(), 1.0); + double blueGain = rgbMeans.g() / std::max(rgbMeans.b(), 1.0); /* * Clamp the gain values to the hardware, which expresses gains as Q2.8 @@ -298,8 +301,8 @@ void Awb::process(IPAContext &context, LOG(RkISP1Awb, Debug) << std::showpoint - << "Means [" << redMean << ", " << greenMean << ", " << blueMean - << "], gains [" << activeState.awb.gains.automatic.red << ", " + << "Means " << rgbMeans + << ", gains [" << activeState.awb.gains.automatic.red << ", " << activeState.awb.gains.automatic.green << ", " << activeState.awb.gains.automatic.blue << "], temp " << activeState.awb.temperatureK << "K"; diff --git a/src/ipa/rpi/controller/rpi/agc_channel.cpp b/src/ipa/rpi/controller/rpi/agc_channel.cpp index 8583f4f31907..a99beb70b89a 100644 --- a/src/ipa/rpi/controller/rpi/agc_channel.cpp +++ b/src/ipa/rpi/controller/rpi/agc_channel.cpp @@ -13,6 +13,7 @@ #include #include "libipa/colours.h" +#include "libipa/vector.h" #include "../awb_status.h" #include "../device_status.h" @@ -680,12 +681,13 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, * Note that the weights are applied by the IPA to the statistics directly, * before they are given to us here. */ - double rSum = 0, gSum = 0, bSum = 0, pixelSum = 0; + ipa::RGB sum{ 0.0 }; + double pixelSum = 0; for (unsigned int i = 0; i < stats->agcRegions.numRegions(); i++) { auto ®ion = stats->agcRegions.get(i); - rSum += std::min(region.val.rSum * gain, (maxVal - 1) * region.counted); - gSum += std::min(region.val.gSum * gain, (maxVal - 1) * region.counted); - bSum += std::min(region.val.bSum * gain, (maxVal - 1) * region.counted); + sum.r() += std::min(region.val.rSum * gain, (maxVal - 1) * region.counted); + sum.g() += std::min(region.val.gSum * gain, (maxVal - 1) * region.counted); + sum.b() += std::min(region.val.bSum * gain, (maxVal - 1) * region.counted); pixelSum += region.counted; } if (pixelSum == 0.0) { @@ -693,14 +695,11 @@ static double computeInitialY(StatisticsPtr &stats, AwbStatus const &awb, return 0; } - double ySum; /* Factor in the AWB correction if needed. */ - if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb) { - ySum = ipa::rec601LuminanceFromRGB(rSum * awb.gainR, - gSum * awb.gainG, - bSum * awb.gainB); - } else - ySum = ipa::rec601LuminanceFromRGB(rSum, gSum, bSum); + if (stats->agcStatsPos == Statistics::AgcStatsPos::PreWb) + sum *= ipa::RGB{{ awb.gainR, awb.gainR, awb.gainB }}; + + double ySum = ipa::rec601LuminanceFromRGB(sum); return ySum / pixelSum / (1 << 16); } From patchwork Tue Nov 19 12:19:25 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22012 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 D2316C32F1 for ; Tue, 19 Nov 2024 12:20:28 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 46BD565F3B; Tue, 19 Nov 2024 13:20:28 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="k/s2eCss"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id EFB9265F38 for ; Tue, 19 Nov 2024 13:20:21 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1DBB91A4A for ; Tue, 19 Nov 2024 13:20:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018804; bh=0iZYBaR+o5G70ZHH7Vi/NBicWWhhajdjTWCDkTGSmBI=; h=From:To:Subject:Date:In-Reply-To:References:From; b=k/s2eCss3cIqK0mDBZGafHYCb2U1Wndw7mNYVxFBY40E0gbq37OssGQX3zVS2ofqN DUlEmUNNIwDh0Ufzi1b8JtXsvr5YNrAuaIGCbJ3YdC6YUmX60X7CQmkU6pixem5tNG FEMLkv8p9R09LvbF8CvXP1N8vmHxKohJLXSKwTJg= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 14/17] ipa: libipa: colour: Use Vector and Matrix for linear algebra Date: Tue, 19 Nov 2024 14:19:25 +0200 Message-ID: <20241119121928.30939-15-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" Replace the manual vector and matrix calculations with usage of the Vector and Matrix classes. This simplifies the code and improves readability. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- src/ipa/libipa/colours.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/ipa/libipa/colours.cpp b/src/ipa/libipa/colours.cpp index 6c597093ddf8..97124cf460d4 100644 --- a/src/ipa/libipa/colours.cpp +++ b/src/ipa/libipa/colours.cpp @@ -31,7 +31,11 @@ namespace ipa { */ double rec601LuminanceFromRGB(const RGB &rgb) { - return (rgb.r() * .299) + (rgb.g() * .587) + (rgb.b() * .114); + static const Vector rgb2y{{ + 0.299, 0.587, 0.114 + }}; + + return rgb.dot(rgb2y); } /** @@ -54,17 +58,21 @@ double rec601LuminanceFromRGB(const RGB &rgb) */ uint32_t estimateCCT(const RGB &rgb) { - /* Convert the RGB values to CIE tristimulus values (XYZ) */ - double X = (-0.14282) * rgb.r() + (1.54924) * rgb.g() + (-0.95641) * rgb.b(); - double Y = (-0.32466) * rgb.r() + (1.57837) * rgb.g() + (-0.73191) * rgb.b(); - double Z = (-0.68202) * rgb.r() + (0.77073) * rgb.g() + (0.56332) * rgb.b(); + /* + * Convert the RGB values to CIE tristimulus values (XYZ) and divide by + * the sum of X, Y and Z to calculate the CIE xy chromaticity. + */ + static const Matrix rgb2xyz({ + -0.14282, 1.54924, -0.95641, + -0.32466, 1.57837, -0.73191, + -0.68202, 0.77073, 0.56332 + }); - /* Calculate the normalized chromaticity values */ - double x = X / (X + Y + Z); - double y = Y / (X + Y + Z); + Vector xyz = rgb2xyz * rgb; + xyz /= xyz.sum(); /* Calculate CCT */ - double n = (x - 0.3320) / (0.1858 - y); + double n = (xyz.x() - 0.3320) / (0.1858 - xyz.y()); return 449 * n * n * n + 3525 * n * n + 6823.3 * n + 5520.33; } From patchwork Tue Nov 19 12:19:26 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22013 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 713ADC32F3 for ; Tue, 19 Nov 2024 12:20:31 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E716C65F41; Tue, 19 Nov 2024 13:20:30 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="P0xw3/Bi"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6F6C565F3B for ; Tue, 19 Nov 2024 13:20:25 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 9BFDA1A4A for ; Tue, 19 Nov 2024 13:20:07 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018807; bh=2BLsRqZ0wvApEx6CVUwoEr7WazrYFC9FciaQ6viBWg8=; h=From:To:Subject:Date:In-Reply-To:References:From; b=P0xw3/BixQvERK62GTPk5j3HYAYJxKhg8K2qX5mCa0c6B8SOVfR7PeHZyodOA24+Y c0lPQokYJg8pfby6aPvI39fEzite+8E8LO5mvm2m2W/RC9ZsZUENYj3kqwGGxSiiGJ zz34cv4IWCsIDjLX/94dMFQWfRVcUHQpmzFZIWE4= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 15/17] ipa: rkisp1: awb: Use RGB class to store colour gains Date: Tue, 19 Nov 2024 14:19:26 +0200 Message-ID: <20241119121928.30939-16-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" Replace the manual storage of gains in the IPA active state and frame context with usage of the RGB class. This simplifies the code thanks to usage of the arithmetic functions provided by the RGB class. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- src/ipa/rkisp1/algorithms/awb.cpp | 71 +++++++++++-------------------- src/ipa/rkisp1/ipa_context.cpp | 31 +------------- src/ipa/rkisp1/ipa_context.h | 20 ++------- 3 files changed, 32 insertions(+), 90 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index dbeaf81565ff..c330feff9f5d 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -47,12 +47,8 @@ Awb::Awb() int Awb::configure(IPAContext &context, const IPACameraSensorInfo &configInfo) { - context.activeState.awb.gains.manual.red = 1.0; - context.activeState.awb.gains.manual.blue = 1.0; - context.activeState.awb.gains.manual.green = 1.0; - context.activeState.awb.gains.automatic.red = 1.0; - context.activeState.awb.gains.automatic.blue = 1.0; - context.activeState.awb.gains.automatic.green = 1.0; + context.activeState.awb.gains.manual = RGB{ 1.0 }; + context.activeState.awb.gains.automatic = RGB{ 1.0 }; context.activeState.awb.autoEnabled = true; /* @@ -89,21 +85,17 @@ void Awb::queueRequest(IPAContext &context, const auto &colourGains = controls.get(controls::ColourGains); if (colourGains && !awb.autoEnabled) { - awb.gains.manual.red = (*colourGains)[0]; - awb.gains.manual.blue = (*colourGains)[1]; + awb.gains.manual.r() = (*colourGains)[0]; + awb.gains.manual.b() = (*colourGains)[1]; LOG(RkISP1Awb, Debug) - << "Set colour gains to red: " << awb.gains.manual.red - << ", blue: " << awb.gains.manual.blue; + << "Set colour gains to " << awb.gains.manual; } frameContext.awb.autoEnabled = awb.autoEnabled; - if (!awb.autoEnabled) { - frameContext.awb.gains.red = awb.gains.manual.red; - frameContext.awb.gains.green = 1.0; - frameContext.awb.gains.blue = awb.gains.manual.blue; - } + if (!awb.autoEnabled) + frameContext.awb.gains = awb.gains.manual; } /** @@ -116,19 +108,16 @@ void Awb::prepare(IPAContext &context, const uint32_t frame, * This is the latest time we can read the active state. This is the * most up-to-date automatic values we can read. */ - if (frameContext.awb.autoEnabled) { - frameContext.awb.gains.red = context.activeState.awb.gains.automatic.red; - frameContext.awb.gains.green = context.activeState.awb.gains.automatic.green; - frameContext.awb.gains.blue = context.activeState.awb.gains.automatic.blue; - } + if (frameContext.awb.autoEnabled) + frameContext.awb.gains = context.activeState.awb.gains.automatic; auto gainConfig = params->block(); gainConfig.setEnabled(true); - gainConfig->gain_green_b = std::clamp(256 * frameContext.awb.gains.green, 0, 0x3ff); - gainConfig->gain_blue = std::clamp(256 * frameContext.awb.gains.blue, 0, 0x3ff); - gainConfig->gain_red = std::clamp(256 * frameContext.awb.gains.red, 0, 0x3ff); - gainConfig->gain_green_r = std::clamp(256 * frameContext.awb.gains.green, 0, 0x3ff); + gainConfig->gain_green_b = std::clamp(256 * frameContext.awb.gains.g(), 0, 0x3ff); + gainConfig->gain_blue = std::clamp(256 * frameContext.awb.gains.b(), 0, 0x3ff); + gainConfig->gain_red = std::clamp(256 * frameContext.awb.gains.r(), 0, 0x3ff); + gainConfig->gain_green_r = std::clamp(256 * frameContext.awb.gains.g(), 0, 0x3ff); /* If we have already set the AWB measurement parameters, return. */ if (frame > 0) @@ -196,8 +185,8 @@ void Awb::process(IPAContext &context, metadata.set(controls::AwbEnable, frameContext.awb.autoEnabled); metadata.set(controls::ColourGains, { - static_cast(frameContext.awb.gains.red), - static_cast(frameContext.awb.gains.blue) + static_cast(frameContext.awb.gains.r()), + static_cast(frameContext.awb.gains.b()) }); metadata.set(controls::ColourTemperature, activeState.awb.temperatureK); @@ -253,12 +242,7 @@ void Awb::process(IPAContext &context, * divide by the gains that were used to get the raw means from the * sensor. */ - RGB gains{{ - frameContext.awb.gains.red, - frameContext.awb.gains.green, - frameContext.awb.gains.blue - }}; - rgbMeans /= gains; + rgbMeans /= frameContext.awb.gains; /* * If the means are too small we don't have enough information to @@ -278,8 +262,11 @@ void Awb::process(IPAContext &context, * gain is hardcoded to 1.0. Avoid divisions by zero by clamping the * divisor to a minimum value of 1.0. */ - double redGain = rgbMeans.g() / std::max(rgbMeans.r(), 1.0); - double blueGain = rgbMeans.g() / std::max(rgbMeans.b(), 1.0); + RGB gains({ + rgbMeans.g() / std::max(rgbMeans.r(), 1.0), + 1.0, + rgbMeans.g() / std::max(rgbMeans.b(), 1.0) + }); /* * Clamp the gain values to the hardware, which expresses gains as Q2.8 @@ -287,24 +274,18 @@ void Awb::process(IPAContext &context, * divisions by zero when computing the raw means in subsequent * iterations. */ - redGain = std::clamp(redGain, 1.0 / 256, 1023.0 / 256); - blueGain = std::clamp(blueGain, 1.0 / 256, 1023.0 / 256); + gains = gains.max(1.0 / 256).min(1023.0 / 256); /* Filter the values to avoid oscillations. */ double speed = 0.2; - redGain = speed * redGain + (1 - speed) * activeState.awb.gains.automatic.red; - blueGain = speed * blueGain + (1 - speed) * activeState.awb.gains.automatic.blue; + gains = gains * speed + activeState.awb.gains.automatic * (1 - speed); - activeState.awb.gains.automatic.red = redGain; - activeState.awb.gains.automatic.blue = blueGain; - activeState.awb.gains.automatic.green = 1.0; + activeState.awb.gains.automatic = gains; LOG(RkISP1Awb, Debug) << std::showpoint - << "Means " << rgbMeans - << ", gains [" << activeState.awb.gains.automatic.red << ", " - << activeState.awb.gains.automatic.green << ", " - << activeState.awb.gains.automatic.blue << "], temp " + << "Means " << rgbMeans << ", gains " + << activeState.awb.gains.automatic << ", temp " << activeState.awb.temperatureK << "K"; } diff --git a/src/ipa/rkisp1/ipa_context.cpp b/src/ipa/rkisp1/ipa_context.cpp index 14d0c02a2b32..8f545cd76d52 100644 --- a/src/ipa/rkisp1/ipa_context.cpp +++ b/src/ipa/rkisp1/ipa_context.cpp @@ -188,30 +188,12 @@ namespace libcamera::ipa::rkisp1 { * \struct IPAActiveState::awb.gains * \brief White balance gains * - * \struct IPAActiveState::awb.gains.manual + * \var IPAActiveState::awb.gains.manual * \brief Manual white balance gains (set through requests) * - * \var IPAActiveState::awb.gains.manual.red - * \brief Manual white balance gain for R channel - * - * \var IPAActiveState::awb.gains.manual.green - * \brief Manual white balance gain for G channel - * - * \var IPAActiveState::awb.gains.manual.blue - * \brief Manual white balance gain for B channel - * - * \struct IPAActiveState::awb.gains.automatic + * \var IPAActiveState::awb.gains.automatic * \brief Automatic white balance gains (computed by the algorithm) * - * \var IPAActiveState::awb.gains.automatic.red - * \brief Automatic white balance gain for R channel - * - * \var IPAActiveState::awb.gains.automatic.green - * \brief Automatic white balance gain for G channel - * - * \var IPAActiveState::awb.gains.automatic.blue - * \brief Automatic white balance gain for B channel - * * \var IPAActiveState::awb.temperatureK * \brief Estimated color temperature * @@ -333,15 +315,6 @@ namespace libcamera::ipa::rkisp1 { * \struct IPAFrameContext::awb.gains * \brief White balance gains * - * \var IPAFrameContext::awb.gains.red - * \brief White balance gain for R channel - * - * \var IPAFrameContext::awb.gains.green - * \brief White balance gain for G channel - * - * \var IPAFrameContext::awb.gains.blue - * \brief White balance gain for B channel - * * \var IPAFrameContext::awb.temperatureK * \brief Estimated color temperature * diff --git a/src/ipa/rkisp1/ipa_context.h b/src/ipa/rkisp1/ipa_context.h index 7b93a9e9461d..b4dec0c3288d 100644 --- a/src/ipa/rkisp1/ipa_context.h +++ b/src/ipa/rkisp1/ipa_context.h @@ -25,6 +25,7 @@ #include #include #include +#include namespace libcamera { @@ -87,16 +88,8 @@ struct IPAActiveState { struct { struct { - struct { - double red; - double green; - double blue; - } manual; - struct { - double red; - double green; - double blue; - } automatic; + RGB manual; + RGB automatic; } gains; unsigned int temperatureK; @@ -140,12 +133,7 @@ struct IPAFrameContext : public FrameContext { } agc; struct { - struct { - double red; - double green; - double blue; - } gains; - + RGB gains; bool autoEnabled; } awb; From patchwork Tue Nov 19 12:19:27 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22014 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 2330FC32F5 for ; Tue, 19 Nov 2024 12:20:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 71F4865F44; Tue, 19 Nov 2024 13:20:35 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="geUyojEj"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 8263365F3E for ; Tue, 19 Nov 2024 13:20:28 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id D4FE01A4A for ; Tue, 19 Nov 2024 13:20:10 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018811; bh=RNPG53cFIFiGz2WIvN4/531MeaV0mTQfhxjMRxaZ+DA=; h=From:To:Subject:Date:In-Reply-To:References:From; b=geUyojEjqDs5grNWazzh3gujitcOBEtLMyvqxy0dBgjWz9yllCN8+LXN5ZaTR6vzc yfLaJcwnog8QXFvyTQ3s8P/Hsq1Qm3bqWoeW/EJR2RaakBFTUcu2I0U0FP1fBddZ0m BSuguK0vKGTjxWI65kY45O/m5bw3As0v41TlJDr8= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 16/17] ipa: rkisp1: awb: Use Vector and Matrix for linear algebra Date: Tue, 19 Nov 2024 14:19:27 +0200 Message-ID: <20241119121928.30939-17-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" Replace the manual vector and matrix calculations with usage of the Vector and Matrix classes. This simplifies the code and improves readability. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v2: - Split colour temperature estimation to separate patch - Update commit message Changes since v1: - Adapt to Vector::normalize() being dropped --- src/ipa/rkisp1/algorithms/awb.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index c330feff9f5d..26d7b8138f17 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -203,9 +203,11 @@ void Awb::process(IPAContext &context, }}; } else { /* Get the YCbCr mean values */ - double yMean = awb->awb_mean[0].mean_y_or_g; - double cbMean = awb->awb_mean[0].mean_cb_or_b; - double crMean = awb->awb_mean[0].mean_cr_or_r; + Vector yuvMeans({ + static_cast(awb->awb_mean[0].mean_y_or_g), + static_cast(awb->awb_mean[0].mean_cb_or_b), + static_cast(awb->awb_mean[0].mean_cr_or_r) + }); /* * Convert from YCbCr to RGB. @@ -219,14 +221,16 @@ void Awb::process(IPAContext &context, * [1,1636, -0,4045, -0,7949] * [1,1636, 1,9912, -0,0250]] */ - yMean -= 16; - cbMean -= 128; - crMean -= 128; - rgbMeans = {{ - 1.1636 * yMean - 0.0623 * cbMean + 1.6008 * crMean, - 1.1636 * yMean - 0.4045 * cbMean - 0.7949 * crMean, - 1.1636 * yMean + 1.9912 * cbMean - 0.0250 * crMean - }}; + static const Matrix yuv2rgbMatrix({ + 1.1636, -0.0623, 1.6008, + 1.1636, -0.4045, -0.7949, + 1.1636, 1.9912, -0.0250 + }); + static const Vector yuv2rgbOffset({ + 16, 128, 128 + }); + + rgbMeans = yuv2rgbMatrix * (yuvMeans - yuv2rgbOffset); /* * Due to hardware rounding errors in the YCbCr means, the From patchwork Tue Nov 19 12:19:28 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 22015 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 12B50C32F1 for ; Tue, 19 Nov 2024 12:20:39 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 567F565F48; Tue, 19 Nov 2024 13:20:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="OTyUKHIh"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 128F565F3B for ; Tue, 19 Nov 2024 13:20:32 +0100 (CET) Received: from pendragon.ideasonboard.com (81-175-209-231.bb.dnainternet.fi [81.175.209.231]) by perceval.ideasonboard.com (Postfix) with ESMTPSA id 1D91C20A4 for ; Tue, 19 Nov 2024 13:20:14 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1732018814; bh=FHRkbjMUxQInW2YKSKd1ARRr3TPKQSJsVhz8lJ2QHug=; h=From:To:Subject:Date:In-Reply-To:References:From; b=OTyUKHIhOdJQ7lcoSucxLNMECDW3Lq2IB4wR7L8JdPk6tc1ewVJnMCqFnrJ6lvRUm 9aFGlL5loBMrgaAxyglZGid+qo4CfyHAntLeosB7sMUBZNqOX1BwDw6rk5YKESXr4N 77+kK9tXKjuKU7GFaimrJ4W+/Zfyozwi7NTyxcMY= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v4 17/17] ipa: rkisp1: awb: Expand comment Date: Tue, 19 Nov 2024 14:19:28 +0200 Message-ID: <20241119121928.30939-18-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241119121928.30939-1-laurent.pinchart@ideasonboard.com> References: <20241119121928.30939-1-laurent.pinchart@ideasonboard.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" The RGB to YCbCr conversion matrix mentioned in a comment, coming from the hardware documentation, does not match any of the canonical matrices specified by any standard. While researching where the values came from, it became apparent they are likely Bt.601 limited range coefficients rounded to 6 bits of decimal precision. Record this in comments. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- src/ipa/rkisp1/algorithms/awb.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ipa/rkisp1/algorithms/awb.cpp b/src/ipa/rkisp1/algorithms/awb.cpp index 26d7b8138f17..4bb4f5b88375 100644 --- a/src/ipa/rkisp1/algorithms/awb.cpp +++ b/src/ipa/rkisp1/algorithms/awb.cpp @@ -210,13 +210,18 @@ void Awb::process(IPAContext &context, }); /* - * Convert from YCbCr to RGB. - * The hardware uses the following formulas: - * Y = 16 + 0.2500 R + 0.5000 G + 0.1094 B + * Convert from YCbCr to RGB. The hardware uses the following + * formulas: + * + * Y = 16 + 0.2500 R + 0.5000 G + 0.1094 B * Cb = 128 - 0.1406 R - 0.2969 G + 0.4375 B * Cr = 128 + 0.4375 R - 0.3750 G - 0.0625 B * - * The inverse matrix is thus: + * This seems to be based on limited range BT.601 with Q1.6 + * precision. + * + * The inverse matrix is: + * * [[1,1636, -0,0623, 1,6008] * [1,1636, -0,4045, -0,7949] * [1,1636, 1,9912, -0,0250]]