[2/2] libcamera: converter: converter_dw100: Allow to transform between different camera matrices
diff mbox series

Message ID 20260617095857.667583-3-stefan.klug@ideasonboard.com
State Superseded
Headers show
Series
  • Add cmNew to dewarp paremeters
Related show

Commit Message

Stefan Klug June 17, 2026, 9:58 a.m. UTC
For some use cases (like removing a skew introduced by the camera
geometry) it is necessary to define the output camera matrix. Add that
functionality by adding an optional tuning parameter "cmNew" to the
Dewarp configuration. If that parameter is not provided, cm is used
instead.

Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>

---

Changes in v0.2:
- Swapped cm and cmNew in the output calculation
---
 .../converter/converter_dw100_vertexmap.h         |  2 ++
 src/libcamera/converter/converter_dw100.cpp       | 15 ++++++++++++++-
 .../converter/converter_dw100_vertexmap.cpp       |  8 ++++++--
 3 files changed, 22 insertions(+), 3 deletions(-)

Comments

Laurent Pinchart June 17, 2026, 2:41 p.m. UTC | #1
Hi Stefan,

Thank you for the patch.

On Wed, Jun 17, 2026 at 11:58:50AM +0200, Stefan Klug wrote:
> For some use cases (like removing a skew introduced by the camera
> geometry) it is necessary to define the output camera matrix. Add that
> functionality by adding an optional tuning parameter "cmNew" to the
> Dewarp configuration. If that parameter is not provided, cm is used
> instead.

After reading the commit message and the patch I have no idea what
"cmNew" is. More effort is required on the documentation side somewhere.

> Signed-off-by: Stefan Klug <stefan.klug@ideasonboard.com>
> 
> ---
> 
> Changes in v0.2:
> - Swapped cm and cmNew in the output calculation
> ---
>  .../converter/converter_dw100_vertexmap.h         |  2 ++
>  src/libcamera/converter/converter_dw100.cpp       | 15 ++++++++++++++-
>  .../converter/converter_dw100_vertexmap.cpp       |  8 ++++++--
>  3 files changed, 22 insertions(+), 3 deletions(-)
> 
> diff --git a/include/libcamera/internal/converter/converter_dw100_vertexmap.h b/include/libcamera/internal/converter/converter_dw100_vertexmap.h
> index 787498c7fdb5..d60997f56ad5 100644
> --- a/include/libcamera/internal/converter/converter_dw100_vertexmap.h
> +++ b/include/libcamera/internal/converter/converter_dw100_vertexmap.h
> @@ -33,11 +33,13 @@ public:
>  
>  	struct DewarpParams {
>  		DewarpParams() : cm(Matrix<double, 3, 3>::identity()),
> +				 cmNew(Matrix<double, 3, 3>::identity()),
>  				 coefficients({})
>  		{
>  		}
>  
>  		Matrix<double, 3, 3> cm;
> +		Matrix<double, 3, 3> cmNew;
>  
>  		union {
>  			struct {
> diff --git a/src/libcamera/converter/converter_dw100.cpp b/src/libcamera/converter/converter_dw100.cpp
> index 34f81c6b9fab..97a025b7f961 100644
> --- a/src/libcamera/converter/converter_dw100.cpp
> +++ b/src/libcamera/converter/converter_dw100.cpp
> @@ -104,9 +104,10 @@ int ConverterDW100Module::init(const ValueNode &params)
>  
>  	auto &cm = params["cm"];
>  	auto &coefficients = params["coefficients"];
> +	auto &cmNew = params["cmNew"];
>  
>  	/* If nothing is provided, the dewarper is still functional */
> -	if (!cm && !coefficients)
> +	if (!cm && !coefficients && !cmNew)
>  		return 0;
>  
>  	if (!cm) {
> @@ -142,6 +143,18 @@ int ConverterDW100Module::init(const ValueNode &params)
>  
>  	std::copy(coeffs->begin(), coeffs->end(), &dp.coefficients[0]);
>  
> +	if (cmNew) {
> +		matrix = cmNew.get<Matrix<double, 3, 3>>();
> +		if (!matrix) {
> +			LOG(Converter, Error) << "Failed to load 'cmNew' value";
> +			return -EINVAL;
> +		}
> +
> +		dp.cmNew = *matrix;
> +	} else {
> +		dp.cmNew = dp.cm;
> +	}
> +
>  	dewarpParams_ = dp;
>  
>  	return 0;
> diff --git a/src/libcamera/converter/converter_dw100_vertexmap.cpp b/src/libcamera/converter/converter_dw100_vertexmap.cpp
> index 31d992546857..22e08656d36d 100644
> --- a/src/libcamera/converter/converter_dw100_vertexmap.cpp
> +++ b/src/libcamera/converter/converter_dw100_vertexmap.cpp
> @@ -234,6 +234,9 @@ int dw100VerticesForLength(const int length)
>   * \var Dw100VertexMap::DewarpParams::cm
>   * \brief The camera matrix
>   *
> + * \var Dw100VertexMap::DewarpParams::cmNew
> + * \brief The new camera matrix after dewarping
> + *
>   * \var Dw100VertexMap::DewarpParams::coefficient
>   * \brief Structure containing the lens dewarp coefficients
>  
> @@ -619,10 +622,11 @@ Vector2d Dw100VertexMap::dewarpPoint(const Vector2d &p)
>  	double x, y;
>  	double xout, yout;
>  	auto &cm = dewarpParams_->cm;
> +	auto &cmNew = dewarpParams_->cmNew;
>  	auto &c = dewarpParams_->coefficient;
>  
> -	y = (p.y() - cm[1][2]) / cm[1][1];
> -	x = (p.x() - cm[0][2] - y * cm[0][1]) / cm[0][0];
> +	y = (p.y() - cmNew[1][2]) / cmNew[1][1];
> +	x = (p.x() - cmNew[0][2] - y * cmNew[0][1]) / cmNew[0][0];
>  
>  	double r2 = x * x + y * y;
>  	double r4 = r2 * r2;
> -- 
> 2.53.0
>

Patch
diff mbox series

diff --git a/include/libcamera/internal/converter/converter_dw100_vertexmap.h b/include/libcamera/internal/converter/converter_dw100_vertexmap.h
index 787498c7fdb5..d60997f56ad5 100644
--- a/include/libcamera/internal/converter/converter_dw100_vertexmap.h
+++ b/include/libcamera/internal/converter/converter_dw100_vertexmap.h
@@ -33,11 +33,13 @@  public:
 
 	struct DewarpParams {
 		DewarpParams() : cm(Matrix<double, 3, 3>::identity()),
+				 cmNew(Matrix<double, 3, 3>::identity()),
 				 coefficients({})
 		{
 		}
 
 		Matrix<double, 3, 3> cm;
+		Matrix<double, 3, 3> cmNew;
 
 		union {
 			struct {
diff --git a/src/libcamera/converter/converter_dw100.cpp b/src/libcamera/converter/converter_dw100.cpp
index 34f81c6b9fab..97a025b7f961 100644
--- a/src/libcamera/converter/converter_dw100.cpp
+++ b/src/libcamera/converter/converter_dw100.cpp
@@ -104,9 +104,10 @@  int ConverterDW100Module::init(const ValueNode &params)
 
 	auto &cm = params["cm"];
 	auto &coefficients = params["coefficients"];
+	auto &cmNew = params["cmNew"];
 
 	/* If nothing is provided, the dewarper is still functional */
-	if (!cm && !coefficients)
+	if (!cm && !coefficients && !cmNew)
 		return 0;
 
 	if (!cm) {
@@ -142,6 +143,18 @@  int ConverterDW100Module::init(const ValueNode &params)
 
 	std::copy(coeffs->begin(), coeffs->end(), &dp.coefficients[0]);
 
+	if (cmNew) {
+		matrix = cmNew.get<Matrix<double, 3, 3>>();
+		if (!matrix) {
+			LOG(Converter, Error) << "Failed to load 'cmNew' value";
+			return -EINVAL;
+		}
+
+		dp.cmNew = *matrix;
+	} else {
+		dp.cmNew = dp.cm;
+	}
+
 	dewarpParams_ = dp;
 
 	return 0;
diff --git a/src/libcamera/converter/converter_dw100_vertexmap.cpp b/src/libcamera/converter/converter_dw100_vertexmap.cpp
index 31d992546857..22e08656d36d 100644
--- a/src/libcamera/converter/converter_dw100_vertexmap.cpp
+++ b/src/libcamera/converter/converter_dw100_vertexmap.cpp
@@ -234,6 +234,9 @@  int dw100VerticesForLength(const int length)
  * \var Dw100VertexMap::DewarpParams::cm
  * \brief The camera matrix
  *
+ * \var Dw100VertexMap::DewarpParams::cmNew
+ * \brief The new camera matrix after dewarping
+ *
  * \var Dw100VertexMap::DewarpParams::coefficient
  * \brief Structure containing the lens dewarp coefficients
 
@@ -619,10 +622,11 @@  Vector2d Dw100VertexMap::dewarpPoint(const Vector2d &p)
 	double x, y;
 	double xout, yout;
 	auto &cm = dewarpParams_->cm;
+	auto &cmNew = dewarpParams_->cmNew;
 	auto &c = dewarpParams_->coefficient;
 
-	y = (p.y() - cm[1][2]) / cm[1][1];
-	x = (p.x() - cm[0][2] - y * cm[0][1]) / cm[0][0];
+	y = (p.y() - cmNew[1][2]) / cmNew[1][1];
+	x = (p.x() - cmNew[0][2] - y * cmNew[0][1]) / cmNew[0][0];
 
 	double r2 = x * x + y * y;
 	double r4 = r2 * r2;