# MaskTools

## Přehled

autor: kurosu and Manao
verze: 1.5.8
stáhnout: http://manao4.free.fr/, http://www.avisynth.org/warpenterprises/
kategorie: Různé pluginy
požadavky: YV12 Barevné prostředí
license: GPL

## Obsah

- I) O pluginu MaskTools
  - 1) Obecně
  - 2) Popis
- II) Popis funkcí
- III) Některá praktická použití
  - 1) MSharpen
  - 2) MSoften
  - 3) Redukce duhy
  - 4) Supervzorkovaný fxtoon
  - 5) Warpsharp pro tmavý jas (luma)
  - 6) Pseudo-deinterlacer (barevnost bude stále problematická)
  - 7) Nepravoúhlá překrývání
  - 8) Náhrada pozadí
  - 9) Kmf-Toon ;-)
- IV) Na dopracování
- V) Odmítnutí záruk (nepřeskakujte tuto část, ale nenutím vás to naučit se)
- VI) Revize
- VII) Pro vývojáře

## I) O pluginu MaskTools

### 1) Obecně

Po zpracování můžete potřebovat zachovat jen část výstupu. Řekněme, máte klip nazvaný smooth, který je výsledkem vyhlazování (blur() například) klipu nazvaného source.
Většina šumu z klipu source v klipu smooth zmizela, Ale také má detaily. Proto by jste mohli chtít zachovat jen filtované pixely a zahodit ty, ve kterých je velký rozdíl barev nebo světlosti. To je to co dělá například MSmooth od D. Grafta. Nyní uvažujme, že zapíšete pixely obrazu ze smooth, které chcete zachovat jako bílé pixely, a ty druhé z klipu source jako černé pixely. Získáne to co se nazývá maskou. MaskTools jsou o vytváření, přeměnách a manipulaci s takovými maskami pro každou komponentu barevného prostředí YV12.

### 2) Popis

Tento plugin pro Avisynth 2.5, který je určen jen pro YV12 nabízí několik funkcí manipulace s klipy jako maskami:

- Binarize bude binarizovat vstupní obraz podle prahové hodnoty a příkazu.
- CombMask vytváří masku, která dává oblasti, kde se nachází prokládání (combing).
- DEdgeMask / DEdgeMask2 vytváří masku hran klipu, použitím vymezení prahových hodnot (dané hodnoty je zapínají nebo vypínají).
- EdgeMask vytváří masku hran klipu, použitím vymezení prahových hodnot - thresholding (dané hodnoty je zapínají nebo vypínají). Podobná s DEdgeMask s předdefinovanými jádry.
- Expand 'expanduje' vysoké hodnoty v ploše, vkládáním maximální hodnoty v okolí 3x3 kolem vstupního pixelu do výstupu. Opačná funkce se nazývá Inpand.
- FitY2UV/FitY2U/FitY2V mění velikost plochy Y a nahrazuje UV/U/V plochy výsledkem změny velikosti (můžete zadat svůj filtr změny velikosti, dokonce takový, který není vestavěn v AviSynthu); opačné funkce jsou FitU2Y a FitV2Y.
- Inflate 'nafoukne' vysoké hodnoty v ploše, vložením do výstupní plochy buď průměr 8 sousedů, pokud je vyšší než původní hodnota, jinak původní hodnotu. Opačná funkce se nazývá Deflate (věnováno Philu Katzovi).
- Invert invertuje pixel (t.j. out = 255 - in); toto může být také použito pro aplikaci 'solarize' efektu na obraz.
- Logic vykoná nejtypičtější logické operace (ve skutečnosti, ty samé jako nabízí MMX mnemonics, třebaže jsou C funkce stále dostupné, hlavně kvůli omezení rozměrů obrazu).
- RGBLUT/YV12LUT/YV12LUTxy jsou tabulky, umožňující aplikovat rychle funkci na všechny pixely obrazu.
- MaskedMerge vezme 3 klipy a použije vážené sloučení mezi prvním a druhým klipem podle masky reprezentované klipem3.
- MotionMask vytvoří masku pohybu v obrazu.
- OverlayMask porovná 2 klipy založené na prahových hodnotách jasu a barevnosti, a říká zda jsou pixely blízké nebo ne (podobné tomu co dělá ColorKeyMask).
- YV12Convolution vám umožní convole (svinout) obraz maticí podle vaší volby.
- YV12Layer je ekvivalent k OverLay.
- YV12Substract je stejná jako Subtract, také pracuje v YV12, ale *měla by* být trochu rychlejší (protože má MMX optimalizaci).

Dále, všechny funkce berou 3 parametry: Y, U a V (kromě FitPlane funkcí, kde jména jasně říkají co je zpracováno). Podle jejich hodnoty (value), jsou aplikovány různé operace na každou plochu:

- value = 3 udělá skutečné zpracování filtrem,
- value = 2 zkopíruje 2.video plochu (je-li použitelná) do výstupu odpovídající plochy
- value = 1 to nezpracuje (t.j., nejčastěji, nechá to s 1.plochou klipu nebo smetím - prověřte to sami)
- value = [-255...0] zaplní výstup plochy zápornou hodnotou (t.j. aby jsme měli šedé úrovně, použijte U=128,V=128)

Posledním bodem je schopnost některých funkcí zpracovat jen část snímku:

- toto chování je nastaveno parametry (offX, offY) (pozice počátečního bodu) a (w,h) (šířka a výška zpracované oblasti); filtry by měli upravovat tyto parametry, tak že zpracovaná oblast je uvnitř 2 obrazů
- v případě filtru (kromě YV12Layer) používajícího 2 klipy, musí mít 2 klipy stejné rozměry
- ve všech případech, musí být rozměry obrazu dělitelné minimálně 8 (někdy 16) aby se zapnulo využití MMX funkcí (t.j. práce plnou rychlostí)

Toto bylo zamýšleno pro modularitu a atomické operace (nebo užitečné, jak je to možné), a ne právě pro rychlost. Stala se z toho nafouklá a pomalá věc. Nechám na vás rozhodnutí zda je toto tvrzení zcela pravdivé, nebo trochu méně... Příklady v kapitole III) jsou s největší pravděpodobností mnohem rychleji aplikovány původními filtry.

## II) Popis funkcí

### Binarize

`Binarize` (clip, int "threshold", bool "upper")
Filtr `Binarize` umožňuje základní vymezení prahových hodnot (thresholding) obrazu. Jestliže upper=true, pixel jehož hodnota je striktně větší než prahová hodnota threshold bude nastavena na nulu, jinak na 255. Naproti tomu, jestliže upper=false, pixel jehož hodnota je striktně větší než threshold bude nastaveno na 255, jinak na nulu.
Výchozí hodnoty jsou threshold = 20 and upper = true.

### CombMask

`CombMask` (clip, int "thY1", int "thY2")

Tento filtr produkuje masku zobrazující oblasti, které jsou prokládané (combed). Prahové hodnoty fungují jako u jiných filtrů: je-li po výpočtu hodnoty prokládání tato hodnota níž než thY1, nastaví se pixel na 0, když je nad thY2, nastaví se na 255, a mezitím je nastavená hodnota prokládání podělena 256.

Hodnota prokládání je (vyšší_pixel - pixel)*(nižší_pixel - pixel). Tedy, není to normalizováno do rozsahu 0..255, protože, kdyby to tak bylo, by byla blízko 1 nebo 2, ne víc. To znamená můžete použít prahovou hodnotu vyšší než 255, dokonce, i kdyby neměly být užitečné.

Výchozí jsou thY1 = 10 a thY2 = 10 ( tedy vytvoření binární masky ).

### DEdgeMask / DEdgeMask2

`DEdgeMask` (clip, int "thY1", int "thY2", int "thC1", int "thC2", string "matrix", float "divisor", bool "setdivisor", bool "vmode")
`DEdgeMask2` (clip source, clip low_thres, clip high_thres, string "matrix", float "divisor", bool "setdivisor", bool "vmode")
Tento filtr vytváří masku hran obrazu. Algoritmus nalezení hran používá konvoluční jádro, a výsledek konvoluce je pak vymezen pomocí prahových hodnot thY1 a thY2 ( jas - luma ) a thC1 a thC2 ( barevnost - chroma ). Vymezení nastane takto ( r je výsledek konvoluce ) :

- r <= th1 dává 0.
- th1 < r <= th2 dává r.
- th2 < r dává 255.

Za účelem vytvoření binární masky, musíte nastavit th1=th2.

Volba konvolučního jádra se provede maticí - matrix. matice musí být 3 na 3, jejíž koeficienty jsou celočíselné, oddělené jednou mezerou. Proto řetězece "-1 -1 -1 -1 8 -1 -1 -1 -1" a "0 -1 0 -1 0 1 0 1 0" dají jádra "laplace" a "sobel" filtru EdgeMask.

Koeficienty musí být celočíselné, divisor je použit pro očištění výsledku konvoluce. Tento výsledek bude jednoduše podělen parametrem divisor. Jestliže divisor není definovaný, vyjde se ze součtu kladných koeficientů matice, čímž se umožní klasická normalizace. Může být buď desetinný nebo celočíselný, z nichž ten druhý je rychlejší.
setdivisor je přítomen jen pro zpětnou kompatibilitu. Nepoužívejte ho.
A nakonec vmode umožní vytvářet masku středěnou na 128 místo nuly. Výchozí hodnoty jsou : thY1 = 0, thY2 = 20, thC1 = 0, thC2 = 20, matrix = "-1 -1 -1 -1 8 -1 -1 -1 -1" a vmode=false.

DEdgemask2 v zásadě pracuje jako DEdgeMask, kromě toho, že místo 2 nízkých / vysokých prahových hodnot bere 2 další klipy. Každý klip obsahuje lokální prahové hodnoty pro každý pixel. Řekněme, že chcete adaptivní prahové hodnoty beroucí lokální kontrast do své hodnoty. Dobrá, lokální min & max lze získat přes inpand() a expand(). Rozdíl může být vytvořen pomocí YV12LUTxy nebo YV12Subtract. A voila, máte prahový klip obsahující lokální kontrasty.

### EdgeMask

`EdgeMask` (clip, int "thY1", int "thY2", int "thC1", int "thC2", string "type")
Tento filtr vytváří masku hran v obrazu. Algoritmus nalezení hran používá konvoluční jádro, a výsledek konvoluce je pak vymezen prahovými hodnotami thY1 a thY2 ( jas ) a thC1 a thC2 ( barevnost ). Vymezení prahových hodnot nastane takto ( r je výsledek konvoluce ) :

- r <= th1 dává 0.
- th1 < r <= th2 dává r.
- th2 < r dává 255.

Aby se vytvořila binární maska, musíte nastavit th1=th2.

Volba konvolučnho jádra se provede parametrem type :

- type = "roberts" :

  2 | -1
  -1 | 0

- type = "sobel" :

  0 | -1 | 0
  -1 | 0 | 1
  0 | 1 | 0

- type = "laplace" :

  -1/8 | -1/8 | -1/8
  -1/8 | 1 | -1/8
  -1/8 | -1/8 | -1/8

- type = "special" :

  -1/4 | 0 | -1/4
  0 | 1 | 0
  -1/4 | 0 | -1/4

- type = "roberts" :

  2 | -1
  -1 | 0

A nakonec, existují dvě další možné hodnoty pro type ( "cartoon" a "line" ), které mají chování v této dokumentaci neuvedené.

Výchozí hodnoty jsou : thY1 = 0, thY2 = 20, thC1 = 0, thC2 = 20 a type = "sobel".

### FitY2U / FitY2V / FitY2UV FitU2Y / FitV2Y / FitU2V / FitV2U

`FitPlane` (clip, string resizer)

`FitPlane` má následující inkarnace:
- jas do barevnosti: `FitY2U`, `FitY2V`, `FitY2UV`
- barevnost do jasu: `FitU2Y`, `FitV2Y`
- barevnost do barevnosti: `FitU2V`, `FitV2U`

Tímto filtrem můžete rozšířit (použít) masku vytvořenou na jedné ploše do do jiné plochy.

### Inpand / Expand / Deflate / Inflate

`Inpand` (clip)
`Expand` (clip)
`Deflate` (clip)
`Inflate` (clip)

Tyto filtry umožňují zvětšit / snížit masku. `Expand` nahradí hodnotu pixelu největší okolní hodnotou. `Inpand` ji naopak nahradí nejnižší okolní hodnotou. `Inflate` vypočítá průměr okolních pixelů, a nahradí hodnotu pixelu vypočtenou jen, když je tento průměr vyšší než původní hodnota pixelu. `Deflate` Udělá to samé jen když je průměr nižší než původní hodnota.

Obraz vrácený funkcemi `Expand` / `Inflate` bude vždy vyšší než původní obraz. Naopak, obraz vrácený funkcemi `Inpand` / `Deflate` bude vždy nižší.

Zvětšení / snížení vytvářené pomocí `Deflate` / `Inflate` je měkčí než to, které vytváří `Expand` / `Inpand`.

### HysteresyMask

`HysteresyMask` (mask_clip1, mask_clip2)

Tento filtr vytváří masku ze dvou masek. Teoreticky, první maska by měla být uvnitř té druhé, ale může to fungovat i pokud tomu tak není ( ačkoli výsledky budou méně zajímavé ). Principem filtru je zvětšení částí, které patří k oběma maskám, uvnitř druhé masky.

Tento algoritmus je zajímavý protože umožňuje například získat masku hran se všemi zajímavými hranami, ale bez šumu. Sestavíte dvě masky hran, jednu s hodně hranami a šumem, a druhou s málo hranami a téměř bez šumu. Pak, použijete tento filtr, a měli by jste obdržet hrany bez šumu, protože šum ve druhé masce nebyl.

### Invert

`Invert` (clip, int offX, int offX, int w, int h)

Tento filtr nahrazuje hodnotu pixelu hodnotou 255-(hodnota pixelu).

Binarize(upper=false) mohlo by být shledáno (ale není zpracováno) jako

Invert().Binarize(upper=true)

### Logic

`Logic` (mask_clip1, mask_clip2, string "mode")

Tento filtr produkuje novou masku, která je výsledkem binární operace mezi dvěma maskami. Operace je zvolena parametrem mode.

- mode="and" : pracuje jen s binárními maskami ( jen pixel na 0 nebo 255 ). Výstupní maska je průnikem dvou masek. To znamená, že pokud oba odpovídající pixely jsou 255, výsledný pixel bude 255, jinak 0.
- mode="or" : pracuje jen s binárními maskami. Výstupní maska je sjednocením dvou masek. To znamená, že pokud jeden z odpovídajících pixelů je 255, výsledný pixel bude 255, jinak 0.
- mode="xor" : pracuje jen s binárními maskami. Výstupní maska je rozdílem (odlišností) mezi dvěma maskami. To znamená, že pokud ( výhradně ) jeden z odpovídajících pixelů je 255, výsledný pixel bude 255, jinak 0.
- mode="andn" : pracuje jen s binárními maskami. Výstupní maska je rozdílem (odečtením) druhé masky od první. To znamená, že pokud pixel první masky je 255 a druhá je 0, vrátí 255, jinak 0.
- mode="min" : vrací pro každý pixel minimální hodnotu mezi dvěma pixely vstupních masek. Jako mode="and", ale pro nebinární masky.
- mode="max" : vrací pro každý pixel maximální hodnotu mezi dvěma pixely vstupních masek. Jako mode="or", ale pro nebinární masky.

Pokud je logický operátor použit s nebinární maskou, výsledky jsou nepředvídatelné.

Výchozí : mode = "and".

### RGBLUT / YV12LUT / YV12LUTxy / YUY2LUT

`YV12LUT` (clip, string "yexpr", string "uexpr", string "vexpr")
`YUY2LUT` (clip, string "yexpr", string "uexpr", string "vexpr")
`RGBLUT` (clip, string "Rexpr", string "Gexpr", string "Bexpr", string "AMPFile")
`YV12LUTxy` (clipx, clipy, string "yexpr", string "uexpr", string "vexpr")

Tyto filtry aplikují funkci na každý pixel obrazu. Aby byl umožněn rychlý výpočet, každá možná hodnota funkce je předvypočtena a uložena v tabulce Look-Up Table ( udtud jména funkcí LUT ). To dělá tyto filtry slušně rychlými. `RGBLUT` pracuje přesně stejně jako `YV12LUT`, kromě toho, že má přidaný argument AMPFile. Umožní vám načíst photoshop barevný profil.

Aby bylo možné aplikovat téměř každou možnou funkci, je toto dáno řetězcem, který reprezentuje výraz v obráceném polském zápisu (reverse polish notation). Principem tohoto zápisu je zapisovat nejdříve operandy / parametry operátoru / funkce, a pak operátor / funkci samotnou. Proto, "3 + 7" se stane "3 7 +", a "sin(3)" se stane "3 sin". Půjdeme dále ve vysvětlování, "3 * 7 + 5" se stane "3 7 * 5 +", a "(3 + 7) * 5" : "3 7 + 5 *". Nyní rozumíte hlavnímu kladu tohoto zápisu (notation) : žádná potřeba závorek.

Výpočty jsou vedeny v reálných číslech. Kladná čísla představují pravdivé tvrzení, zatímco záporná čísla představují nepravdivé tvrzení. Symbol "x" v řetězci je hodnota pixelu před použitím funkce. Pro `YV12LUTxy` máte také symbol "y", který představuje hodnotu vázaného pixelu v druhém klipu. Symboly musí být odděleny jednou mezerou.

Jsou imlementovány některé operátory a funkce :

- +, -, /, *, ^, % jsou operátory plus, minus, děleno, krát, mocnina a modulo.
- &, |, °, !& jsou logické operátory and, or, xor, a not. Pokud je výsledek pravda, pak vrací 1.0, jinak -1.0.
- <, <=, >, >=, =, != jsou relační operátory menší než, menší nebo rovno, větší než, větší nebo rovno, rovná se, nerovná se. Pokud je výsledek pravda, pak vrátí 1.0, jinak -1.0.
- cos, sin, tan, acos, asin, atan, exp, log, abs jsou funkce kosinus, sinus, tangens, arckosinus, arcsinus, arctangens, exponenciální, napierův (přirozený) logaritmus, absolutní hodnota.
- ? umožní provést podmínkový test. Je to trojitý operátor, prvním operandem bývá podmínka, druhým hodnota jestli je podmínka pravdivá (true), třetím je hodnota jestliže je podmínka nepravdivá (false).

Několik příkladů :

* Binarizace obrazu pomocí prahové hodnoty 128 : "x 128 < 0 255 ?". Je to přeloženo jako : "(x < 128) ? 0 : 255".
* Levels(il, gamma, ih, ol, oh) ( Podívejte se na filtr Levels ) : "x il - ih il - / 1 gamma / ^ oh ol - *". To je přeloženo jako "(((x - il) / (ih - il)) ^ (1 / gamma)) * (oh - ol)".

Výchozí hodnoty jsou : Yexpr = Uexpr = Vexpr = "x" ( tedy filtr neudělá nic ).

### MaskedMerge

`MaskedMerge` (base_clip, overlay_clip, mask_clip)

Tento filtr aplikuje klip overlay_clip na klip base_clip, s ohledem na klip mask_clip. Přesněji, s bc, oc a mc hodnotami tří pixelů vzatých z base_clip, overlay_clip a mask_clip, bude výsledek :

    v = ((256 - mc) * bc + mc * oc + 128) / 256

128 je zde ke snížení chyby při zaokrouhlování celočíselného dělení.

Tedy, když je maska 255, pixel bude pixelem z overlay_clip, když je maska 0, pixel bude z base_clip, a mezitím bude smíchán z obou klipů.

### MotionMask

`MotionMask` (clip, int "thY1", int "thY2', int "thC1", int "thC2", int "thSD")

Tento filtr vytváří masku pohybu obrazu. Jako u jiných filtrů vytvářejících masky, jakmile je pohyb vypočítán, je vymezen dvěma prahovými hodnotami. Tento filtr bude také prověřovat změnu scény, a nevytváří masku jestliže už je nějaká detekována.

Detekce změny scény se provádí výpočtem součtů absolutních rozdílů v obrazu a jeho předchozího. Tento součet je zprůměrován a pak porovnán s thSD. Pokud je to víc než thSD, je detekována změna scény.

Pohyb je vypočítán stejným způsobem NoMoSmooth, což znamená, že pro každý pixel budeme počítat absolutní součet rozdílů mezi pixelem a jeho okolím, a pixel a okolí v předchozím obrazu. Výsledná hodnota je podělena číslem 9, aby byl výsledek normalizován do rozsahu 0 a 255.

Tento algoritmus dává pouze přiblížení (aproximaci) pohybu. Bude dobře pracovat na hranách objektu, ale ne uvnitř.

Výchozí hodnoty jsou : thY1= 20, thY2 = 20, thC1 = 10, thC2 = 10 a thSD = 10.

### YV12Convolution

`YV12Convolution` (clip, string "horizontal", string "vertical", int "total", bool "automatic", bool "saturate")

Tento filtr vypočítá konvoluční součin mezi obrazem a jádrem definovaným násobením hodnot horizontal a vertical. Tyto dva řetězce představují vektory. Musí mít lichý počet celých nebo reálných čísel, oddělených jednou mezerou. total je normalizační faktor, kterým je výsledek součinu podělen. Jestliže je automatic nastaveno na 'true', total je součtem koeficientů matice. To znamená, že touto cestou celková světlost obrazu není dotčena. Saturate umožní vybrat chování filtru, když je výsledkem záporné číslo.

- saturate = true : záporné hodnoty jsou vynulovány.
- saturate = false : záporné hodnoty jsou invertovány.

Pokud není total definován, je nastaven na součet koeficientů konvolučního jádra, čímž se umožní dobrá normalizace jader pro rozmazání (bluring) / zostření (sharpening).

Pokud jeden z koeficientů horizontal nebo vertical je reálné číslo, všechny výpočty budou provedeny jako floats (desetinné), takže filtr bude pomalejší.

Výchozí hodnoty jsou : horizontal = "1 1 1", vertical = "1 1 1" a automatic = false, saturate = true.

### YV12Subtract

`YV12Subtract` (clip1, clip2, int tol, bool "widerange")

Tento filtr vypočítá rozdíl mezi dvěma klipy. Existuje několik způsobů výpočtu tohoto rozdílu, závisejících na hodnotách widerange a tol.

- widerange = true : vypočítáme rozdíl ( n ) mezi dvěma klipy, a vrátíme r = 128 + 128 * pow(n / 255,1 / tol). Pokud tol < 0, 1 / tol se stane 0.5.
- widerange = false :
  - tol < 0 : vypočítáme absolutní rozdíl ( n ) mezi dvěma klipy, a vrátíme r = n / 2 + 128.
  - tol >= 0 : vypočítáme absolutní rozdíl ( n ) mezi dvěma klipy, a vrátíme 0 pokud n je nižší než tol, jinak n - tol.

Výchozí hodnoty jsou : tol = -1 and widerange = false.

## III) Některá praktická použití (ne moc testované)

Tyto příklady nechtějí vytvářet přesně stejné výsledky jako původní filtry, snaží se je napodobit, navíc jsou o dost pomalejší. Přes řadu dalších funkcí, žádná nová myšlenka.

Poznámky:
- Jsem příliš líný aktualizovat syntaxi, obzvlášť pokud jde o to jak pracuje mode=2, a jak bylo aktualizováno EdgeMask (nyní už například nepotřebuje Binarize)
- Některé filtry popisované jako 'na vytvoření' už existují (imagereader, úrovně pro sevření, ...).

#### 1) MSharpen

    # Sestaví EdgeMask pro clip1, Binarizuje ji a vloží výsledek do clip3
    # Aplikuje zostřovací filtr na clip1 a vloží ho do clip2
    ...
    return MaskMerge(clip1, clip2, clip3)

Zostřené hrany klipu clip2 vyšší než prahová hodnota dané do Binarize budou zostřeny a použity pro nahrazení jejich původních hodnot v klipu clip1. Mohli by jste také napsat filtr s oddělenou Look-up table (nejlépe by vypadala jako zvon), nahradit jí Binarize, a měli by jste vážené zostření podle hodnoty hrany: to je HiQ část ve SmartSmoothHiQ

    clip2 = clip1.<EdgeEnhancer>(<parameters>)
    #U a V plochy nepotřebují filtrování, Y ho potřebuje
    #EdgeMask(<...>, "roberts", Y=3, U=-128, V=-128) pro černobílou mapu
    clip3 = clip1.EdgeMask(15, 60, "roberts", Y=3, U=1, V=1)
    return MaskedMerge(clip1, clip2, clip3)

#### 2) MSoften

Nahraďte EdgeEnhancer prostorovým změkčovačem (kaskádová rozmazání? prostorové změkčení MMX?) a použijte upper=true pro výběr blízkých pixelů v ploše.

#### 3) Redukce duhy (jak se popisuje v tomto vlákně )

Upozornění, ani toto není zázračné řešení

    clip2 = clip1 změkčit na maximum (použitím deen("m2d") nebo edeen například)
    #Získejte jasovou mapu hran a zvýrazněte hrany roztažením (zahuštěním)
    # -> na širší oblasti, které mají být zpracovány
    clip3 = clip1.EdgeMask(6, "roberts", Y=3, U=1, V=1).Inflate(Y=3, U=1, V=1)
    #Nyní použijte jasovou masku hran (edgemask) jako masku barevnosti
    clip3 = YtoUV(clip3, clip3).ReduceBy2().Binarize(15, upper=false, Y=1, U=3, V=3)
    #Musíme zpracovat barevnost pixelů blízko hran, ale zachovat netknutou Y plochu
    return MaskedMerge(clip1, clip2, clip3, Y=1, U=3, V=3)

#### 4) Supersampled (supervzorkovaný) fxtoon

Netestováno

    . Použijte tweak ke ztmavení obrazu nebo použijte plugin, který sníží hodnoty Y
    -> clip2
    . Sestavte masku hran, Supersamplujte tuto masku, Binarizujte ji vysokou prahovou hodnotou
    (sevření zní lépe), zahustěte (inflate) ji klipem -> clip3
    . Použijte tmavší pixely klipu clip2 podle hodnot klipu clip3

#### 5) Warpsharp pro tmavý jas

Netestováno

    . Použijte warpsharp -> clip2 (nahrazení pixelů)
    . Vytvořte omezovací filtr nebo low-luma bypass filtr -> clip3 (mask)

#### 6) Pseudo-deinterlacer (barevnost bude stále problematická)

Netestováno

    clip2 = clip1.SeparateFields().SelectEven().<Method>Resize(<parameters>)
    clip3 = clip1.<CombingDetector>(<parameters>)
    return MaskedMerge(clip1, clip2, clip3, Y=3, U=3, V=3)

(barevnost dokonce ještě problematičtější)

#### 7) Nepravoúhlá překrývání

Ve skutečnosti je toto prováděno lépe funkcemi layer a mask...

    #Jednoduchý hack protože ImageReader potřebuje celočíselnou fps...
    #Většina zdrojů je nativně v YUY2/YV12
    clip = AviSsource("test.avi").ConvertToYV12().assumefps(fps)
    #Načtěte obrázek pro překrývání
    image = ImageReader("mask.bmp", 0, clip.framecount()-1, 24, use_DevIl=false)
    #Jednoduchý způsob: předpokládejme, že černá je průhledná
    #Jakákoliv jiná barva by byla docela komlikovanější*
    masktemp = imageYV12.Binarize(17, upper=false, Y=3)
    #Nastavíme jasovou masku aby zapadly plochy barevnosti
    mask = Mask.FitY2UV()
    #Nyní tak máme masku, která nám říká co chceme zachovat...
    #Nahradíme obrazem části klipu skryté maskou!
    MaskedMerge(clip, image, mask, Y=3, U=3, V=3)
    #*řešení: mask = OverlayMask(image, image.BlankClip("$xxxxxx"), 1, 1)

#### 8) Náhrada pozadí

Tento příklad by jistě vypadala lépe v RGB. Abyste se vyhnuly typickým problémům kvůli šumu nebo kompresi, raději použijte rozmazané verze klipu a obrazu.

    source = AviSource("overlay.avi").AssumeFPS(24)
    #rozmazání (blur) zdroje
    clip = source.Blur(1.58).Blur(1.58).Blur(1.58)
    #načtěte pozadí pro nahrazení, zachycené z rozmazané sekvence
    bgnd = ImageReader("bgnd.ebmp", 0, clip.framecount()-1, 24, use_DevIl=false)
    #načtěte nové pozadí
    new = ImageReader("new.ebmp", 0, clip.framecount()-1, 24, use_DevIl=false)
    #integrovaný filtr pro výstupní masku = (clip~overlay?)
    mask = OverlayMask(clip, overlay.ConvertToYV12(), 10, 10)
    MaskedMerge(source, new.ConvertToYV12(), mask, Y=3, U=3, V=3)

#### 9) K-mfToon

Potřebuje zahrnout více informací (původní url/příspěvky) ale prozatím si myslím, že původní autor filtru mfToon, mf (mf@onthanet.net) na to nebude reagovat moc vehementně, zatím to stále není adresováno.
Výstup funkce uvnitř K-mfToon.avs by měl být identický s výstupem původního mftoon.avs (také zahrnutý), s dvojnásobnou rychlostí.
Požadavky jsou:
- Pro mfToon:
. načíst pluginy zvané "MaskTools", "warsharp", "awarsharp"

## IV) Na dopracování

Nic, vše závisí na zpětné vazbě

## V) Odmítnutí záruk

Tento plugin je vydáván pod GPL licencí. Musíte souhlasit s podmínkami uvedenými v 'Copying.txt' před použitím pluginu nebo jeho zdrojového kódu.
Také se vám doporučuje používat ho ve filantropickém (lidumilném) rozpoložení, t.j. ne ve smyslu "Budu si tohle tajemství držet pro sebe".
V neposlední řadě, velmi malá část všech možných použití každého filtru byla testována (možná 5% - zbývá spousta strávených hodin při ladění ;-). Proto je zpětná vazba velmi vítána (naproti tomu - nedostatek zpětné vazby - je také skutečností...)

## VI) Revize

1.5.8 - 8th August 2005

- Added DEdgeMask2.

1.5.7

- Added YUY2LUT.

1.5.6

- Corrected chroma handling of YV12LUTxy.

v1.5.5 - 6 November 2004

- Version with binarize working;
  Pentium4 with HT enabled.

v1.5.4 - 14 October 2004

- A lot of filters which were working in place aren't anymore ( because of an AviSynth strangeness which was causing slowdowns ). Before, a filter such as YV12LUT, with U = V = 1, would have had it's chroma left untouched. Now, if you want to preserve the chroma, you have to specify U = V = 2, as it is said in the documentation.

1.5.2 - 1.5.3

- ?

1.5.1

- Complete rewritting of the documentation ( a huge thanks to Wilbert ).
- DEdgeMask now supports a float divisor. However, if the divisor is integer, it *should* be faster.
- DEdgeMask now has back its parameter "setdivisor", but it's only for backward compatibility with some scripts.
- YV12LUTxy : it's a new filter, implementing the idea presented by Didee on the previous post. The "y" symbol has the value of the collocated pixel in the second clip.

1.4.16

- Bugfixes : Logic "min" & "max" modes weren't properly working, it's corrected.
- Bugfixes : Logic & Subtract weren't using MMX & iSSE optimizations, due to a very silly bug. It's Corrected.

1.4.15.3

- RGBLUT added : works the same as YV12LUT ( except R, G and B replace Y, U and V ).
- In addition, you can specify an AMP file ( arbitrary color mapping file format from photoshop ).

1.4.15.2

- Bug finally solved on YV12LUT. Silly programming bug, as always...
- In YV12LUT, logical and relationnal operators added ( <, <=, >, >=, ==, !=, &, !&, |, ° ( xor ) )
- In YV12LUT, a ternary operator added : ? ( works as in C )

1.4.15.1

- In YV12LUT, another bug which was still preventing it from working fine. Hopefully, it should really work now.

1.4.15

- New Filter : HysteresyMask. It will allow you to build a new edge mask from two edge masks, one only having a few edges ( but we're sure they indeed are edges ), the other having two much edges ( due to a too low thresholding for example ). Look in the documentation to have further explanations.

1.4.14.2

- Several bugfixes concerning the behavior of negative values for Y, U and V ( edgemask, dedgemask, motionmask, combmask, logic )
- Several bugfixes concerning the use of offX / offY / w and h ( filters than can use it are : maskedmerge, binarize, expand, YV12subtract, yv12lut )
- In YV12LUT, a bug prevented to use it with some filter. It should work now.
- In YV12Convolution, float coefficients can be used now. If none is used, all the processing will take place with integer, so it will be faster than if you use a float. Moreover, if
  there is the possibility of overflow ( giving a result over 255 or under 0 ) during computation, a slower but safe function will be used to saturate computation to 0 and 255.

1.4.14.1

- Bugfix in YV12LUT to allow the use of negative numbers

1.4.14

- Bugfix : In YV12Layer, a useless test could prevent the filter to work. The test has been removed
- Bugfix : In DEdgeMask, threshold weren't taken into account. They are now
- Bugfix : Logic filter is now fully functionnal, in C and MMX
- Added : documentation to Logic filter
- Added : two modes for Logic : "Min" and "Max" ( C, MMX, iSSE )
- Added : In DEdgeMask, the possibility to set the normalization factor
- Corrected : documentation.

1.4.13

- Bugfix : One more, in the MotionMask ( the last row was not correctly computed )
- Optimizations : MaskedMerge gives now the same output in MMX and C, so MMX optimizations for it are back by default.
- Added : In EdgeMask, you now can use the laplace kernel. See the documentation on that filter
- Added : 'New' filter, DEdgeMask, which allows you to choose your kernel ( at a cost : speed )

1.4.12

- Behavior modifications : MotionMask and EdgeMask now also computes pixels on the borders mainly by extending the mask to these pixels.
- Bugfix : Inflate / Inpand / Expand / Deflate, when using negative parameters for y,u and v, some weird problems could occur.
- Added functionnality : In YV12LUT, the function abs is now defined.

1.4.11

- Bugfix : EdgeMask, MMX optimizations give different results. They are disabled by default. To activate them, use usemmx = true. They'll be used only with mod 16 resolution
- Bugfix : EdgeMask : first and last lines weren't always computed.
- Bugfix : MaskedMerge : MMX optimizations darken slightly the picture. They are disabled by default. To activate them, use usemmx = true. They'll be used only with mod 16 resolution.

1.4.10

- Bugfix : first and last lines were not correctly computed with inflate / deflate
- Invert is no longer a filter of the Masktools, it has been moved inside AviSynth.

1.4.9

- New filter : CombMask. As usual, read further for more documentation

1.4.8

- YV12Convolution now supports negative coefficients in the matrix. It allows to use the filter has an edge detecter.
- YV12Convolution has now a new parameter : bool saturate, which, if set to true, or if there is a possibility of getting out of the range [0..255] during calculation, clips each pixel into that range ( which means it's slightly slower )
- A new filter : LUT. Read further for more information on how to use it.

1.4.7

- Rename MotionDetection to MotionMask. I know it's kind of silly, but it's a lot more logical that way.
- Add the check of the width for the use MMX in MotionMask
- Slightly modify MMX optimizations in Binarize.
- Add a new filter : YV12Convolution. It allows you to convole the picture by a matrix of (almost) any size. Look further in the readme to learn how to use it

1.4.6

- Made the scenechange detection in MotionDetection iSSE optimized ( meaning you need an Athlon XP / Pentium IV ). It works with an Athlon XP, it is not tested with
  an Pentium IV, it is possible to disable it by using usemmx = false in the paremeters of the filter.
- Optimized the calculation of the motion, without using MMX ( just by avoiding to do 3 times the same calculations... ). So the filter should be more or less three times faster.

1.4.5

- Added MotionDetection filter, no MMX / assembler optimizations for it yet. Look further in the Readme to learn how to use it. It takes the idea of Sansgrip's filter (NoMoSmooth) and outputs the motion mask directly in the correct colorspace for the MaskTools.

1.4.4

- Reactivated MMX optimizations for MaskedMerge
- Came back to Kurosu's optimizations for Invert

1.4.3

- Made some MMX optimizations ( binarize, invert )
- Corrected some MMX optimizations ( which means mostly 'disabled some MMX optimizations' ). It should now work with P4.

1.4.2

- Fixed bugs concerning the inpand / expand / inflate / deflate functions

1.4.1

- Fixed the dreadly bug "multiple instances of a filter with different functions needed"

1.4.0

- Added an experimental LUT filter. Not tested, debug later.

1.3.0 (private version)

- Made usable the FitPlane function (still an overload of work when only one plane has to be resized) which was previously undocumented; therefore, added FastFitPlane functions (corresponding FitPlane ones should be useless now, except for the resizers settings)
- Allowed the specification of a processing area for many filters; however, this should not produce any noticable speed increase.
- Cleaned YV12Layer (in particular the unusable "Darken"/"Lighten" modes)
- Added OverlayMask, a function that compares 2 clips, and outputs a mask of the parts that are identical (slow and far from perfect).

1.2.0 (private version)

- YV12Layer: no more useless RGB32 conversion! Approximately the same as Arithmetic (except a third clip is not used), so that one is gone...
- YV12Substract: hey, why only a C version? Masks are really an underused feature of AviSynth |-[

1.1.0 (private version)

- Older inflate/deflate are renamed expand/inpand while newer functions replace them
- Logic and Arithmetic functions added (shouldn't produce the expected results because of no debugging)
- Edgemask now takes 4 thresholds (2 for luma and 2 for chroma). They are used for: setting to 0 or leaving as is a value depending on first threshold, setting to 255 or leaving as is a value depending on the second one.

1.0.2 (last version - public project dropped):

- Fix the shift for edgemask using sobel and roberts (misplaced MMX instruction)
- MaskMerge now works (mask cleared before being used... check with MaskMerge(clip3,clip3) for instance)

1.0.1: Initial release

## VII) Pro vývojáře

Přeskočte na V) jestliže vás nezajímá vývoj dostupných nástrojů.
The project is a VC++ 6 basic project. Each filter has its own folder which stores the header used by the interface, the source for the function members, the source for processing functions and its header. Let's look at EdgeMask:
- EdgeMask.h is included by the interface to know what the filter 'looks like' (but interface.cpp still holds the definition of the calling conventions and exported functions)
- EM_func.h describes the different processing functions (they should all have the same prototype/parameters):
. Line_MMX and Line_C
. Roberts_MMX and Roberts_C
. Sobel_MMX and Sobel_C
- EM_func.cpp, as all <filter's initials>_func.cpp, stores the implementation of the processing functions, and sometimes their MMX equivalents.
- EdgeMask.cpp implements the class; the constructor select the appropriate processing function (MMX? C? Roberts? Line? Sobel?) and uses it to fill the generic protected function pointer used in GetFrame
Interface.cpp stores the export function and all of the calling functions (AVSValue ... Create_<filter>).
ChannelMode.cpp defines the Channel operating modes. There could be added the equivalent of a debugprintf.
This quick walkthrough won't probably help most developers, as the examples of V) for users, but that's the best I've come with so far. It will improve of course over time depending on the success of the idea, which main drawback, speed, will probably make it scarcely used, if ever. <g>

`$English Date: 2005/10/05 18:12:43 $`

`Český překlad:22.2.2009`