Skip to content

Feature request: --vpp-msharpen / --vpp-msmooth - Edge-masked sharpening and smoothing filters #283

@teaching-droid

Description

@teaching-droid

Hi @rigaya

Thank you, as always, for the fantastic work on NVEncC/QSVEncC/VCEEncC.

I want to suggest two complementary filters from Donald A. Graft (both GPL v2+, source available at http://www.rationalqm.us/mine.html):

MSharpen - edge-selective sharpening
MSmooth - edge-preserving spatial smoothing

What makes these different from existing filters?

The biggest complaint about the unsharp mask is that setting the strength high enough to sharpen important edges also amplifies noise and small details. MSharpen solves this by first detecting important edges, then applying sharpening only to those areas. You can set very high sharpening strengths without amplifying noise because the edge mask protects non-edge areas.

Similarly, the biggest complaint about typical threshold-based smoothers is that setting the threshold high enough for good smoothing also destroys detail. MSmooth solves this by decoupling the two controls: threshold controls what is detected as detail, and strength controls how much smoothing is applied. You tune them independently.

Both filters share the same edge detection (3×3 box blur → threshold comparison → binary mask). The only difference is what happens after:

  • MSharpen applies unsharp-mask sharpening at edge pixels, leaves flat areas alone
  • MSmooth applies spatial averaging in flat areas, leaves edge pixels alone

How the algorithm works

Edge detection is quite simple: blur the source, compare neighbouring pixel values against a threshold, and build a binary mask. There's a "highq" mode that checks all four directions (diagonal + vertical + horizontal) instead of just diagonal.

For MSharpen, the sharpening formula at edge pixels is 4·src − 3·blur, blended by strength. Single-pass after edge detection.

For MSmooth, non-edge pixels are averaged with their cardinal neighbours (but only the neighbours that are also non-edge). This smoothing pass is repeated strength times (1-25) for progressively stronger smoothing, similar to how --vpp-warpsharp handles its iterative blur.

Proposed syntax

--vpp-msharpen [threshold=<int>],[strength=<int>],[highq=<bool>],[mask=<bool>]
  • threshold (0-255, default 15): edge detection sensitivity
  • strength (0-255, default 100): sharpening intensity
  • highq (default true): full 4-direction edge detection
  • mask (default false): show edge mask for threshold tuning
--vpp-msmooth [threshold=<int>],[strength=<int>],[highq=<bool>],[mask=<bool>],[chroma=<bool>]
  • threshold (0-255, default 15): edge detection sensitivity
  • strength (1-25, default 3): smoothing iterations
  • highq (default true): full 4-direction edge detection
  • mask (default false): show edge mask for threshold tuning
  • chroma (default false): also smooth chroma planes

Code

I've taken a look at the original source code and prepared some OpenCL kernel drafts and C++ skeleton headers following the rgy_filter_* conventions, in case they might be useful as a starting point. The kernels use the standard read_imagef / write_imagef pattern. Since both filters share the blur and edge-mask kernels, implementing the second one after the first would mostly just mean adding one more kernel.

I'm happy to attach these files if you're interested.

Source material

  • MSharpen 1.10 by Donald A. Graft (GPL v2+): http://www.rationalqm.us/mine.html
  • MSmooth 2.02 by Donald A. Graft (GPL v2+): same site

Even implementing just MSharpen alone would already be very valuable.
I suggest these improvements to contribute to the project's continued excellence.

Thank you for considering this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions