{"id":22051605,"url":"https://github.com/parlaynu/jetson-camcal","last_synced_at":"2026-04-29T15:02:53.855Z","repository":{"id":155555127,"uuid":"584983338","full_name":"parlaynu/jetson-camcal","owner":"parlaynu","description":"Tools using OpenCV to calibrate a Jetson Nano camera to correct for geometric distortions.","archived":false,"fork":false,"pushed_at":"2024-01-12T05:42:48.000Z","size":11248,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-06-15T02:06:39.440Z","etag":null,"topics":["deepstream","gstreamer","jetson-nano","nvidia","nvidia-jetson-nano","opencv","opencv-python"],"latest_commit_sha":null,"homepage":"","language":"Python","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/parlaynu.png","metadata":{"files":{"readme":"Readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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}},"created_at":"2023-01-04T02:37:56.000Z","updated_at":"2024-05-31T10:20:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"83fe54ad-eab3-4410-978f-e2b4b49a3e8e","html_url":"https://github.com/parlaynu/jetson-camcal","commit_stats":null,"previous_names":["parlaynu/jetson-camcal"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/parlaynu/jetson-camcal","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parlaynu%2Fjetson-camcal","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parlaynu%2Fjetson-camcal/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parlaynu%2Fjetson-camcal/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parlaynu%2Fjetson-camcal/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/parlaynu","download_url":"https://codeload.github.com/parlaynu/jetson-camcal/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/parlaynu%2Fjetson-camcal/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32430803,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-29T13:34:34.882Z","status":"ssl_error","status_checked_at":"2026-04-29T13:34:29.830Z","response_time":110,"last_error":"SSL_read: 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":["deepstream","gstreamer","jetson-nano","nvidia","nvidia-jetson-nano","opencv","opencv-python"],"created_at":"2024-11-30T15:09:55.806Z","updated_at":"2026-04-29T15:02:53.827Z","avatar_url":"https://github.com/parlaynu.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Simple Camera Calibration\n\nThis is a set of tools to calibrate a camera to correct for lens and camera geometric distortions. \nAn example of images captured without and with the calibration applied is below:\n\n\u003ctable\u003e\n    \u003ctr\u003e\n        \u003ctd\u003e\u003cimg src=\"docs/img-nocal.png\"\u003e\u003c/td\u003e\n        \u003ctd\u003e\u003cimg src=\"docs/img-cal.png\"\u003e\u003c/td\u003e\n    \u003c/tr\u003e\n\u003c/table\u003e\n\nIt has been built to run on a Jetson Nano using the CSI camera interface.\n\nThere are four tools in the toolkit:\n\n* viewer.py - simple viewer that can optionally load a calibration matrix\n* capture.py - tool to capture a sequence of calibration images\n* calibrate.py - process the captured images \n* recorder.py - records images to disk, optionally using a calibration matrix\n\nThe viewer and capture applications are built using \n[Gstreamer](https://gstreamer.freedesktop.org/documentation/tutorials/index.html?gi-language=python) \nwith Nvidia's [deepstream](https://docs.nvidia.com/metropolis/deepstream/dev-guide/text/DS_Overview.html) \nextensions. The calibration tool is built using [OpenCV](https://opencv.org/) and based on this \n[tutorial](https://docs.opencv.org/4.6.0/dc/dbb/tutorial_py_calibration.html).\n\nThe basic set of steps involve in the calibration are:\n\n* create a checkerboard calibration image\n* capture a range of images of the checkerboard\n* create calibration matrix from the images\n* run the viewer with the generated calibration configuration\n\nFull documentation for the tools can be found by running them with the `--help` flag, or in this\n[document](docs/tools.md)\n\n## Example\n\nThis section provides an example of walking through the process and using the generated calibration\nfiles. \n\n### Setup\n\nThe examples here are for a system without a GUI running, so the first step is to turn it off:\n\n    sudo systemctl isolate multi-user.target\n    sudo systemctl set-default multi-user.target\n\nThe rest of the examples assume that you are accessing the jetson nano using ssh, and the HDMI\noutput is connected to a display.\n\nInstall the extra packages needed on the jetson to run the applications. This needs to be installed\nin the user's path or the system - it can't be in a virtualenv as need to use the libraries that\nare part of the jetpack, not what's available through pip.\n\n    pip3 install -r requirements.txt\n\nMake sure the gstreamer packages are installed on your system. This is what I have installed:\n\n    sudo apt install gstreamer1.0-tools nvidia-l4t-gstreamer gstreamer1.0-libav gstreamer1.0-alsa\n    sudo apt install gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly\n\nThere are possibly other things that need to be installed. If I ever start from scratch again, I'll take\nbetter notes and update here.\n\n### Viewing\n\nTo view the images and get a feeling for the distortion, run the `viewer.py` app:\n\n    $ ./viewer.py\n\nLine up some straight edges next to the edge of the image to get a good feeling for the amount\nof distortion.\n\nStop the viewer with `ctrl-c`.\n\nThe view takes a '--mode' flag as an option to select the different sensor modes of the camera. On my jetson-nano\nthe modes are:\n\n| mode | resolution  | fps     | \n| ---- | ----------- | ------- |\n| 0    | 3264 x 2464 |  21     |\n| 1    | 3264 x 1848 |  28     |\n| 2    | 1920 x 1080 |  29.999 |\n| 3    | 1640 x 1232 |  29.999 |\n| 4    | 1280 x 720  |  59.999 |\n| 5    | 1280 x 720  | 120     |\n\n\n### Capturing Images\n\nYou'll need a checkerboard ready before running this - see the reference section.\n\nRun the capture application:\n\n    $ ./capture.py -n 20 -t 5 --hflip local\n\nThis will capture 20 images, with a delay of 5 seconds between image (so you have time to get your \ncheckboard into the next position). It also flips the image for display so it looks like you're in\nfront of a mirror - I find this easier to position the checkerboard while watching the display.\n\nThe captured images along with the capture config are saved to a timestamp directory under `local`\nlike this:\n\n    $ ls -l local/\n    total 8\n    drwxrwxr-x 2 paul paul 4096 May 18 01:19 20230518-011818\n\n    $ ls -l local/20230518-011818\n    total 45308\n    -rw-rw-r-- 1 paul paul     110 May 18 01:18 capture.txt\n    -rw-rw-r-- 1 paul paul 5122545 May 18 01:18 image0000.png\n    -rw-rw-r-- 1 paul paul 5120516 May 18 01:18 image0001.png\n    ....\n    -rw-rw-r-- 1 paul paul 5118010 May 18 01:20 image0018.png\n    -rw-rw-r-- 1 paul paul 5303458 May 18 01:20 image0019.png\n\nThe contents of the capture config file are like this:\n\n    [camera]\n    camera-mode=2\n    camera-width=1920\n    camera-height=1080\n    [capture]\n    capture-width=1920\n    capture-height=1080\n\n\n### Calibrating\n\nBefore calibrating, it's worth reviewing the images that you've captured and removing any bad captures.\nA bad image could be blurred from motion, or in the checkerboard partially off screen. You'll get better \nresults if you remove any bad images.\n\nOnce you have the images, you can run the calibration.\n\n    $ ./calibrate.py -x 8 -y 6 -g 2 local/20230518-011818/\n    processing local/20230518-011818/image0000.jpg: success\n    processing local/20230518-011818/image0001.jpg: success\n    ...\n    processing local/20230518-011818/image0018.jpg: success\n    processing local/20230518-011818/image0019.jpg: success\n    calibrating...\n\nThis creates two files in the image directory with the calibration information:\n\n    -rw-rw-r-- 1 paul paul    478 May 18 01:22 cal-config.txt\n    -rw-rw-r-- 1 paul paul    533 May 18 01:22 cal-raw.xml\n\nThe file `cal-config.txt` is in the format needed for the viewer and looks like this:\n\n    [property]\n    camera-mode=2\n    output-width=1920\n    output-height=1080\n    num-batch-buffers=1\n    [surface0]\n    # 3=PerspectivePerspective\n    projection-type=3\n    width=1920\n    height=1080\n    focal-length=1588.8534809922935\n    src-x0=1048.3737261822962\n    src-y0=506.03150358949677\n    distortion=-0.3561592743907544;0.19877723536005001;-0.07516529290785304;-0.002437501887250334;-0.002127113862300699\n\nThis is fed to the nvidia deepstream nvdewarper node. The documentation for that node is \n[here](https://docs.nvidia.com/metropolis/deepstream/dev-guide/text/DS_plugin_gst-nvdewarper.html)\nwith an explanation of what all the parameters mean.\n\n### Viewing With Correction\n\nNow that you've got the calibration file, you can run the viewer with the correction:\n\n    $ ./viewer.py local/20230518-011818/cal-config.txt\n\nYou should be seeing straight edges in the image.\n\n## Reference\n\nThere are a range of calibration checkerboard images available on the internet - here are a couple\nof sources:\n\n* https://github.com/opencv/opencv/blob/master/doc/pattern.png\n* https://markhedleyjones.com/projects/calibration-checkerboard-collection\n\nYou can also use an OpenCV tool to generate calibration patterns as described in this tutorial:\n\n* https://docs.opencv.org/4.x/da/d0d/tutorial_camera_calibration_pattern.html\n\nHere are some videos on what it's all about and how to perform a calibration:\n\n* https://www.youtube.com/watch?v=26nV4oDLiqc\n* https://www.youtube.com/watch?v=-9He7Nu3u8s\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparlaynu%2Fjetson-camcal","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fparlaynu%2Fjetson-camcal","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fparlaynu%2Fjetson-camcal/lists"}