From patchwork Mon Nov 18 22:16:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21961 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 F355DC32EA for ; Mon, 18 Nov 2024 22:16:33 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 5AABC658F6; Mon, 18 Nov 2024 23:16:33 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="mxs0h8Vc"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 93706658EA for ; Mon, 18 Nov 2024 23:16:29 +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 934916DE for ; Mon, 18 Nov 2024 23:16:12 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968172; bh=flPWboZjiZjFOSn+7VXCGQdCyul9jGvDM1bImb3MlZI=; h=From:To:Subject:Date:In-Reply-To:References:From; b=mxs0h8VcjqyaKNtTLNFxbkQ+LZ4b55fc3yMSe1hiKPzLiNWIZHrfkAiZLebdRJdSx BPMX9zavz+vz9qAZXg2AcP0Nk4Cyzfztd+FC8K/6KffWxnNQ/GoKQlwv2ZhAVr7ap+ UPCk55iyvc1BQc2ZRQkD+j4tqiEYdSQ7owQAOxxY= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 01/17] ipa: libipa: vector: Add mutable x(), y() and z() accessors Date: Tue, 19 Nov 2024 00:16:02 +0200 Message-ID: <20241118221618.13953-2-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 --- 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..8a39bfd27f90 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 T &Vector::x() + * \brief Convenience function to access the first element of the vector + * \return The first element of the vector + */ + +/** + * \fn T &Vector::y() + * \brief Convenience function to access the second element of the vector + * \return The second element of the vector + */ + +/** + * \fn 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..1b11a34deee4 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__ */ + T &x() { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + T &y() { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + T &z() { return data_[2]; } + constexpr double length2() const { double ret = 0; From patchwork Mon Nov 18 22:16:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21962 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 8F7A8C32EA for ; Mon, 18 Nov 2024 22:16:36 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 0A402658F3; Mon, 18 Nov 2024 23:16:35 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ORcyV+zS"; 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 261EC658F2 for ; Mon, 18 Nov 2024 23:16:31 +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 EADD96DE for ; Mon, 18 Nov 2024 23:16:13 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968174; bh=5FJorzt8vTQ5JAV376oBgqvBlLrZxLuMEpMah8S3HeM=; h=From:To:Subject:Date:In-Reply-To:References:From; b=ORcyV+zSpMLjuC4js18gfUq36HVy+6HBzeqllEWaSpW4iSgIsDtbIIN5UnYjnM0km Q195Sf3f9irN9hSjqXzuA8dawN3huBw9gjNZCwXKc3IVSXqgm6tlip+NqPDBPvruYY 02avXy6ShgnqRWQXDjzJYYLAcUrSOGNCASkhEiWw= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 02/17] ipa: libipa: vector: Add r(), g() and b() accessors Date: Tue, 19 Nov 2024 00:16:03 +0200 Message-ID: <20241118221618.13953-3-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 --- 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 8a39bfd27f90..f14f155216f3 100644 --- a/src/ipa/libipa/vector.cpp +++ b/src/ipa/libipa/vector.cpp @@ -126,6 +126,39 @@ namespace ipa { * \copydoc Vector::z() */ +/** + * \fn T &Vector::r() + * \brief Convenience function to access the first element of the vector + * \return The first element of the vector + */ + +/** + * \fn T &Vector::g() + * \brief Convenience function to access the second element of the vector + * \return The second element of the vector + */ + +/** + * \fn 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 1b11a34deee4..b72ab9851aa3 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -126,6 +126,31 @@ public: #endif /* __DOXYGEN__ */ 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__ */ + T &r() { return data_[0]; } +#ifndef __DOXYGEN__ + template= 2>> +#endif /* __DOXYGEN__ */ + T &g() { return data_[1]; } +#ifndef __DOXYGEN__ + template= 3>> +#endif /* __DOXYGEN__ */ + 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 Mon Nov 18 22:16:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21963 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 9BC70C32EA for ; Mon, 18 Nov 2024 22:16:38 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 377AD658FE; Mon, 18 Nov 2024 23:16:38 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="dWg+j6vf"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 623F8658EF for ; Mon, 18 Nov 2024 23:16: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 5DB2D8DB for ; Mon, 18 Nov 2024 23:16:15 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968175; bh=/F4cJONraqeugqVic2iAeCnfpBopoCBdtsQ4oAySm3U=; h=From:To:Subject:Date:In-Reply-To:References:From; b=dWg+j6vf0oBTfnTkzlCn2ubnNbYcwE9tZCIJbzQ+YwlLwIHseg2U/mjG64Sakkl+2 1s6SMGlJ28pUF5A15PAgoIq7gROWX1r3w2aHXgxh/4Wf0hM0uqP6cvoj088HhA+1Hx jTSkMqyvhpGkMxuOelmcXaf/Etxr/ioUPm4tkljM= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 03/17] ipa: libipa: vector: Add scalar constructor Date: Tue, 19 Nov 2024 00:16:04 +0200 Message-ID: <20241118221618.13953-4-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 --- 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 f14f155216f3..d414ba97e41e 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 b72ab9851aa3..be568eadfeac 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -35,6 +35,11 @@ class Vector public: constexpr Vector() = default; + constexpr Vector(T scalar) + { + data_.fill(scalar); + } + constexpr Vector(const std::array &data) { for (unsigned int i = 0; i < Rows; i++) From patchwork Mon Nov 18 22:16:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21964 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 4F858C32EA for ; Mon, 18 Nov 2024 22:16:42 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BD9F1658FB; Mon, 18 Nov 2024 23:16:41 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="wZVblFTt"; 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 B7E1B658F9 for ; Mon, 18 Nov 2024 23:16:33 +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 B48778DB for ; Mon, 18 Nov 2024 23:16:16 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968176; bh=8rcuaTIQJIPsp30V5RFodG0Vgjh3hhCgRHL2U2sQoro=; h=From:To:Subject:Date:In-Reply-To:References:From; b=wZVblFTtAXixJ5xQJwHbhIE+pAnV+RuSETtCD4/mdzBOGwKLggZAhzj/iE6453gAa VaFDKafpVmqIKvO8oMxjthEFuE6pcAHj5HQnm/ADnbOrAqQJR2Tv6BD2X9fi2sWvGy Sg+ag5Qoe/VQ/qslhiX3G0z+Kvyh2Dct6l3zbVfI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 04/17] ipa: libipa: vector: Add copy constructor and assignment operator Date: Tue, 19 Nov 2024 00:16:05 +0200 Message-ID: <20241118221618.13953-5-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 v2: - Make copy constructor constexpr - Drop #include --- src/ipa/libipa/vector.cpp | 13 +++++++++++++ src/ipa/libipa/vector.h | 12 ++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index d414ba97e41e..80f1758578f0 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 be568eadfeac..35fc9539dc99 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -46,6 +46,18 @@ public: data_[i] = data[i]; } + constexpr Vector(const Vector &other) + : data_(other.data_) + { + } + + Vector &operator=(const Vector &other) + { + data_ = other.data_; + + return *this; + } + const T &operator[](size_t i) const { ASSERT(i < data_.size()); From patchwork Mon Nov 18 22:16:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21965 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 4DA31C32EA for ; Mon, 18 Nov 2024 22:16:44 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E5643658FC; Mon, 18 Nov 2024 23:16:43 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="bsKF+HeG"; 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 2DEBE658F4 for ; Mon, 18 Nov 2024 23:16:35 +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 1DAAA6DE for ; Mon, 18 Nov 2024 23:16:18 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968178; bh=VaT9bMYGwLdZla0QqP0x1Gz+ElYdMvISlbfY5o4bzRI=; h=From:To:Subject:Date:In-Reply-To:References:From; b=bsKF+HeG7Ufa3X2KIs79Yv1AAnKiblCwhDIzFx8caCOgRdEMF2fzGz+tBrxoHcLFZ fnCgjFyZj7OHmKmkpgYxono69mpBXcT4jaG+fg+NySJri2WF0oVoJUL+1Ul/zyJdLB zqwjC+9NQvZ2Yrgq7Rt5XgYCn5ihcuSZREnOek9w= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 05/17] ipa: libipa: vector: Rename the dot product operator*() to dot() Date: Tue, 19 Nov 2024 00:16:06 +0200 Message-ID: <20241118221618.13953-6-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 80f1758578f0..143ee9262f05 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 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 35fc9539dc99..2abb5536361c 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -94,14 +94,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; @@ -118,6 +110,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 Mon Nov 18 22:16:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21966 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 29B4BC32EA for ; Mon, 18 Nov 2024 22:16:46 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A780665ED5; Mon, 18 Nov 2024 23:16:45 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="PEeTwrqA"; 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 868F6658F5 for ; Mon, 18 Nov 2024 23:16:36 +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 7C7E56DE for ; Mon, 18 Nov 2024 23:16:19 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968179; bh=6ZDifGd+wZiBl42L+P8oClq9yu8AHmknQmHW7qHC0/A=; h=From:To:Subject:Date:In-Reply-To:References:From; b=PEeTwrqArIff+EQbCxLPYD5Zh6upVSKPIbZyWfwlkcLTP7lgNTuaqRaloVF4w+Wgr w/f6o7p4rI8hjwGOXgepII1iKRkrNsnmRwWWJ7P64ClH/gKwhNCYUevBROhZZhK+We RbHdzjdznCqhFQ1k5w1J4CenPRaI/SEX2vDrpHyE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 06/17] ipa: libipa: vector: Generalize arithmetic operators Date: Tue, 19 Nov 2024 00:16:07 +0200 Message-ID: <20241118221618.13953-7-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 std::function. This will simplify adding missing arithmetic operators. Signed-off-by: Laurent Pinchart Reviewed-by: Milan Zamazal --- Changes since v2: - Include - Use std::plus, std::minus, std::multiplies and std::divides --- src/ipa/libipa/vector.h | 50 ++++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/src/ipa/libipa/vector.h b/src/ipa/libipa/vector.h index 2abb5536361c..76fd2934b870 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 @@ -78,36 +80,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 @@ -182,6 +172,26 @@ public: } private: + static constexpr Vector apply(const Vector &lhs, const Vector &rhs, std::function func) + { + Vector result; + std::transform(lhs.data_.begin(), lhs.data_.end(), + rhs.data_.begin(), result.data_.begin(), + func); + + return result; + } + + static constexpr Vector apply(const Vector &lhs, T rhs, std::function func) + { + Vector result; + std::transform(lhs.data_.begin(), lhs.data_.end(), + result.data_.begin(), + [&func, rhs](T v) { return func(v, rhs); }); + + return result; + } + std::array data_; }; From patchwork Mon Nov 18 22:16:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21967 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 B8DBAC32EA for ; Mon, 18 Nov 2024 22:16:48 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id E06DC65904; Mon, 18 Nov 2024 23:16:47 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ilD6vlyu"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id D3043658FB for ; Mon, 18 Nov 2024 23:16:37 +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 DD8258DB for ; Mon, 18 Nov 2024 23:16:20 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968181; bh=RGa3DPbSiu66UA1a5vLH2UJf2jGLe7CJXsiMRW1gvjE=; h=From:To:Subject:Date:In-Reply-To:References:From; b=ilD6vlyudu9O2CyjqXtf2H3M/118m62Y9wgZ8kczt7NCuaoSw4ZHdTOnIA8zizALB ZhctiE6fRxFEExf2+7ZEL7LplfWknc2S1zfKtayGIGhLven0YaEWZBn/+vMm3I9WP5 xcWx0OqCaE3FK8FZIcW4KmbvP5Qg/XWdj0zPQBiI= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 07/17] ipa: libipa: vector: Add missing binary arithemtic operators Date: Tue, 19 Nov 2024 00:16:08 +0200 Message-ID: <20241118221618.13953-8-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 143ee9262f05..d8f7ce951d60 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 76fd2934b870..88f2a03fe579 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -80,24 +80,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 Mon Nov 18 22:16:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21968 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 7341BC32F0 for ; Mon, 18 Nov 2024 22:16:50 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 815A465ED9; Mon, 18 Nov 2024 23:16:49 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="aI4wdJlB"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 361EF65902 for ; Mon, 18 Nov 2024 23:16:39 +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 2DC0F6DE for ; Mon, 18 Nov 2024 23:16:22 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968182; bh=WZPXj2Nuz3Z3KOJiIMd6JFdDT9rTF9Sb3WJ1nfRI+jI=; h=From:To:Subject:Date:In-Reply-To:References:From; b=aI4wdJlBRpjWh+nF04xxyKCQ9IXrHH+2gPQlqYrx+cWLZfg8QL1pXWjcRUq14NgnW Y+WrzAbYPck6baUIsFSi5y5R6XoEWI6OgpgsfEP3+Rf4JQRT3jK85BMzqX0BnvpWHu R9gFCEPNbqxD6GAq8pop/Hd+9ZHMMWKUJlnUK3sE= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 08/17] ipa: libipa: vector: Add compound assignment operators Date: Tue, 19 Nov 2024 00:16:09 +0200 Message-ID: <20241118221618.13953-9-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 v2: - Use std::plus, std::minus, std::multiplies and std::divides --- src/ipa/libipa/vector.cpp | 56 ++++++++++++++++++++++++++++++++++++++ src/ipa/libipa/vector.h | 57 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 113 insertions(+) diff --git a/src/ipa/libipa/vector.cpp b/src/ipa/libipa/vector.cpp index d8f7ce951d60..64ffcf5036a4 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 88f2a03fe579..15f511653b60 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -120,6 +120,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; @@ -212,6 +252,23 @@ private: return result; } + Vector &apply(const Vector &other, std::function func) + { + auto itOther = other.data_.begin(); + std::for_each(data_.begin(), data_.end(), + [&func, &itOther](T &v) { v = func(v, *itOther++); }); + + return *this; + } + + Vector &apply(T scalar, std::function func) + { + std::for_each(data_.begin(), data_.end(), + [&func, scalar](T &v) { v = func(v, scalar); }); + + return *this; + } + std::array data_; }; From patchwork Mon Nov 18 22:16:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21969 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 A7D06C32EA for ; Mon, 18 Nov 2024 22:16:51 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 26EDD65905; Mon, 18 Nov 2024 23:16:51 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="b8eLwwEt"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 7DEBF658F6 for ; Mon, 18 Nov 2024 23:16:40 +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 86CA08DB for ; Mon, 18 Nov 2024 23:16:23 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968183; bh=e5yIhDKeKmWDxXmNZ5GaJ7A3z+6gzmeEHE8dB2zg5R0=; h=From:To:Subject:Date:In-Reply-To:References:From; b=b8eLwwEtWlk6oiA4ESvEi3powk1bR0dryTGqGM9XUKzdXYNu7sA83jLRcIBhCs/Zs 8XzNlDOVJIJrVjOkRLT9GGjUqsqBYalMAGqSbXTIBiGsk8jOCMCYjq9ACbbyHED/27 nTvb+V/gEPZzr8vk4t3MOY6DhItdyINpEds/6+7I= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 09/17] ipa: libipa: vector: Add element-wise min() and max() functions Date: Tue, 19 Nov 2024 00:16:10 +0200 Message-ID: <20241118221618.13953-10-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 64ffcf5036a4..56c494a7e4da 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 15f511653b60..3fed9570bf62 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -160,6 +160,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 Mon Nov 18 22:16:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Pinchart X-Patchwork-Id: 21970 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 288C3C32F0 for ; Mon, 18 Nov 2024 22:16:53 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 9ACFD65ED9; Mon, 18 Nov 2024 23:16:52 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="XjZcu67r"; 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 DC130658FE for ; Mon, 18 Nov 2024 23:16:41 +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 D0D056DE for ; Mon, 18 Nov 2024 23:16:24 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968185; bh=CfQrts0FGzibO3+YYYZdwluX8ReZ/57VWl/f+nCSqpM=; h=From:To:Subject:Date:In-Reply-To:References:From; b=XjZcu67rNEoqSddSHkX2BUvHfMQKRs8wwesJPNoMLljbsSIRMW9B31rvoBKjGgc8P cW3BbQNtbL4HCdATCvM1jVB5RTMnL89NAYopJTHjki+SeORg9GEp79STtSC00ZhU9G ct8KHTtwJmG+LRYgdZZI5VeniulvslWdY2DdmJKQ= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 10/17] ipa: libipa: vector: Add sum() function Date: Tue, 19 Nov 2024 00:16:11 +0200 Message-ID: <20241118221618.13953-11-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 56c494a7e4da..a1ad47cd046b 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 3fed9570bf62..564292743829 100644 --- a/src/ipa/libipa/vector.h +++ b/src/ipa/libipa/vector.h @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -251,6 +252,12 @@ public: return std::sqrt(length2()); } + template + constexpr R sum() const + { + return std::accumulate(data_.begin(), data_.end(), R{}); + } + private: static constexpr Vector apply(const Vector &lhs, const Vector &rhs, std::function func) { From patchwork Mon Nov 18 22:16: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: 21971 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 0E0F3C32EA for ; Mon, 18 Nov 2024 22:16:55 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id BB3DB65ED6; Mon, 18 Nov 2024 23:16:53 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="ZxmlRn3s"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 40C81658F9 for ; Mon, 18 Nov 2024 23:16:43 +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 328B66DE for ; Mon, 18 Nov 2024 23:16:26 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968186; bh=AWwtAnZYgaczRoTVwL5Kd/UZfsIOE2iUa5X6/0Wnw3I=; h=From:To:Subject:Date:In-Reply-To:References:From; b=ZxmlRn3s2OtzO88Xh7crwpaF9fW6+2zRMtFf2FwKF5XvGEHw0S3jntTLYDvJsWNTb /6RygkEBLRzwAxEF7+mGFQ3IKI/ez5Yskq12F1+3y7aDojb5yVIVPpSB8uS/Sfmed5 2Ihun9LejCqeyPldTmjpm6wJ6U9XH5Hx7idDpnd0= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 11/17] test: libipa: Add Vector class test Date: Tue, 19 Nov 2024 00:16:12 +0200 Message-ID: <20241118221618.13953-12-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 Mon Nov 18 22:16: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: 21972 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 B5102C32EA for ; Mon, 18 Nov 2024 22:16:58 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 6676F65ED8; Mon, 18 Nov 2024 23:16:58 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="oWFkmIwP"; 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 9992465906 for ; Mon, 18 Nov 2024 23:16: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 8E83A6DE for ; Mon, 18 Nov 2024 23:16:27 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968187; bh=+ZTXoiMpZm1TAEtU2dsP30+mo6sIv7tz0ORoRHVKbfs=; h=From:To:Subject:Date:In-Reply-To:References:From; b=oWFkmIwP2hZOqb80LJTWd+lhtAXJQ8My8tqxGgv9lmyGXfO69wUdQ2KIEoG3chYBv BwQC/PUihuDozc6okF3zBbKTt9FXjoDQ5VmzL/OzpAQYT1Ll0K1RP9SfC6n3spjOxY WpmxFj5oUE/KdEbdKjRqBctquKUiokFmpqj9in1s= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 12/17] ipa: ipu3: awb: Replace Awb::RGB class with ipa::RGB Date: Tue, 19 Nov 2024 00:16:13 +0200 Message-ID: <20241118221618.13953-13-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 Mon Nov 18 22:16: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: 21973 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 755A5C32F0 for ; Mon, 18 Nov 2024 22:17:00 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id A2CD765EE9; Mon, 18 Nov 2024 23:16:59 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="uMaf+x5S"; 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 0425F658FC for ; Mon, 18 Nov 2024 23:16: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 EE8418DB for ; Mon, 18 Nov 2024 23:16:28 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968189; bh=Ipm5bKH+UlIsSXDdQf8fVMRQNwTu3V2nmuWjTyaaFl8=; h=From:To:Subject:Date:In-Reply-To:References:From; b=uMaf+x5SoFzskogiJdyXu4+8ugIZzN+aFDtYoQCKUoMF+hKZKHLfhHRmmAcJnZUkj D4R6crf9A/CmqV4LRlzn0OCCWUL4SwsH6WGeuT1KtNBlzHn8wd3amQotCc6orKqOgO rAFeT7mWOzWvUy+kbJyFP11wMp1sRZBVlLpHdBro= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 13/17] ipa: libipa: colour: Use the RGB class to model RGB values Date: Tue, 19 Nov 2024 00:16:14 +0200 Message-ID: <20241118221618.13953-14-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 moduels 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 Mon Nov 18 22:16: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: 21974 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 C015EC32EA for ; Mon, 18 Nov 2024 22:17:01 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 2D64565EDE; Mon, 18 Nov 2024 23:17:01 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="DtUGI5cu"; 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 4D4B565ED7 for ; Mon, 18 Nov 2024 23:16:47 +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 403F16DE for ; Mon, 18 Nov 2024 23:16:30 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968190; bh=N9tLch1jQfpIYwSzEcB9jFULCeIarc+8nDnmozhrnrQ=; h=From:To:Subject:Date:In-Reply-To:References:From; b=DtUGI5cugpLpXFhpicXlvCr2O/sUtsdEFIuqWFZHB0+NlP1BLcQ7H3eqE+TF6qrBe /nOMCx4mNT92HYjsNEc/pDLAaznmzEuSOSpgZtF+Vjx28QrvELtCWUSN93i8mI0Q/n 4e3uEUcRF4rli9h5OSTDcGlHgQLT85XIKa7gKquA= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 14/17] ipa: libipa: colour: Use Vector and Matrix for linear algebra Date: Tue, 19 Nov 2024 00:16:15 +0200 Message-ID: <20241118221618.13953-15-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 Mon Nov 18 22:16: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: 21975 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 3D6DDC32F0 for ; Mon, 18 Nov 2024 22:17:04 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id 95C5265EE4; Mon, 18 Nov 2024 23:17:03 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="wbIJQNW2"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id A813B65ED5 for ; Mon, 18 Nov 2024 23:16:48 +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 9A7F56DE for ; Mon, 18 Nov 2024 23:16:31 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968191; bh=kCGkI5awc1sOrdtp9sDY95oyT1K6jXBY+I7HgQyzjhw=; h=From:To:Subject:Date:In-Reply-To:References:From; b=wbIJQNW2QiE4CQqkHu7odgt7K/4LOLbTR1n2+LxO2kVBhfSfHb3vdowLN9dL9cwMj v+g9wt7WDkI6NCDVJgksE20cwTYRgZEYWpls4kidy5BGyOC+UMCV8NQxa3msafzQmb iIoRQ5oToFsEkdodDPzXkBceyiiO9qD0+twEW1CY= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 15/17] ipa: rkisp1: awb: Use RGB class to store colour gains Date: Tue, 19 Nov 2024 00:16:16 +0200 Message-ID: <20241118221618.13953-16-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 Mon Nov 18 22:16: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: 21976 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 5E4CEC32EA for ; Mon, 18 Nov 2024 22:17:05 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id D043F65EE3; Mon, 18 Nov 2024 23:17:04 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="rwuWEl2r"; 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 16B71658F7 for ; Mon, 18 Nov 2024 23:16:50 +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 0353E8DB for ; Mon, 18 Nov 2024 23:16:32 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968193; bh=RNPG53cFIFiGz2WIvN4/531MeaV0mTQfhxjMRxaZ+DA=; h=From:To:Subject:Date:In-Reply-To:References:From; b=rwuWEl2r96rXNTZJGQ1PQrpXFw5oncuhMBA3e2Vrf9x/f6lLPd0lEM3pfFv0BP7Yj jKYVYmz11dGUvYx7kMDrmCZqJzvu2qHH3WmkcbPkAf1vEPAz3igLWBpNmzosUfjW8l BXKmWxSwWjBnaMzLX/ekiUUNMobX2pGJKZ/+QPdo= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 16/17] ipa: rkisp1: awb: Use Vector and Matrix for linear algebra Date: Tue, 19 Nov 2024 00:16:17 +0200 Message-ID: <20241118221618.13953-17-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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 Mon Nov 18 22:16: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: 21977 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 92873C32F0 for ; Mon, 18 Nov 2024 22:17:06 +0000 (UTC) Received: from lancelot.ideasonboard.com (localhost [IPv6:::1]) by lancelot.ideasonboard.com (Postfix) with ESMTP id F345A65EDF; Mon, 18 Nov 2024 23:17:05 +0100 (CET) Authentication-Results: lancelot.ideasonboard.com; dkim=pass (1024-bit key; unprotected) header.d=ideasonboard.com header.i=@ideasonboard.com header.b="HTdlQL5s"; dkim-atps=neutral Received: from perceval.ideasonboard.com (perceval.ideasonboard.com [213.167.242.64]) by lancelot.ideasonboard.com (Postfix) with ESMTPS id 6701065EDD for ; Mon, 18 Nov 2024 23:16:51 +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 5F1148DB for ; Mon, 18 Nov 2024 23:16:34 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com; s=mail; t=1731968194; bh=/XTcCf7GgzVrQeALl6c200OUkd+x2DRlPNXv8XuCRrw=; h=From:To:Subject:Date:In-Reply-To:References:From; b=HTdlQL5sw3lPK6h3QECNUM7ucWDkJzfhcDmZ6/RgdZymg6RZtnZPtJk0tGUO/HHsc LOjDN4NUvNlOph/fcTbzRgLaLiMRPUwUAw8booGKmLrvpSfkiFhBJqQRJta0OkfyoI b764ccTh+1CY8UE6wbx4HUBUUghh0sIEhWMW2SlQ= From: Laurent Pinchart To: libcamera-devel@lists.libcamera.org Subject: [PATCH v3 17/17] ipa: rkisp1: awb: Expand comment Date: Tue, 19 Nov 2024 00:16:18 +0200 Message-ID: <20241118221618.13953-18-laurent.pinchart@ideasonboard.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241118221618.13953-1-laurent.pinchart@ideasonboard.com> References: <20241118221618.13953-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]]