Patch Detail
Show a patch.
GET /api/patches/26910/?format=api
{ "id": 26910, "url": "https://patchwork.libcamera.org/api/patches/26910/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26910/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/projects/1/?format=api", "name": "libcamera", "link_name": "libcamera", "list_id": "libcamera_core", "list_email": "libcamera-devel@lists.libcamera.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260617095857.667583-2-stefan.klug@ideasonboard.com>", "date": "2026-06-17T09:58:49", "name": "[1/2] libcamera: converter: converter_dw100: Refactor dewarp param handling", "commit_ref": null, "pull_url": null, "state": "superseded", "archived": false, "hash": "0bef76bc53fac0d724ce59aa976c6237f02a0d14", "submitter": { "id": 184, "url": "https://patchwork.libcamera.org/api/people/184/?format=api", "name": "Stefan Klug", "email": "stefan.klug@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/26910/mbox/", "series": [ { "id": 6001, "url": "https://patchwork.libcamera.org/api/series/6001/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=6001", "date": "2026-06-17T09:58:48", "name": "Add cmNew to dewarp paremeters", "version": 1, "mbox": "https://patchwork.libcamera.org/series/6001/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26910/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26910/checks/", "tags": {}, "headers": { "Return-Path": "<libcamera-devel-bounces@lists.libcamera.org>", "X-Original-To": "parsemail@patchwork.libcamera.org", "Delivered-To": "parsemail@patchwork.libcamera.org", "Received": [ "from lancelot.ideasonboard.com (lancelot.ideasonboard.com\n\t[92.243.16.209])\n\tby patchwork.libcamera.org (Postfix) with ESMTPS id 68754C328C\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 17 Jun 2026 09:59:07 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id 07A5862720;\n\tWed, 17 Jun 2026 11:59:07 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[213.167.242.64])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id E8F1162720\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 17 Jun 2026 11:59:05 +0200 (CEST)", "from ideasonboard.com (unknown\n\t[IPv6:2a00:6020:448c:6c00:bba7:89ad:1437:cbea])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id CFD86664;\n\tWed, 17 Jun 2026 11:58:31 +0200 (CEST)" ], "Authentication-Results": "lancelot.ideasonboard.com; dkim=pass (1024-bit key;\n\tunprotected) header.d=ideasonboard.com header.i=@ideasonboard.com\n\theader.b=\"WlSWG2J8\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1781690311;\n\tbh=pCPqMhxPQo+B5cLq5cRPNqCviSDU2cvzi9RCZt7llV4=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=WlSWG2J8fI8tsnz02SWIPGpcLgDx5quyeATYmCBeCJ2x2I35gC98R6yKdrEquHJt5\n\tI0dMnHVUyP0T8eaJZ5QDrM1zYojIHdgpLEPorsbx5Oz1Slyoz9hFP4oV/Cpwsx/SZJ\n\tSE7QSnJp5yCh9MNzFRo4xGGdrVQbwYWFAuskFJF4=", "From": "Stefan Klug <stefan.klug@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Stefan Klug <stefan.klug@ideasonboard.com>", "Subject": "[PATCH 1/2] libcamera: converter: converter_dw100: Refactor dewarp\n\tparam handling", "Date": "Wed, 17 Jun 2026 11:58:49 +0200", "Message-ID": "<20260617095857.667583-2-stefan.klug@ideasonboard.com>", "X-Mailer": "git-send-email 2.53.0", "In-Reply-To": "<20260617095857.667583-1-stefan.klug@ideasonboard.com>", "References": "<20260617095857.667583-1-stefan.klug@ideasonboard.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "libcamera-devel@lists.libcamera.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "<libcamera-devel.lists.libcamera.org>", "List-Unsubscribe": "<https://lists.libcamera.org/options/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=unsubscribe>", "List-Archive": "<https://lists.libcamera.org/pipermail/libcamera-devel/>", "List-Post": "<mailto:libcamera-devel@lists.libcamera.org>", "List-Help": "<mailto:libcamera-devel-request@lists.libcamera.org?subject=help>", "List-Subscribe": "<https://lists.libcamera.org/listinfo/libcamera-devel>,\n\t<mailto:libcamera-devel-request@lists.libcamera.org?subject=subscribe>", "Errors-To": "libcamera-devel-bounces@lists.libcamera.org", "Sender": "\"libcamera-devel\" <libcamera-devel-bounces@lists.libcamera.org>" }, "content": "There is already a ConverterDW100Module::DewarpParams class while in\nDw100VertexMap the parameters are handled separately for no good reason.\nCreate a Dw100VertexMap::DewarpParams struct for that purpose and adjust\nthe code accordingly. This has the added benefit that the size checking\nfor the coefficient list can now be done in the tuning file loading code\nwhere it belongs.\n\nSigned-off-by: Stefan Klug <stefan.klug@ideasonboard.com>\n---\n .../internal/converter/converter_dw100.h | 7 +-\n .../converter/converter_dw100_vertexmap.h | 35 ++++++--\n src/libcamera/converter/converter_dw100.cpp | 15 +++-\n .../converter/converter_dw100_vertexmap.cpp | 82 ++++++++-----------\n 4 files changed, 75 insertions(+), 64 deletions(-)", "diff": "diff --git a/include/libcamera/internal/converter/converter_dw100.h b/include/libcamera/internal/converter/converter_dw100.h\nindex 1db1aadcb06b..003f5eb954e9 100644\n--- a/include/libcamera/internal/converter/converter_dw100.h\n+++ b/include/libcamera/internal/converter/converter_dw100.h\n@@ -69,18 +69,13 @@ private:\n \tint applyControls(const Stream *stream, const V4L2Request *request);\n \tvoid reinitRequest(V4L2Request *request);\n \n-\tstruct DewarpParms {\n-\t\tMatrix<double, 3, 3> cm;\n-\t\tstd::vector<double> coeffs;\n-\t};\n-\n \tstruct VertexMapInfo {\n \t\tDw100VertexMap map;\n \t\tbool update;\n \t};\n \n \tstd::map<const Stream *, VertexMapInfo> vertexMaps_;\n-\tstd::optional<DewarpParms> dewarpParams_;\n+\tstd::optional<Dw100VertexMap::DewarpParams> dewarpParams_;\n \tunsigned int inputBufferCount_;\n \tV4L2M2MConverter converter_;\n \tRectangle sensorCrop_;\ndiff --git a/include/libcamera/internal/converter/converter_dw100_vertexmap.h b/include/libcamera/internal/converter/converter_dw100_vertexmap.h\nindex 3bf80ea66dc7..787498c7fdb5 100644\n--- a/include/libcamera/internal/converter/converter_dw100_vertexmap.h\n+++ b/include/libcamera/internal/converter/converter_dw100_vertexmap.h\n@@ -9,6 +9,7 @@\n \n #include <assert.h>\n #include <cmath>\n+#include <optional>\n #include <stdint.h>\n #include <vector>\n \n@@ -30,6 +31,33 @@ public:\n \t\tCrop = 1,\n \t};\n \n+\tstruct DewarpParams {\n+\t\tDewarpParams() : cm(Matrix<double, 3, 3>::identity()),\n+\t\t\t\t coefficients({})\n+\t\t{\n+\t\t}\n+\n+\t\tMatrix<double, 3, 3> cm;\n+\n+\t\tunion {\n+\t\t\tstruct {\n+\t\t\t\tdouble k1;\n+\t\t\t\tdouble k2;\n+\t\t\t\tdouble p1;\n+\t\t\t\tdouble p2;\n+\t\t\t\tdouble k3;\n+\t\t\t\tdouble k4;\n+\t\t\t\tdouble k5;\n+\t\t\t\tdouble k6;\n+\t\t\t\tdouble s1;\n+\t\t\t\tdouble s2;\n+\t\t\t\tdouble s3;\n+\t\t\t\tdouble s4;\n+\t\t\t} coefficient;\n+\t\t\tstd::array<double, 12> coefficients;\n+\t\t};\n+\t};\n+\n \tvoid applyLimits();\n \tvoid setInputSize(const Size &size)\n \t{\n@@ -60,8 +88,7 @@ public:\n \tvoid setMode(const ScaleMode mode) { mode_ = mode; }\n \tScaleMode mode() const { return mode_; }\n \n-\tint setDewarpParams(const Matrix<double, 3, 3> &cm, const Span<const double> &coeffs);\n-\tbool dewarpParamsValid() { return dewarpParamsValid_; }\n+\tvoid setDewarpParams(const DewarpParams ¶ms) { dewarpParams_ = params; }\n \n \tvoid setLensDewarpEnable(bool enable) { lensDewarpEnable_ = enable; }\n \tbool lensDewarpEnable() { return lensDewarpEnable_; }\n@@ -85,10 +112,8 @@ private:\n \tPoint effectiveOffset_;\n \tRectangle effectiveScalerCrop_;\n \n-\tMatrix<double, 3, 3> dewarpM_ = Matrix<double, 3, 3>::identity();\n-\tstd::array<double, 12> dewarpCoeffs_;\n+\tstd::optional<DewarpParams> dewarpParams_;\n \tbool lensDewarpEnable_ = true;\n-\tbool dewarpParamsValid_ = false;\n };\n \n } /* namespace libcamera */\ndiff --git a/src/libcamera/converter/converter_dw100.cpp b/src/libcamera/converter/converter_dw100.cpp\nindex 44f7ec035e62..34f81c6b9fab 100644\n--- a/src/libcamera/converter/converter_dw100.cpp\n+++ b/src/libcamera/converter/converter_dw100.cpp\n@@ -15,6 +15,7 @@\n #include <libcamera/stream.h>\n \n #include \"libcamera/internal/converter.h\"\n+#include \"libcamera/internal/converter/converter_dw100_vertexmap.h\"\n #include \"libcamera/internal/converter/converter_v4l2_m2m.h\"\n #include \"libcamera/internal/media_device.h\"\n #include \"libcamera/internal/v4l2_videodevice.h\"\n@@ -99,7 +100,7 @@ ConverterDW100Module::createModule(DeviceEnumerator *enumerator)\n */\n int ConverterDW100Module::init(const ValueNode ¶ms)\n {\n-\tDewarpParms dp;\n+\tDw100VertexMap::DewarpParams dp;\n \n \tauto &cm = params[\"cm\"];\n \tauto &coefficients = params[\"coefficients\"];\n@@ -131,7 +132,15 @@ int ConverterDW100Module::init(const ValueNode ¶ms)\n \t\tLOG(Converter, Error) << \"Dewarp parameters 'coefficients' value is not a list\";\n \t\treturn -EINVAL;\n \t}\n-\tdp.coeffs = std::move(*coeffs);\n+\n+\tif (coeffs->size() != 4 && coeffs->size() != 5 &&\n+\t coeffs->size() != 8 && coeffs->size() != 12) {\n+\t\tLOG(Converter, Error)\n+\t\t\t<< \"Dewarp 'coefficients' must have 4, 5, 8 or 12 values\";\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tstd::copy(coeffs->begin(), coeffs->end(), &dp.coefficients[0]);\n \n \tdewarpParams_ = dp;\n \n@@ -163,7 +172,7 @@ int ConverterDW100Module::configure(const StreamConfiguration &inputCfg,\n \t\tvertexMap.setSensorCrop(sensorCrop_);\n \n \t\tif (dewarpParams_)\n-\t\t\tvertexMap.setDewarpParams(dewarpParams_->cm, dewarpParams_->coeffs);\n+\t\t\tvertexMap.setDewarpParams(*dewarpParams_);\n \t\tinfo.update = true;\n \t}\n \ndiff --git a/src/libcamera/converter/converter_dw100_vertexmap.cpp b/src/libcamera/converter/converter_dw100_vertexmap.cpp\nindex 6e238736c435..31d992546857 100644\n--- a/src/libcamera/converter/converter_dw100_vertexmap.cpp\n+++ b/src/libcamera/converter/converter_dw100_vertexmap.cpp\n@@ -227,6 +227,20 @@ int dw100VerticesForLength(const int length)\n * into account within the possible limits.\n */\n \n+/**\n+ * \\struct Dw100VertexMap::DewarpParams\n+ * \\brief Structure combining all dewarp parameters\n+ *\n+ * \\var Dw100VertexMap::DewarpParams::cm\n+ * \\brief The camera matrix\n+ *\n+ * \\var Dw100VertexMap::DewarpParams::coefficient\n+ * \\brief Structure containing the lens dewarp coefficients\n+\n+ * See https://docs.opencv.org/4.12.0/d9/d0c/group__calib3d.html for further\n+ * details on the model.\n+ */\n+\n /**\n * \\brief Apply limits on scale and offset\n *\n@@ -549,7 +563,7 @@ std::vector<uint32_t> Dw100VertexMap::getVertexMap()\n \n \t\t\tp = transformPoint(outputToSensor, p);\n \n-\t\t\tif (dewarpParamsValid_ && lensDewarpEnable_)\n+\t\t\tif (lensDewarpEnable_)\n \t\t\t\tp = dewarpPoint(p);\n \n \t\t\tp = transformPoint(sensorToInput, p);\n@@ -566,41 +580,13 @@ std::vector<uint32_t> Dw100VertexMap::getVertexMap()\n \n /**\n * \\brief Set the dewarp parameters\n- * \\param cm The camera matrix\n- * \\param coeffs The dewarp coefficients\n+ * \\param params The dewarp parameters\n *\n * Sets the dewarp parameters according to the commonly used dewarp model. See\n * https://docs.opencv.org/4.12.0/d9/d0c/group__calib3d.html for further details\n * on the model. The parameter \\a coeffs must either hold 4,5,8 or 12 values.\n * They represent the parameters k1,k2,p1,p2[,k3[,k4,k5,k6[,s1,s2,s3,s4]]] in\n * the model.\n- *\n- * \\return A negative number on error, 0 otherwise\n- */\n-int Dw100VertexMap::setDewarpParams(const Matrix<double, 3, 3> &cm,\n-\t\t\t\t const Span<const double> &coeffs)\n-{\n-\tdewarpM_ = cm;\n-\tdewarpCoeffs_.fill(0.0);\n-\n-\tif (coeffs.size() != 4 && coeffs.size() != 5 &&\n-\t coeffs.size() != 8 && coeffs.size() != 12) {\n-\t\tLOG(Converter, Error)\n-\t\t\t<< \"Dewarp 'coefficients' must have 4, 5, 8 or 12 values\";\n-\t\tdewarpParamsValid_ = false;\n-\t\treturn -EINVAL;\n-\t}\n-\tstd::copy(coeffs.begin(), coeffs.end(), dewarpCoeffs_.begin());\n-\n-\tdewarpParamsValid_ = true;\n-\treturn 0;\n-}\n-\n-/**\n- * \\fn Dw100VertexMap::dewarpParamsValid()\n- * \\brief Returns if the dewarp parameters are valid\n- *\n- * \\return True if the dewarp parameters are valid, false otherwise\n */\n \n /**\n@@ -627,32 +613,28 @@ int Dw100VertexMap::setDewarpParams(const Matrix<double, 3, 3> &cm,\n */\n Vector2d Dw100VertexMap::dewarpPoint(const Vector2d &p)\n {\n+\tif (!dewarpParams_.has_value())\n+\t\treturn p;\n+\n \tdouble x, y;\n \tdouble xout, yout;\n-\tdouble k1 = dewarpCoeffs_[0];\n-\tdouble k2 = dewarpCoeffs_[1];\n-\tdouble p1 = dewarpCoeffs_[2];\n-\tdouble p2 = dewarpCoeffs_[3];\n-\tdouble k3 = dewarpCoeffs_[4];\n-\tdouble k4 = dewarpCoeffs_[5];\n-\tdouble k5 = dewarpCoeffs_[6];\n-\tdouble k6 = dewarpCoeffs_[7];\n-\tdouble s1 = dewarpCoeffs_[8];\n-\tdouble s2 = dewarpCoeffs_[9];\n-\tdouble s3 = dewarpCoeffs_[10];\n-\tdouble s4 = dewarpCoeffs_[11];\n+\tauto &cm = dewarpParams_->cm;\n+\tauto &c = dewarpParams_->coefficient;\n \n-\ty = (p.y() - dewarpM_[1][2]) / dewarpM_[1][1];\n-\tx = (p.x() - dewarpM_[0][2] - y * dewarpM_[0][1]) / dewarpM_[0][0];\n+\ty = (p.y() - cm[1][2]) / cm[1][1];\n+\tx = (p.x() - cm[0][2] - y * cm[0][1]) / cm[0][0];\n \n \tdouble r2 = x * x + y * y;\n-\tdouble d = (1 + k1 * r2 + k2 * r2 * r2 + k3 * r2 * r2 * r2) /\n-\t\t (1 + k4 * r2 + k5 * r2 * r2 + k6 * r2 * r2 * r2);\n-\txout = x * d + 2 * p1 * x * y + p2 * (r2 + 2 * x * x) + s1 * r2 + s2 * r2 * r2;\n-\tyout = y * d + 2 * p2 * x * y + p1 * (r2 + 2 * y * y) + s3 * r2 + s4 * r2 * r2;\n+\tdouble r4 = r2 * r2;\n+\tdouble r6 = r2 * r2 * r2;\n+\tdouble d = (1 + c.k1 * r2 + c.k2 * r4 + c.k3 * r6) /\n+\t\t (1 + c.k4 * r2 + c.k5 * r4 + c.k6 * r6);\n \n-\treturn { { xout * dewarpM_[0][0] + yout * dewarpM_[0][1] + dewarpM_[0][2],\n-\t\t yout * dewarpM_[1][1] + dewarpM_[1][2] } };\n+\txout = x * d + 2 * c.p1 * x * y + c.p2 * (r2 + 2 * x * x) + c.s1 * r2 + c.s2 * r4;\n+\tyout = y * d + 2 * c.p2 * x * y + c.p1 * (r2 + 2 * y * y) + c.s3 * r2 + c.s4 * r4;\n+\n+\treturn { { xout * cm[0][0] + yout * cm[0][1] + cm[0][2],\n+\t\t yout * cm[1][1] + cm[1][2] } };\n }\n \n } /* namespace libcamera */\n", "prefixes": [ "1/2" ] }