Skip to content

Conversation

@tonyreina
Copy link

@tonyreina tonyreina commented Oct 14, 2025

Category:

New feature (non-breaking change which adds functionality)

Description:

This PR adds Contrast-Limited Adaptive Histogram Equalization (CLAHE) to the DALI image operators.

CLAHE performs local histogram equalization with clipping and bilinear blending of lookup tables (LUTs) between neighboring tiles. This technique enhances local contrast while preventing over-amplification of noise. The implementation maintains exact algorithmic compatibility with OpenCV's cv::createCLAHE() while providing significant GPU performance optimizations.

Additional information:

Affected modules and functionalities:

  • Added clahe_op.cc and clahe_op.cu for GPU implementation with CUDA kernels
  • Added clahe_cpu.cc for CPU implementation using OpenCV
  • Added comprehensive operator schema with detailed documentation
  • Added Jupyter Notebook example

Key points relevant for the review:

  • Algorithmic Compatibility: Follows the algorithm used by OpenCV
  • Performance Optimizations: Includes automatic optimizations:
    • Kernel fusion (RGB→LAB + histogram computation)
    • Warp-privatized histograms for larger tiles (≥1024 pixels)
    • Vectorized memory access for larger images (≥8192 pixels)
    • Adaptive algorithm selection based on image size and tile configuration
  • Feature Support:
    • Supports grayscale (1-channel) and RGB (3-channel) uint8 images in HWC layout
    • Two RGB processing modes: luminance-only (preserves color relationships) and per-channel
    • Configurable tile grid, clip limit, and histogram bins

Tests:

  • New tests added
    • Python tests: test_clahe.py with multiple parameter combinations, device testing (CPU/GPU), and API validation
    • GTests: clahe_test.cc with CPU vs GPU equivalence testing, different tile sizes, clip limits, and error handling
    • Example: clahe_example.py demonstrating usage patterns and parameter effects
    • Benchmark: Performance benchmarking could be added in future work

Checklist

Documentation

  • Documentation updated
    • Docstring: Comprehensive operator schema documentation with parameter descriptions and usage examples
    • Doxygen: C++ code documentation following DALI conventions
    • RST: Added CLAHE optimizations section to performance tuning guide
    • Other: Performance optimization details documented in PERFORMANCE_NOTES.md

DALI team only

Requirements

  • Implements new requirements
  • Affects existing requirements
  • N/A

REQ IDs: N/A

JIRA TASK: N/A

@JanuszL
Copy link
Contributor

JanuszL commented Oct 15, 2025

@tonyreina, thank you for your contribution. We appreciate the time you spent diving into DALI and extending it.

I haven't delved deeply into the code yet, as I focused more on general remarks - mostly regarding testing, examples, and memory management. Please let us know if you need any guidance in applying the suggestions.

@tonyreina tonyreina force-pushed the main branch 2 times, most recently from 084b2f1 to 4e087d2 Compare October 15, 2025 18:01
@tonyreina tonyreina closed this Oct 15, 2025
@mzient mzient assigned mzient and unassigned klecki Oct 15, 2025
@tonyreina tonyreina reopened this Oct 15, 2025
@review-notebook-app
Copy link

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@tonyreina tonyreina requested review from JanuszL and mzient October 15, 2025 22:59
@jantonguirao
Copy link
Contributor

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [36715300]: BUILD STARTED

@jantonguirao
Copy link
Contributor

Would be nice to add images to the example, to see the effect of this transformation visually

Signed-off-by: Tony Reina <[email protected]>
@tonyreina tonyreina requested a review from mzient November 13, 2025 19:49
@tonyreina
Copy link
Author

Can you re-try the build and tests?

Could you please render the Jupyter notebook and upload it in that format?

Rendered.

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

13 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [38418710]: BUILD FAILED

Signed-off-by: Tony Reina <[email protected]>
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

13 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

@tonyreina
Copy link
Author

Is there a build error message?

@JanuszL
Copy link
Contributor

JanuszL commented Nov 14, 2025

Is there a build error message?

Let me rerun this with the latest changes.

@JanuszL
Copy link
Contributor

JanuszL commented Nov 14, 2025

!build

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [38479272]: BUILD STARTED

@JanuszL
Copy link
Contributor

JanuszL commented Nov 14, 2025

I see following errors:
Gtest:

[2025-11-14 09:47:15] [ RUN      ] ClaheOpTest.LumaOnlyVsPerChannel
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] !!! Forced use of Executor 2.0 !!!
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] !!! Forced use of Executor 2.0 !!!
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] !!! Forced use of Executor 2.0 !!!
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] !!! Forced use of Executor 2.0 !!!
[2025-11-14 09:47:15] unknown file: Failure
[2025-11-14 09:47:15] C++ exception with description "Critical error in pipeline:
[2025-11-14 09:47:15] Critical error in pipeline:
[2025-11-14 09:47:15] Error in GPU operator `nvidia.dali.ops.Clahe` encountered:
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] ClaheGPU RGB input requires luma_only=True; per-channel mode (luma_only=False) is not supported on GPU. Use CPU backend for per-channel processing.
[2025-11-14 09:47:15] Current pipeline object is no longer valid.
[2025-11-14 09:47:15] Current pipeline object is no longer valid." thrown in the test body.
[2025-11-14 09:47:15] 

test_clahe.py

[2025-11-14 11:02:30] ======================================================================
[2025-11-14 11:02:30] ERROR: test_clahe (nose2.loader.ModuleImportFailure)
[2025-11-14 11:02:30] ----------------------------------------------------------------------
[2025-11-14 11:02:30] ImportError: Failed to import test module: test_clahe
[2025-11-14 11:02:30] Traceback (most recent call last):
[2025-11-14 11:02:30]   File "/usr/local/lib/python3.10/dist-packages/nose2/plugins/loader/discovery.py", line 195, in _find_tests_in_file
[2025-11-14 11:02:30]     module = util.module_from_name(module_name)
[2025-11-14 11:02:30]   File "/usr/local/lib/python3.10/dist-packages/nose2/util.py", line 73, in module_from_name
[2025-11-14 11:02:30]     __import__(name)
[2025-11-14 11:02:30]   File "/opt/dali/dali/test/python/operator_1/test_clahe.py", line 17, in <module>
[2025-11-14 11:02:30]     import pytest
[2025-11-14 11:02:30] ModuleNotFoundError: No module named 'pytest
'```

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [38479272]: BUILD FAILED

@tonyreina
Copy link
Author

I see following errors: Gtest:

[2025-11-14 09:47:15] [ RUN      ] ClaheOpTest.LumaOnlyVsPerChannel
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] !!! Forced use of Executor 2.0 !!!
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] !!! Forced use of Executor 2.0 !!!
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] !!! Forced use of Executor 2.0 !!!
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] !!! Forced use of Executor 2.0 !!!
[2025-11-14 09:47:15] unknown file: Failure
[2025-11-14 09:47:15] C++ exception with description "Critical error in pipeline:
[2025-11-14 09:47:15] Critical error in pipeline:
[2025-11-14 09:47:15] Error in GPU operator `nvidia.dali.ops.Clahe` encountered:
[2025-11-14 09:47:15] 
[2025-11-14 09:47:15] ClaheGPU RGB input requires luma_only=True; per-channel mode (luma_only=False) is not supported on GPU. Use CPU backend for per-channel processing.
[2025-11-14 09:47:15] Current pipeline object is no longer valid.
[2025-11-14 09:47:15] Current pipeline object is no longer valid." thrown in the test body.
[2025-11-14 09:47:15] 

test_clahe.py

[2025-11-14 11:02:30] ======================================================================
[2025-11-14 11:02:30] ERROR: test_clahe (nose2.loader.ModuleImportFailure)
[2025-11-14 11:02:30] ----------------------------------------------------------------------
[2025-11-14 11:02:30] ImportError: Failed to import test module: test_clahe
[2025-11-14 11:02:30] Traceback (most recent call last):
[2025-11-14 11:02:30]   File "/usr/local/lib/python3.10/dist-packages/nose2/plugins/loader/discovery.py", line 195, in _find_tests_in_file
[2025-11-14 11:02:30]     module = util.module_from_name(module_name)
[2025-11-14 11:02:30]   File "/usr/local/lib/python3.10/dist-packages/nose2/util.py", line 73, in module_from_name
[2025-11-14 11:02:30]     __import__(name)
[2025-11-14 11:02:30]   File "/opt/dali/dali/test/python/operator_1/test_clahe.py", line 17, in <module>
[2025-11-14 11:02:30]     import pytest
[2025-11-14 11:02:30] ModuleNotFoundError: No module named 'pytest
'```

ok. please try the build again.

thanks!

-Tony

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. docs/examples/image_processing/clahe_example.ipynb, line 1 (link)

    logic: Notebook file is completely empty with no content. The PR description mentions a comprehensive Jupyter Notebook example demonstrating CLAHE usage patterns and parameter effects, but this file contains nothing. Users will have no practical example of how to use the new CLAHE operator.

13 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile
React with 👍 or 👎 to share your feedback on this new summary format

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [38651866]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [38651866]: BUILD FAILED

@tonyreina
Copy link
Author

CI MESSAGE: [38651866]: BUILD FAILED

What was the latest build error?

Is there a way I can run this build test from the docker/build.sh?

@JanuszL
Copy link
Contributor

JanuszL commented Nov 18, 2025

@tonyreina
It seems that only one issue remains:

[2025-11-17 22:00:06] [ RUN      ] ClaheOpTest.GpuRejectsPerChannelMode
[2025-11-17 22:00:06] 
[2025-11-17 22:00:06] !!! Forced use of Executor 2.0 !!!
[2025-11-17 22:00:06] /opt/dali/dali/operators/image/clahe/clahe_test.cc:202: Failure
[2025-11-17 22:00:06] Expected: pipe.Run() throws an exception of type std::runtime_error.
[2025-11-17 22:00:06]   Actual: it throws nothing.```

Signed-off-by: Tony Reina <[email protected]>
Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. docs/examples/image_processing/clahe_example.ipynb, line 1 (link)

    logic: Empty notebook file provides no documentation despite PR claiming comprehensive example. This completely fails to deliver the promised educational content for CLAHE operator usage. Was this notebook supposed to contain actual example code and documentation, or is this an accidental commit of an empty file?

13 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile
React with 👍 or 👎 to share your feedback on this new summary format

@JanuszL
Copy link
Contributor

JanuszL commented Nov 18, 2025

!build

@tonyreina
Copy link
Author

@tonyreina It seems that only one issue remains:

[2025-11-17 22:00:06] [ RUN      ] ClaheOpTest.GpuRejectsPerChannelMode
[2025-11-17 22:00:06] 
[2025-11-17 22:00:06] !!! Forced use of Executor 2.0 !!!
[2025-11-17 22:00:06] /opt/dali/dali/operators/image/clahe/clahe_test.cc:202: Failure
[2025-11-17 22:00:06] Expected: pipe.Run() throws an exception of type std::runtime_error.
[2025-11-17 22:00:06]   Actual: it throws nothing.```

Ok. I think I've got it now. I was able to do the GTest on my side using some mods to the build.sh script (but didn't push these).

@JanuszL
Copy link
Contributor

JanuszL commented Nov 18, 2025

@tonyreina It seems that only one issue remains:

[2025-11-17 22:00:06] [ RUN      ] ClaheOpTest.GpuRejectsPerChannelMode
[2025-11-17 22:00:06] 
[2025-11-17 22:00:06] !!! Forced use of Executor 2.0 !!!
[2025-11-17 22:00:06] /opt/dali/dali/operators/image/clahe/clahe_test.cc:202: Failure
[2025-11-17 22:00:06] Expected: pipe.Run() throws an exception of type std::runtime_error.
[2025-11-17 22:00:06]   Actual: it throws nothing.```

Ok. I think I've got it now. I was able to do the GTest on my side using some mods to the build.sh script (but didn't push these).

Thank you. Let me give it a go.

@tonyreina
Copy link
Author

I think it couldn't be scheduled for the build.

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [38766317]: BUILD STARTED

@dali-automaton
Copy link
Collaborator

CI MESSAGE: [38766317]: BUILD PASSED

@JanuszL
Copy link
Contributor

JanuszL commented Nov 20, 2025

@tonyreina the CI is passing so please let us review the latest changes again. We hope to do that soon (it is over 4k lines of code after all).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants