Skip to content

Dev v0.2.1#5

Merged
mathiassalvas merged 6 commits into
mainfrom
dev_v0.2.1
Jun 29, 2026
Merged

Dev v0.2.1#5
mathiassalvas merged 6 commits into
mainfrom
dev_v0.2.1

Conversation

@mathiassalvas

Copy link
Copy Markdown
Collaborator

Summary

Adds image-enhancement methods, new validation utilities and metrics, several bug fixes, stronger test coverage, and updated documentation.

Image enhancement

utils.py

Added six grayscale enhancement methods:

  • classic_he_gray
  • tidhe_gray
  • rdfhe_gray
  • nfldice_gray
  • betce_gray
  • sfcef_gray

All methods support legacy_mode=True.

Documented two intentional differences from SHINE/MATLAB:

  • The noise tie strategy in exact_histogram uses centered noise instead of SHINE’s one-sided noise, avoiding upward bias.
  • sf_match and spec_match use soft_clip rather than MATLAB-style hard clipping, because hard clipping distorts the matched spectrum.

Mode 9

Mode 9 now supports two standalone operation groups through standalone_op:

  • "ie_methods" for image enhancement
  • "dithering" for dithering

The CLI now prompts users to select the standalone operation.

Validation and metrics

Added:

  • sf_match_validation
  • spec_match_validation
  • corr_rmse_per_item
  • mean_spectrum
  • ImageStats
  • imstats
  • AMBE, MSSIM, PSNR, BP2BPSIM, contrast-improvement, and entropy metrics
  • tidhe_hist_plot

The spectrum validation functions support fft_padding_mode.

Bug fixes

ImageProcessor.py

Fixed background-pixel overflow in modes 7 and 8 by applying soft_clip during the final outer iteration. This prevents out-of-range IFFT values from accumulating while preserving foreground rank ordering before histogram matching.

utils.py

Added clipping after dataset-level min/max normalization in rescale_images255 option 3, preventing outlier images from exceeding [0, 255].

Converter.py

Improved legacy_mode compatibility:

  • Grayscale conversion now explicitly uses MATLAB-compatible Rec. 601 weights.
  • The output matches the Y component of MATLAB rgb2ntsc.
  • Added MATLAB_RGB2GRAY_WEIGHTS.
  • Renamed conversion_type to color_conversion.
  • Clarified the legacy conversion path in the docstrings.
     

ImageProcessor.py

  • The seedfrom Options was never used, always resorted to "int(datetime.now().timestamp())"

Chroma-loss utilities

Shortened quantify_chroma_loss.py and several function names.

Tests

Improved test infrastructure:

  • Failed and errored combinations are retried instead of being treated as cached successes.
  • Image preparation now processes only the first image in each buffer cell and removes unused buffers.
  • Validation seeds are deterministic and reproducible.
  • Unexpected Options() errors now fail explicitly.
  • Coverage accounting now verifies actual combinations.
  • Final SSIM checks were refined for composite modes.
  • RMSE baselines now use the initial processing buffer.

Added:

  • Utils_test.py
  • PrunedCoverage_test.py
  • ImageEnhancement_validation_test.py
  • MATLAB reference hashes and SFCEF reference outputs

TIDHE, RDFHE, NFLDICE, and BETCE are validated against pixel-exact MATLAB hashes. SFCEF allows a maximum difference of one gray level because of floating-point and FMA rounding.

Documentation

Updated documentation.md with:

  • Expanded RGB-to-grayscale documentation
  • FMA and ULP explanations
  • Revised mode 9 usage
  • Histogram-equalization terminology
  • Descriptions of Classic HE, TIDHE, RDFHE, NFLDICE, BETCE, and SFCEF
  • Updated testing documentation

Updated demos.md with separate mode 9 examples for image enhancement and dithering.

utils.py — image enhancement algorithms (mode 9)
- Added classic_he_gray, tidhe_gray, rdfhe_gray, nfldice_gray, betce_gray, sfcef_gray; all support legacy_mode=True.
- Documented intentional deviations from SHINE/MATLAB in-source:
  · exact_histogram 'noise' tie-strategy uses centered noise [-level, +level] instead of SHINE match.m's
    one-sided rand()*0.1, avoiding systematic upward bias.
  · sf_match/spec_match use soft_clip instead of MATLAB's silent uint8 hard-clip, even in legacy_mode
    (hard-clip distorts the matched spectrum).

utils.py — validation
- Added sf_match_validation and spec_match_validation (adapted for fft_padding_mode).
- Added corr_rmse_per_item and mean_spectrum (de-duplicate repeated code).

utils.py — metrics
- Added ImageStats and imstats (replicate MATLAB imstats.m).
- Added compute_ambe, compute_mssim, compute_psnr, compute_bp2bpsim, compute_contrast_improvement,
  compute_image_entropy.
- Added tidhe_hist_plot.

Options.py
- Added mode=9 standalone_op parameter ('dithering', 'ie_methods'). Mode 9 is no longer dithering-only:
  it now groups the non-matching processing options and catalogues the image enhancement methods.

SHINIER.py
- Mode 9 CLI prompts for standalone_op selection.

Bug fixes

ImageProcessor.py — background pixel overflow in modes 7 and 8
- Frequency operations (sf_match, spec_match) produce out-of-range IFFT values for background pixels
  (outside the mask, not processed by the following hist_match); with _is_moving_target=True these
  accumulate across iterations. Fixed by applying soft_clip when _iter_num == iterations-1 (last outer
  iteration) instead of only at _is_last_operation. soft_clip is monotonic, so it preserves the rank
  ordering seen by the following hist_match on foreground pixels.

utils.py — rescale_images255 option 3
- Dataset-average min/max normalization could map outlier images outside [0, 255]; added
  np.clip(..., 0, 255) after the linear rescaling.

Converter.py — legacy_mode improvements
- forward_color_treatment/backward_color_treatment with legacy_mode=True now explicitly call
  rgb2gray(weighting_standard="rec601", matlab_601=True) — equivalent to rgb2ntsc_intensity — matching
  the Y channel of MATLAB rgb2ntsc / NTSC-YIQ, and output the Y component.
- Renamed parameter conversion_type -> color_conversion in both methods.
- Added MATLAB_RGB2GRAY_WEIGHTS constant with the exact MATLAB Rec.601 weights.
- Improved legacy_mode docstring: clarifies when the NTSC-YIQ path is taken and its relationship to
  Options(legacy_mode=True).

quantify_chroma_loss.py
- Shortened the file name and several function names.

Tests

tests/tools/utils.py
- is_already_done skips only terminal-success statuses; failed/error combos are retried, not cached green.
- prepare_images treats only the first image per buffer cell and drops the unused buffers_other (~12 -> 2 MB).

tests/validation_tests/ImageProcessor_validation_test.py
- Seed authoritative per combo (from_unit_test + proc.seed, then process()); no wall-clock reseed, so
  failures reproduce. seed_iter strips volatile paths; combo_hash namespaced by option-space fingerprint.
- Unexpected Options() errors hard-fail (not "invalid"); real coverage accounting replaces the vacuous
  cnt>=0 assert.
- 'final' SSIM check hard only for mode 2; composite modes 5-8 gate on final-output SSIM (hard collapse
  floor + soft degraded warning). RMSE baseline now uses proc._initial_buffer.

New test files
- tests/unit_tests/Utils_test.py.
- tests/unit_tests/PrunedCoverage_test.py.
- tests/validation_tests/ImageEnhancement_validation_test.py (pixel-exact MATLAB SHA-256 hashes for
  TIDHE/RDFHE/NFLDICE/BETCE; pixel-difference bound <= 1 gray level for SFCEF due to FMA rounding).
- tests/assets/image_enhancement_matlab_sha256.json.
- tests/assets/sfcef_matlab_reference/.

Documentation

documentation.md
- Expanded the RGB-to-grayscale section.
- Added "Convolution — FMA and Unit in the Last Place (ULP)".
- Updated mode 9 to document standalone_op and ie_methods.
- Added "Histogram Equalization: Exact Specification and Histogram-Derived Remapping".
- Added algorithm descriptions (sections 5-10): Classic HE, TIDHE, RDFHE, NFLDICE, BETCE, SFCEF.
- Updated the testing section: Utils_test, PrunedCoverage_test, ImageEnhancement_validation_test.

demos.md
- Updated the mode 9 example; split into 9a (standalone_op="ie_methods", with ie_methods selection)
  and 9b (standalone_op="dithering").
@mathiassalvas mathiassalvas merged commit b29fa29 into main Jun 29, 2026
24 checks passed
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.

1 participant