{"id":13410345,"url":"https://github.com/letmaik/lensfunpy","last_synced_at":"2026-01-26T01:05:46.377Z","repository":{"id":15224602,"uuid":"17953221","full_name":"letmaik/lensfunpy","owner":"letmaik","description":"📷 Lens distortion correction for Python, a wrapper for lensfun","archived":false,"fork":false,"pushed_at":"2026-01-24T17:17:07.000Z","size":7658,"stargazers_count":161,"open_issues_count":8,"forks_count":24,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-25T01:08:09.569Z","etag":null,"topics":["camera-image","distortion-correction","image-processing","lens","python"],"latest_commit_sha":null,"homepage":"https://pypi.python.org/pypi/lensfunpy","language":"Cython","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/letmaik.png","metadata":{"files":{"readme":"README.rst","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2014-03-20T18:14:59.000Z","updated_at":"2026-01-12T22:10:06.000Z","dependencies_parsed_at":"2024-02-09T23:23:57.540Z","dependency_job_id":"838b5058-5938-4080-9065-1f28290568be","html_url":"https://github.com/letmaik/lensfunpy","commit_stats":{"total_commits":319,"total_committers":9,"mean_commits":35.44444444444444,"dds":0.08150470219435735,"last_synced_commit":"dc71bd1b517ba8796db662eee4e3b48b47628577"},"previous_names":["neothemachine/lensfunpy"],"tags_count":33,"template":false,"template_full_name":null,"purl":"pkg:github/letmaik/lensfunpy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letmaik%2Flensfunpy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letmaik%2Flensfunpy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letmaik%2Flensfunpy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letmaik%2Flensfunpy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/letmaik","download_url":"https://codeload.github.com/letmaik/lensfunpy/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/letmaik%2Flensfunpy/sbom","scorecard":{"id":585879,"data":{"date":"2025-08-11","repo":{"name":"github.com/letmaik/lensfunpy","commit":"4caf26b0302c8ec938a266eb0dc2827baea539f9"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":4.4,"checks":[{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":1,"reason":"Found 3/29 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":10,"reason":"GitHub workflow tokens follow principle of least privilege","details":["Info: topLevel permissions set to 'read-all': .github/workflows/ci.yml:5","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":3,"reason":"dependency not pinned by hash detected -- score normalized to 3","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:160: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:183: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:205: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:216: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:219: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:224: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:239: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:259: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:266: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/ci.yml:269: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/ci.yml:287: update your workflow using https://app.stepsecurity.io/secureworkflow/letmaik/lensfunpy/ci.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/ci.yml:233","Info:   0 out of  10 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 third-party GitHubAction dependencies pinned","Info:   2 out of   3 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":3,"reason":"branch protection is not maximal on development and all release branches","details":["Info: 'allow deletion' disabled on branch 'master'","Info: 'force pushes' disabled on branch 'master'","Info: 'branch protection settings apply to administrators' is required to merge on branch 'master'","Warn: 'stale review dismissal' is disabled on branch 'master'","Warn: branch 'master' does not require approvers","Warn: codeowners review is not required on branch 'master'","Warn: 'last push approval' is disabled on branch 'master'","Warn: no status checks found to merge onto branch 'master'","Info: PRs are required in order to make changes on branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Packaging","score":10,"reason":"packaging workflow detected","details":["Info: Project packages its releases by way of GitHub Actions.: .github/workflows/ci.yml:243"],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Vulnerabilities","score":0,"reason":"11 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2018-34 / GHSA-2fc2-6r4j-p65h","Warn: Project is vulnerable to: PYSEC-2021-856 / GHSA-5545-2q6w-2gh6","Warn: Project is vulnerable to: PYSEC-2019-108 / GHSA-9fq2-x9r6-wfmf","Warn: Project is vulnerable to: PYSEC-2018-33 / GHSA-cw6w-4rcx-xphc","Warn: Project is vulnerable to: PYSEC-2021-857 / GHSA-f7c7-j99h-c22f","Warn: Project is vulnerable to: GHSA-fpfv-jqm9-f5jm","Warn: Project is vulnerable to: PYSEC-2017-1 / GHSA-frgw-fgh6-9g52","Warn: Project is vulnerable to: PYSEC-2019-156 / GHSA-xp76-357g-9wqq","Warn: Project is vulnerable to: PYSEC-2023-102","Warn: Project is vulnerable to: PYSEC-2023-114","Warn: Project is vulnerable to: PYSEC-2022-43017 / GHSA-qwmp-2cf2-g9g6"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-20T20:29:46.607Z","repository_id":15224602,"created_at":"2025-08-20T20:29:46.607Z","updated_at":"2025-08-20T20:29:46.607Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28763128,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-26T00:37:26.264Z","status":"ssl_error","status_checked_at":"2026-01-26T00:37:25.959Z","response_time":113,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["camera-image","distortion-correction","image-processing","lens","python"],"created_at":"2024-07-30T20:01:06.350Z","updated_at":"2026-01-26T01:05:46.371Z","avatar_url":"https://github.com/letmaik.png","language":"Cython","funding_links":[],"categories":["Cython","Python"],"sub_categories":[],"readme":"lensfunpy\n=========\n\nlensfunpy is an easy-to-use Python wrapper for the lensfun_ library.\n\n`API Documentation \u003chttps://letmaik.github.io/lensfunpy/api/\u003e`_\n\nSample code\n-----------\n\nHow to find cameras and lenses\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: python\n\n    import lensfunpy\n\n    cam_maker = 'NIKON CORPORATION'\n    cam_model = 'NIKON D3S'\n    lens_maker = 'Nikon'\n    lens_model = 'Nikkor 28mm f/2.8D AF'\n\n    db = lensfunpy.Database()\n    cam = db.find_cameras(cam_maker, cam_model)[0]\n    lens = db.find_lenses(cam, lens_maker, lens_model)[0]\n\n    print(cam)\n    # Camera(Maker: NIKON CORPORATION; Model: NIKON D3S; Variant: ; \n    #        Mount: Nikon F AF; Crop Factor: 1.0; Score: 0)\n\n    print(lens)\n    # Lens(Maker: Nikon; Model: Nikkor 28mm f/2.8D AF; Type: RECTILINEAR;\n    #      Focal: 28.0-28.0; Aperture: 2.79999995232-2.79999995232; \n    #      Crop factor: 1.0; Score: 110)\n\nHow to correct lens distortion\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: python\n\n    import cv2 # OpenCV library\n\n    focal_length = 28.0\n    aperture = 1.4\n    distance = 10\n    image_path = '/path/to/image.tiff'\n    undistorted_image_path = '/path/to/image_undist.tiff'\n\n    img = cv2.imread(image_path)\n    height, width = img.shape[0], img.shape[1]\n\n    mod = lensfunpy.Modifier(lens, cam.crop_factor, width, height)\n    mod.initialize(focal_length, aperture, distance, pixel_format=img.dtype)\n\n    undist_coords = mod.apply_geometry_distortion()\n    img_undistorted = cv2.remap(img, undist_coords, None, cv2.INTER_LINEAR)\n    cv2.imwrite(undistorted_image_path, img_undistorted)\n\nIt is also possible to apply the correction via `SciPy \u003chttp://www.scipy.org\u003e`_ instead of OpenCV.\nThe `lensfunpy.util \u003chttps://letmaik.github.io/lensfunpy/api/lensfunpy.util.html\u003e`_ module\ncontains convenience functions for RGB images which handle both OpenCV and SciPy.\n\nHow to correct lens vignetting\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nNote that the assumption is that the image is in a linear state, i.e., it is not\ngamma corrected.\n\n.. code-block:: python\n\n    import lensfunpy\n    import imageio\n\n    db = lensfun.Database()\n    cam = db.find_cameras('NIKON CORPORATION', 'NIKON D3S')[0]\n    lens = db.find_lenses(cam, 'Nikon', 'Nikkor AF 20mm f/2.8D')[0]\n\n    # The image is assumed to be in a linearly state.\n    img = imageio.imread('/path/to/image.tiff')\n\n    focal_length = 20\n    aperture = 4\n    distance = 10\n    width = img.shape[1]\n    height = img.shape[0]\n\n    mod = lensfunpy.Modifier(lens, cam.crop_factor, width, height)\n    mod.initialize(focal_length, aperture, distance, pixel_format=img.dtype)\n\n    did_apply = mod.apply_color_modification(img)\n    if did_apply:\n        imageio.imwrite('/path/to/image_corrected.tiff', img)\n    else:\n        print('vignetting not corrected, calibration data missing?')\n\n\nHow to correct lens vignetting and TCA\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\nNote that the assumption is that the image is in a linear state, i.e., it is not\ngamma corrected. Vignetting should always be corrected first before applying the\nTCA correction.\n\n.. code-block:: python\n\n    import imageio\n    import cv2\n    import lensfunpy\n\n    db = lensfunpy.Database()\n    cam = db.find_cameras('Canon', 'Canon EOS 5D Mark IV')[0]\n    lens = db.find_lenses(cam, 'Sigma', 'Sigma 8mm f/3.5 EX DG circular fisheye')[0]\n\n    # The image is assumed to be in a linearly state.\n    img = imageio.imread('/path/to/image.tiff')\n\n    focal_length = 8.0\n    aperture = 11\n    distance = 10\n    width = img.shape[1]\n    height = img.shape[0]\n\n    mod = lensfunpy.Modifier(lens, cam.crop_factor, width, height)\n    mod.initialize(focal_length, aperture, distance, pixel_format=img.dtype, flags=lensfunpy.ModifyFlags.VIGNETTING | lensfunpy.ModifyFlags.TCA)\n\n    # Vignette Correction\n    mod.apply_color_modification(img)\n\n    # TCA Correction\n    undist_coords = mod.apply_subpixel_distortion()\n    img[..., 0] = cv2.remap(img[..., 0], undist_coords[..., 0, :], None, cv2.INTER_LINEAR)\n    img[..., 1] = cv2.remap(img[..., 1], undist_coords[..., 1, :], None, cv2.INTER_LINEAR)\n    img[..., 2] = cv2.remap(img[..., 2], undist_coords[..., 2, :], None, cv2.INTER_LINEAR)\n\n    imageio.imwrite('/path/to/image_corrected.tiff', img)\n\nInstallation\n------------\n\nInstall lensfunpy by running:\n\n.. code-block:: sh\n\n    pip install lensfunpy\n\n64-bit binary wheels are provided for Linux, macOS, and Windows.\n\nInstallation from source on Linux/macOS\n---------------------------------------\n\nIf you have the need to use a specific lensfun version or you can't use the provided binary wheels\nthen follow the steps in this section to build lensfunpy from source.\n\nFirst, install the lensfun_ library on your system.\n\nOn Ubuntu, you can get (an outdated) version with:\n\n.. code-block:: sh\n\n    sudo apt-get install liblensfun-dev\n    \nOr install the latest developer version from the Git repository:\n\n.. code-block:: sh\n\n    git clone https://github.com/lensfun/lensfun\n    cd lensfun\n    cmake .\n    sudo make install\n    \nAfter that, install lensfunpy using:\n\n.. code-block:: sh\n\n    git clone https://github.com/letmaik/lensfunpy\n    cd lensfunpy\n    pip install numpy cython\n    pip install .\n    \nOn Linux, if you get the error \"ImportError: liblensfun.so.0: cannot open shared object file: No such file or directory\"\nwhen trying to use lensfunpy, then do the following:\n\n.. code-block:: sh\n\n    echo \"/usr/local/lib\" | sudo tee /etc/ld.so.conf.d/99local.conf\n    sudo ldconfig\n\nThe lensfun library is installed in ``/usr/local/lib`` when compiled from source, and apparently this folder is not searched\nfor libraries by default in some Linux distributions.\nNote that on some systems the installation path may be slightly different, such as ``/usr/local/lib/x86_64-linux-gnu``\nor ``/usr/local/lib64``.\n\nInstallation from source on Windows\n-----------------------------------\n\nThese instructions are experimental and support is not provided for them.\nTypically, there should be no need to build manually since wheels are hosted on PyPI.\n\nYou need to have Visual Studio installed to build lensfunpy.\n\nIn a PowerShell window:\n\n.. code-block:: sh\n\n    $env:USE_CONDA = '1'\n    $env:PYTHON_VERSION = '3.10'\n    $env:PYTHON_ARCH = 'x86_64'\n    $env:NUMPY_VERSION = '2.0.*'\n    git clone https://github.com/letmaik/lensfunpy\n    cd lensfunpy\n    .github/scripts/build-windows.ps1\n\nThe above will download all build dependencies (including a Python installation)\nand is fully configured through the four environment variables.\nSet ``USE_CONDA = '0'`` to build within an existing Python environment.\n\n\n.. _lensfun: https://lensfun.github.io/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fletmaik%2Flensfunpy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fletmaik%2Flensfunpy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fletmaik%2Flensfunpy/lists"}