Patch Detail
Show a patch.
GET /api/1.1/patches/26913/?format=api
{ "id": 26913, "url": "https://patchwork.libcamera.org/api/1.1/patches/26913/?format=api", "web_url": "https://patchwork.libcamera.org/patch/26913/", "project": { "id": 1, "url": "https://patchwork.libcamera.org/api/1.1/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": "<20260617144858.754729-2-stefan.klug@ideasonboard.com>", "date": "2026-06-17T14:48:34", "name": "[v2,1/2] libcamera: converter: converter_dw100: Refactor dewarp param handling", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "e2c08dcecbdddd3d93ac2013861292b385d8da1b", "submitter": { "id": 184, "url": "https://patchwork.libcamera.org/api/1.1/people/184/?format=api", "name": "Stefan Klug", "email": "stefan.klug@ideasonboard.com" }, "delegate": null, "mbox": "https://patchwork.libcamera.org/patch/26913/mbox/", "series": [ { "id": 6002, "url": "https://patchwork.libcamera.org/api/1.1/series/6002/?format=api", "web_url": "https://patchwork.libcamera.org/project/libcamera/list/?series=6002", "date": "2026-06-17T14:48:33", "name": "Add cmNew to dewarp paremeters", "version": 2, "mbox": "https://patchwork.libcamera.org/series/6002/mbox/" } ], "comments": "https://patchwork.libcamera.org/api/patches/26913/comments/", "check": "pending", "checks": "https://patchwork.libcamera.org/api/patches/26913/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 2BF13C3261\n\tfor <parsemail@patchwork.libcamera.org>;\n\tWed, 17 Jun 2026 14:49:10 +0000 (UTC)", "from lancelot.ideasonboard.com (localhost [IPv6:::1])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTP id DA9D36297E;\n\tWed, 17 Jun 2026 16:49:09 +0200 (CEST)", "from perceval.ideasonboard.com (perceval.ideasonboard.com\n\t[IPv6:2001:4b98:dc2:55:216:3eff:fef7:d647])\n\tby lancelot.ideasonboard.com (Postfix) with ESMTPS id 6186A60579\n\tfor <libcamera-devel@lists.libcamera.org>;\n\tWed, 17 Jun 2026 16:49:06 +0200 (CEST)", "from ideasonboard.com (unknown\n\t[IPv6:2a00:6020:448c:6c00:b0bc:b9b5:573f:6fae])\n\tby perceval.ideasonboard.com (Postfix) with ESMTPSA id B39512F8;\n\tWed, 17 Jun 2026 16:48: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=\"wkeSSSIG\"; dkim-atps=neutral", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple; d=ideasonboard.com;\n\ts=mail; t=1781707711;\n\tbh=LMqXvvpRhVV+R3+eJ+k+lXlhYUFy5U/EtPjH4eVgz2o=;\n\th=From:To:Cc:Subject:Date:In-Reply-To:References:From;\n\tb=wkeSSSIGVjlrNIKXeCHy5Y2txOJP88nCqLpkTtcJUn3G9fUSxoixWnuBk3mYY6D7h\n\tLKWULHr4XJ8OatMAqet+/3f4EaW3iDA0+QLYFxWs5qZ8Ddufpy/m8A0n5+ECG8Jdqf\n\tApv/oiinVmYtDwmt+MVDUIXqNw7ecwwlH90yd014=", "From": "Stefan Klug <stefan.klug@ideasonboard.com>", "To": "libcamera-devel@lists.libcamera.org", "Cc": "Stefan Klug <stefan.klug@ideasonboard.com>", "Subject": "[PATCH v2 1/2] libcamera: converter: converter_dw100: Refactor\n\tdewarp param handling", "Date": "Wed, 17 Jun 2026 16:48:34 +0200", "Message-ID": "<20260617144858.754729-2-stefan.klug@ideasonboard.com>", "X-Mailer": "git-send-email 2.53.0", "In-Reply-To": "<20260617144858.754729-1-stefan.klug@ideasonboard.com>", "References": "<20260617144858.754729-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---\n\nChanges in v2:\n- dropped union in DewarpParams struct\n---\n .../internal/converter/converter_dw100.h | 7 +-\n .../converter/converter_dw100_vertexmap.h | 34 ++++-\n src/libcamera/converter/converter_dw100.cpp | 13 +-\n .../converter/converter_dw100_vertexmap.cpp | 127 +++++++++++-------\n 4 files changed, 117 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..6b6f3bae9f50 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,32 @@ 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\tint setCoefficients(Span<const double> coeffs);\n+\n+\t\tMatrix<double, 3, 3> cm;\n+\n+\t\tstruct {\n+\t\t\tdouble k1;\n+\t\t\tdouble k2;\n+\t\t\tdouble p1;\n+\t\t\tdouble p2;\n+\t\t\tdouble k3;\n+\t\t\tdouble k4;\n+\t\t\tdouble k5;\n+\t\t\tdouble k6;\n+\t\t\tdouble s1;\n+\t\t\tdouble s2;\n+\t\t\tdouble s3;\n+\t\t\tdouble s4;\n+\t\t} coefficients;\n+\t};\n+\n \tvoid applyLimits();\n \tvoid setInputSize(const Size &size)\n \t{\n@@ -60,8 +87,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 +111,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..d05823fa4d4c 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,13 @@ 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+\tint ret = dp.setCoefficients(*coeffs);\n+\tif (ret) {\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 \tdewarpParams_ = dp;\n \n@@ -163,7 +170,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..6986f137cbc8 100644\n--- a/src/libcamera/converter/converter_dw100_vertexmap.cpp\n+++ b/src/libcamera/converter/converter_dw100_vertexmap.cpp\n@@ -227,6 +227,65 @@ 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::coefficients\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 Fill the coefficients with a list of coefficients\n+ * \\param coeffs\n+ *\n+ * Fill the coefficients with the ones from the provided span. These data is\n+ * used to fill the coefficients in the order k1, k2, p1, p2, k3, k4, k5, k6,\n+ * s1, s2, s3, s4. The span must either contain 4, 5, 8 or 12 entries, the\n+ * remaining coefficients are set to 0.\n+ *\n+ * \\return 0 on success or -EINVAL if \\a coeffs has the wrong size\n+ */\n+int Dw100VertexMap::DewarpParams::setCoefficients(Span<const double> coeffs)\n+{\n+\tsize_t s = coeffs.size();\n+\tif (!(s == 4 || s == 5 || s == 8 || s == 12))\n+\t\treturn -EINVAL;\n+\n+\tcoefficients = {};\n+\n+\tif (s >= 4) {\n+\t\tcoefficients.k1 = coeffs[0];\n+\t\tcoefficients.k2 = coeffs[1];\n+\t\tcoefficients.p1 = coeffs[2];\n+\t\tcoefficients.p2 = coeffs[3];\n+\t}\n+\n+\tif (s >= 5)\n+\t\tcoefficients.k3 = coeffs[4];\n+\n+\tif (s >= 8) {\n+\t\tcoefficients.k4 = coeffs[5];\n+\t\tcoefficients.k5 = coeffs[6];\n+\t\tcoefficients.k6 = coeffs[7];\n+\t}\n+\n+\tif (s == 12) {\n+\t\tcoefficients.s1 = coeffs[8];\n+\t\tcoefficients.s2 = coeffs[9];\n+\t\tcoefficients.s3 = coeffs[10];\n+\t\tcoefficients.s4 = coeffs[11];\n+\t}\n+\n+\treturn 0;\n+}\n+\n /**\n * \\brief Apply limits on scale and offset\n *\n@@ -549,7 +608,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 +625,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 +658,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_->coefficients;\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": [ "v2", "1/2" ] }