{"id":18027610,"url":"https://github.com/cheind/hue-depth-encoding","last_synced_at":"2026-02-01T02:33:57.483Z","repository":{"id":258548536,"uuid":"873968632","full_name":"cheind/hue-depth-encoding","owner":"cheind","description":"Depth map compression by colorization in vectorized form","archived":false,"fork":false,"pushed_at":"2024-10-30T19:41:50.000Z","size":2944,"stargazers_count":13,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-09-10T01:33:51.370Z","etag":null,"topics":[],"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/cheind.png","metadata":{"files":{"readme":"README.md","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}},"created_at":"2024-10-17T03:03:33.000Z","updated_at":"2025-08-15T22:58:37.000Z","dependencies_parsed_at":"2024-10-20T13:43:01.965Z","dependency_job_id":null,"html_url":"https://github.com/cheind/hue-depth-encoding","commit_stats":null,"previous_names":["cheind/hue-depth-encoding"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/cheind/hue-depth-encoding","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheind%2Fhue-depth-encoding","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheind%2Fhue-depth-encoding/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheind%2Fhue-depth-encoding/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheind%2Fhue-depth-encoding/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cheind","download_url":"https://codeload.github.com/cheind/hue-depth-encoding/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cheind%2Fhue-depth-encoding/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28965422,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T02:14:24.993Z","status":"ssl_error","status_checked_at":"2026-02-01T02:13:55.706Z","response_time":56,"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":[],"created_at":"2024-10-30T08:11:59.421Z","updated_at":"2026-02-01T02:33:57.469Z","avatar_url":"https://github.com/cheind.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![DOI](https://zenodo.org/badge/873968632.svg)](https://doi.org/10.5281/zenodo.14014715)\n\n# hue-depth-encoding\nThis project provides efficient vectorized Python code to perform depth `\u003c-\u003e` color encoding based on\n\n\u003e Sonoda, Tetsuri, and Anders Grunnet-Jepsen.\n\"Depth image compression by colorization for Intel RealSense depth cameras.\" Intel, Rev 1.0 (2021).\n\nwith the following significant changes:\n 1. We stop the hue range at 300° (default) in order to avoid having close and far ranges assigned redish color.\n 1. We detect de-valued and de-saturized colors in the decoding and assign it a pre-defined failure depth.\n\nThe encoding is designed to transform 16bit single channel images to RGB color images that can be processed by standard (lossy) image codec with *minimized* compression artefacts. This leads to a compression factor of up to 80x while maintaining acceptable depth accuracy for many RGBD systems.\n\n## Method\n\nThe underlying method is described in \n\n\u003e Sonoda, Tetsuri, and Anders Grunnet-Jepsen.\n\"Depth image compression by colorization for Intel RealSense depth cameras.\" Intel, Rev 1.0 (2021).\n\nHowever, the formulae presented appear to be inaccurate and specific important details seem to be left out. Here we describe the base encoding plus our adaptations.\n\nThe base method relies on encoding depth as fully saturated/valued colors and assigns increasing depth values increasing hues. For bitdepth $b$ this allows for\n\n```math\nn = \\lfloor \\textrm{Hue}_{\\textrm{max}}/ 60\\rfloor (2^b - 1) + 1\n```\nunique colors. In the original method $`\\textrm{Hue}_{\\textrm{max}}=360°`$, whereas in this implementation $`\\textrm{Hue}_{\\textrm{max}}=300°`$ to avoid ambiguitis between close and far depth values that would otherwise get assigned a reddish color.\n\nLimiting $`\\textrm{Hue}_{\\textrm{max}}`$ limits the number of available bits to $`\\log_2 n`$ (~10.3bit).\n\n\n### Depth transformations\nThe encoding allows for linear and disparity depth normalization. In linear mode, equal depth ratios are preserved in the encoding range, whereas in disparity mode more emphasis is put on closer depth values than on larger ones, leading to more accurare depth resolution closeup.\n\n![](etc/compare_encoding.svg)\n\n\n## Implementation\n\nThis implementation is vectorized using numpy and can handle any image shapes `(*,H,W) \u003c-\u003e (*,H,W,3)`. For improved performance, we precompute encoder and decoder lookup tables to reduce encoding/decoding to a simple lookup. The lookup tables require ~32MB of memory. Use `use_lut=False` switch to rely on the pure vectorized implementation. See benchmarks below for effects.\n\n## Installation\nWith Python \u003e= 3.11 execute\n\n```shell\ngit clone https://github.com/cheind/hue-depth-encoding.git\npip install -e .\n\n# or development install adds more packages to run tests/analysis\npip install -e '.[dev]'\n# or with gpu codec support in dev mode\npip install -e '.[dev]' --no-binary=av \n```\n\n## Usage\n\nBasic usage\n\n```python\n# Import\nimport huecodec as hc\n\n# Random float depths\nd = rng.random((5,240,320), dtype=np.float32)*0.9 + 0.1\n\n# Encode\nrgb = hc.depth2rgb(d, zrange=(0.1,1.0), inv_depth=False)\n# (5,240,320,3), uint8\n\n# Decode\ndepth = hc.rgb2depth(rgb, zrange=(0.1,1.0), inv_depth=False)\n# (5,240,320), float32\n```\n\n## Evaluation\n\n### Encoding/Decoding Roundtrips\n\nThe script `python analysis.py` compares encoding and decoding characteristics for different standard video codecs using hue depth encoding. The reported figures have the following meaning:\n\n - **rmse** [m] root mean square error per depth pixel between groundtruth and transcoded depthmaps\n - **\u003cx** [%] percent of absolute errors less than x\n - **failed** [%] percent of reconstructions failed during decoding. This appear when using lossy video codecs and rgb values are de-saturated or de-valued too much by the codec.\n - **tenc** [milli-sec/frame] encoding time per frame\n - **tdec** [milli-sec/frame] decoding time per frame\n - **nbytes** [kb/frame] kilo-bytes per encoded frame on disk.\n\n\nAll tests are carried out on a 12th Gen Intel® Core™ i9-12900K × 24 with NVIDIA GeForce RTX™ 3090 Ti.\n\n```shell\n# run analysis only for specific variants\npython analysis.py variant=[hue-only,h264-lossless-gpu]\n```\n\n#### Synthetic Depthmaps\n\nEach test encodes/decodes a sequence `(100,512,512)` of np.float32 depthmaps in range `[0..2]` containing a sinusoidal pattern plus random hard depth edges. The pattern moves horizontally over time.\n\n![](etc/synthetic.png)\n\nThe reported values are\n| variant           | zrange [m]   |   rmse [m] |   \u003c1mm [%] |   \u003c5mm [%] |   \u003c1cm [%] |   failed [%] |   tenc [ms/img] |   tdec [ms/img] |   size [kb/img] |\n|:------------------|:-------------|-----------:|-----------:|-----------:|-----------:|-------------:|----------------:|----------------:|----------------:|\n| hue-only          | (0.0, 2.0)   |    0.00040 |      1.000 |      1.000 |      1.000 |        0.000 |            1.98 |            1.32 |          768.00 |\n| hue-only          | (0.0, 4.0)   |    0.00080 |      0.718 |      1.000 |      1.000 |        0.000 |            1.85 |            1.34 |          768.00 |\n| h264-lossless-cpu | (0.0, 2.0)   |    0.00040 |      0.999 |      1.000 |      1.000 |        0.000 |            5.55 |            2.99 |           30.99 |\n| h264-lossless-cpu | (0.0, 4.0)   |    0.00080 |      0.718 |      1.000 |      1.000 |        0.000 |            5.60 |            2.75 |           25.46 |\n| h264-default-cpu  | (0.0, 2.0)   |    0.03587 |      0.287 |      0.508 |      0.707 |        0.004 |            4.93 |            1.89 |           10.26 |\n| h264-default-cpu  | (0.0, 4.0)   |    0.03755 |      0.279 |      0.496 |      0.694 |        0.001 |            4.65 |            1.78 |            9.44 |\n| h264-lossless-gpu | (0.0, 2.0)   |    0.00040 |      1.000 |      1.000 |      1.000 |        0.000 |            2.60 |            2.07 |           48.19 |\n| h264-lossless-gpu | (0.0, 4.0)   |    0.00080 |      0.718 |      1.000 |      1.000 |        0.000 |            2.59 |            1.95 |           25.63 |\n| h264-tuned-gpu    | (0.0, 2.0)   |    0.00078 |      0.838 |      0.997 |      0.997 |        0.003 |            2.60 |            2.09 |           23.38 |\n| h264-tuned-gpu    | (0.0, 4.0)   |    0.00138 |      0.616 |      0.996 |      0.999 |        0.001 |            2.84 |            1.98 |           13.34 |\n| h265-lossless-gpu | (0.0, 2.0)   |    0.00040 |      1.000 |      1.000 |      1.000 |        0.000 |            2.60 |            2.82 |           30.15 |\n| h265-lossless-gpu | (0.0, 4.0)   |    0.00080 |      0.718 |      1.000 |      1.000 |        0.000 |            2.59 |            2.73 |           25.59 |\n| h264-default-gpu  | (0.0, 2.0)   |    0.03591 |      0.285 |      0.506 |      0.706 |        0.005 |            2.59 |            2.63 |           16.70 |\n| h264-default-gpu  | (0.0, 4.0)   |    0.03762 |      0.276 |      0.491 |      0.690 |        0.001 |            2.58 |            2.27 |           12.50 |\n\n#### Real Depthmaps\n\nEach tests encodes a sequence of `(30,600,800)` of np.float32 depthmaps taken with a RealSense 415 in range `[0..2]` containing a sitting person moving.\n\n![](etc/real.png)\n\nThe reported values are\n\n| variant           | zrange [m]   |   rmse [m] |   \u003c1mm [%] |   \u003c5mm [%] |   \u003c1cm [%] |   failed [%] |   tenc [ms/img] |   tdec [ms/img] |   size [kb/img] |\n|:------------------|:-------------|-----------:|-----------:|-----------:|-----------:|-------------:|----------------:|----------------:|----------------:|\n| hue-only          | (0.0, 2.0)   |    0.00028 |      1.000 |      1.000 |      1.000 |        0.000 |            2.03 |            1.27 |          900.00 |\n| hue-only          | (0.0, 4.0)   |    0.00057 |      0.857 |      1.000 |      1.000 |        0.000 |            2.03 |            1.27 |          900.00 |\n| h264-lossless-cpu | (0.0, 2.0)   |    0.00028 |      1.000 |      1.000 |      1.000 |        0.000 |           10.13 |            4.08 |           83.76 |\n| h264-lossless-cpu | (0.0, 4.0)   |    0.00057 |      0.857 |      1.000 |      1.000 |        0.000 |            9.44 |            3.57 |           62.30 |\n| h264-default-cpu  | (0.0, 2.0)   |    0.04110 |      0.738 |      0.949 |      0.959 |        0.026 |            9.44 |            2.67 |           42.16 |\n| h264-default-cpu  | (0.0, 4.0)   |    0.09251 |      0.682 |      0.916 |      0.955 |        0.005 |            7.68 |            2.51 |           36.18 |\n| h264-lossless-gpu | (0.0, 2.0)   |    0.00028 |      1.000 |      1.000 |      1.000 |        0.000 |            2.86 |            2.74 |          102.48 |\n| h264-lossless-gpu | (0.0, 4.0)   |    0.00057 |      0.857 |      1.000 |      1.000 |        0.000 |            2.84 |            2.57 |           73.91 |\n| h264-tuned-gpu    | (0.0, 2.0)   |    0.00104 |      0.825 |      0.974 |      0.976 |        0.024 |            2.84 |            2.45 |           62.26 |\n| h264-tuned-gpu    | (0.0, 4.0)   |    0.00276 |      0.724 |      0.963 |      0.985 |        0.012 |            2.86 |            2.33 |           45.74 |\n| h265-lossless-gpu | (0.0, 2.0)   |    0.00028 |      1.000 |      1.000 |      1.000 |        0.000 |            2.85 |            5.30 |           89.73 |\n| h265-lossless-gpu | (0.0, 4.0)   |    0.00057 |      0.857 |      1.000 |      1.000 |        0.000 |            2.85 |            4.81 |           66.92 |\n| h264-default-gpu  | (0.0, 2.0)   |    0.04110 |      0.726 |      0.944 |      0.958 |        0.027 |            2.82 |            3.79 |           33.68 |\n| h264-default-gpu  | (0.0, 4.0)   |    0.09264 |      0.676 |      0.901 |      0.952 |        0.005 |            2.83 |            3.76 |           32.44 |\n\n```\npython analysis.py data=path/to/npy\n```\n\n### Hue Runtime Benchmark\n\nHere are benchmark results for encoding/decoding float32 depthmaps of various sizes with differnt characteristics. Note, this is pure depth -\u003e color -\u003e depth transcoding without any video codecs involved.\n\n```\n------------- benchmark: 8 tests ------------\nName (time in ms)              Mean          \n---------------------------------------------\nenc_perf[LUT-(640x480)]        2.1851 (1.0)    \ndec_perf[LUT-(640x480)]        2.2124 (1.01)   \nenc_perf[LUT-(1920x1080)]     17.9139 (8.20) \ndec_perf[LUT-(1920x1080)]     16.4741 (7.54)   \nenc_perf[noLUT-(640x480)]     22.3938 (10.25)  \ndec_perf[noLUT-(640x480)]      6.9320 (3.17)   \ndec_perf[noLUT-(1920x1080)]   74.6038 (34.14)  \nenc_perf[noLUT-(1920x1080)]  158.0871 (72.35)  \n---------------------------------------------\n```\n\n```shell\n# run tests and benchmarks  \npytest\n```\n\n### Note on Video Codecs\n\nWhen tuning the prameters for a video codec you need to take into account lossy compression that happens on  different levels of encoding:\n - **spatial/temporal** quantization based how images change over time. Usually controlled by the codec `preset/profile` (lossless, low-latency,...) and quality parameters such as `crf`, `qp`.\n - **color space** quantization due to converting RGB to target pixel format. Different codecs support different pixel color formats of which most perform a lossy compression from rgb to target space. \n\nPrint encoder supported options and pixel formats\n```shell\n# print encoder options\nffmpeg -h encoder=h264_nvenc\n```\n\nSee packing and compression of color formats\nhttps://github.com/FFmpeg/FFmpeg/blob/master/libavutil/pixfmt.h\n\n\n### Takeaways\nHere are some take aways to consider\n - adjust zrange as tightly as possible to your use-case. This increases filesize but reduces reconstruction loss.\n - prefer loss-less codecs if affordable\n - when using lossy codecs ensure that your application does not rely on depth-edges.\n\nThe following plot shows a lossy h264 encoding on real data. Most of the errors are sub-mm, only few \u003e 1cm. \n\n![](etc/h264-tuned-gpu.2.hist.png)\n\nTurns out these errors are located on depth edges where the lossy codec starts interpolating values.\n \n\n## Notes\n\nThe original paper referenced is potentially inaccurate in its equations. This has been noted in varios posts [#10415](https://github.com/IntelRealSense/librealsense/issues/10145),[#11187](https://github.com/IntelRealSense/librealsense/issues/11187),[#10302](https://github.com/IntelRealSense/librealsense/issues/10302).\n\nThis implementation is based on the original paper and code from\nhttps://github.com/jdtremaine/hue-codec/.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcheind%2Fhue-depth-encoding","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcheind%2Fhue-depth-encoding","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcheind%2Fhue-depth-encoding/lists"}