-
Notifications
You must be signed in to change notification settings - Fork 0
DecombUCF
Scene‑change–aware frame replacement filters in KFM, inspired by and extended from DecombUCF (merged scene‑change logic, CUDA‑enabled).
Reference: DecombUCF by ちょっとだけ.
Pre‑processing filter for noise analysis used by DecombUCF
- clip – Source clip
- clip – Noise‑detection clip (e.g., source with Gaussian blur applied)
- int nmin_y = 1
- int range_y = 128
- int nmin_uv = 1
- int range_uv = 128
Noise analysis filter for DecombUCF
- CUDA support: Yes
- clip – Source clip
- clip – KNoiseClip clip
- clip "pad" – KFMPad clip
KDecombUCFParam(int "chroma", float "fd_thresh", int "th_mode", float "off_t", float "off_b", float "namax_thresh", float "namax_diff", float "nrt1y", float "nrt2y", float "nrt2x", float "nrw", bool "show", float "y1", float "y2", float "y3", float "y4", float "y5", float "x1", float "x2", float "x3", float "x4", float "x5")
Parameter clip for DecombUCF
-
CUDA support: –
-
int chroma = 1 –
[0–2]#(0:Y), (1:UV), (2:YUV) for noise detection -
float fd_thresh = 128 –
[0–]#threshold of FieldDiff;fd_thresh = FieldDiff * 100 / (Width * Height) -
int th_mode = 0 –
[1–2:debug][3–7:normal][8–10:restricted]#preset of diff threshold. You can also specify thresholds via x1–x5/y1–y5 (requiresth_mode=0). -
float off_t = 0 – Offset for top‑field diff threshold (first field, top, diff<0)
-
float off_b = 0 – Offset for bottom‑field diff threshold (second field, bottom, 0<diff)
-
reverse (works only when
chroma=0. If absolute noise is too large, treat it as a visual effect and keep the noisier field; the smaller one is flattened by block noise)-
int namax_thresh = 82 –
82 #MX:90 #[0–256]#disabled with chroma=1; upper limit of max noise for detection (75–80–83) -
int namax_diff = 38 –
30–40#disabled with chroma=1; if average noise ≥namax_thresh, usenamax_diffas diff threshold.
-
int namax_thresh = 82 –
-
NR
-
float nrt1y = 28 –
28–29–30#threshold for NR -
float nrt2y = 36 –
36–36.5–37#exclusion range -
float nrt2x = 53.5 –
53–54–55#exclusion range -
float nrw = 2 –
1–2#diff weight for NR threshold
-
float nrt1y = 28 –
-
bool show = false – Turn on debug display (actual behavior varies by filter)
-
float y1..y5, x1..x5 – Score calculation parameters
Analyzes a 24p clip and applies replacement to a 24p clip (same as the original).
- CUDA support: Yes
- clip – Target 24p clip
- clip – KDecombUCFParam clip
- clip – KAnalyzeNoise clip
- clip – bob clip (for when the next field is corrupted)
- clip – bob clip (for when the previous field is corrupted)
- clip "nr" – Optional NR clip
Two bob clips are required because QTGMC‑like bob filters interpolate from both previous and next fields. Even if you choose the previous field to avoid a corrupted field, the nature of the algorithm still mixes in the corrupted field. To avoid this, input two bob clips: one interpolated without using the next field and one without using the previous field, and switch between them appropriately.
The original QTGMC has no option to “not use the next/previous field”. KTGMC can switch this via useFlag. See the usage example below.
Example
TODO
Analyzes a 60i clip and applies replacement to a 24p clip.
- CUDA support: Yes
- clip – Target 24p clip
- clip – KDecombUCFParam clip
- clip – KFMCycleAnalyze clip
- clip – KAnalyzeNoise clip
- clip – bob clip (for when the next field is corrupted)
- clip – bob clip (for when the previous field is corrupted)
- clip "nr" – Optional NR clip
Example
TODO
Analyzes a 60i clip and applies replacement to a 60p clip.
-
Algorithm
- Roughly: the primary judgment uses DecombUCF noise detection; the secondary judgment uses scene‑change detection (both to improve accuracy).
- Perform DecombUCF noise detection on each frame of the DoubleWeaved interlaced source.
- Frames corresponding to fields detected as “dirty” are marked “dirty frames.”
- Not all dirty frames are replaced; replacement occurs only if both of the following hold:
- The dirty frame lies around a scene change; and
- The frame before or after the replacement candidate is static
- Static frames are likely clean
- Motion‑heavy segments are rejected by this criterion
- Additionally, for the dirty frame and its ±1 neighbors, the bob clip is selected to avoid the dirty field.
- In other words, the dirty frame and its neighbors are replaced by frames drawn from the bob clip.
-
CUDA support: Yes
-
clip – Target 60p clip
-
clip – KDecombUCFParam clip
-
clip – KAnalyzeNoise clip
-
clip – bob clip (when the next field is corrupted)
-
clip – bob clip (when the previous field is corrupted)
-
clip "nr" – Optional NR clip
-
float sc_thresh = 256 – Threshold to determine scene changes around the replacement target. Smaller → more frames considered scene changes.
-
float dup_factor = 2.5 – Threshold to determine whether frames around the replacement target are static. Smaller → more frames considered static.
Example
srcpath = "..."
src = LWLibavVideoSource(srcpath,dominance=1,repeat=True).OnCPU(2)
bob = src.KTGMC(Preset="Faster")
before = src.KTGMC(Preset="Faster", PrevGlobals="Reuse", useFlag=1)
after = src.KTGMC(Preset="Faster", PrevGlobals="Reuse", useFlag=2)
fields = src.SeparateFields().Crop(4,4,-4,-4).Align()
noise = fields.KGaussResize(p=2.5)
noise = src.KAnalyzeNoise(fields.KNoiseClip(noise), src.KFMPad()).OnCUDA(2)
bob.KDecombUCF60(KDecombUCFParam(), noise, before, after).OnCUDA(2)