版面规则
提问时请注意:尽量详细描述操作过程、AVS脚本内容等,最好能写出片名,只贴图有时无法看出问题原因。
提示:发布原创内容请尽量使用附件上传。使用网盘会出现过期失效的问题,请注意。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

10. mask處理函數——hysteresis、logic、invert、binarize

首先來看mt_hysteresis(small_mask, big_mask)。這個函數是取一個small mask與一個big mask,對於一整塊在big mask裡連通的區域,看small mask裡是否有點位於這個區域內,如果有的話就保留這個區域,如果沒有的話,認為這個區域的big mask是無效的(可能因為噪點等各種原因誤判的部分)。讓我們看一個實例:[syntax lang="avisynth"]
small = mt_edge("roberts", chroma="128")
big = mt_edge("hprewitt", chroma="128")
mt_hysteresis(small, big, chroma="128")[/syntax]
這裡我們希望邊緣既有hprewitt的覆蓋面,又能像roberts那樣盡量減小噪點的干擾,於是對於roberts檢測裡不包含的部分直接從hprewitt中去除,從而得到一個robustness更高的廣域邊緣部分。效果如圖示:
图片

图片

图片

接下來是mt_logic(clip1, clip2, string "mode", int "th1", int "th2")。這是一個對clip1與clip2進行邏輯運算的函數。它支持6個mode,分別是:
mode
= "and",按位與運算,例: 11 & 5 = 1011 & 101 = 1
= "or",按位或運算,例: 11 | 5 = 1011 | 101 = 1111 = 15
= "xor",按位異或運算,例: 11 ^ 5 = 1011 ^ 101 = 1110 = 14
= "andn",按位與非運算,例: 11 & ~5 = 1011 & ~101 = 1011 & 11111010 = 1010 = 10
= "min",取最小值,即 min(clip1+th1, clip2+th2)
= "max",取最大值,即 max(clip1+th1, clip2+th2)
例如前面的[syntax lang="avisynth"]
temporal_bright = src.mt_lutxy(back_compensate, "x y max").mt_lutxy(forw_compensate, "x y max")
temporal_dark = src.mt_lutxy(back_compensate, "x y min").mt_lutxy(forw_compensate, "x y min")[/syntax]
就相當於[syntax lang="avisynth"]
temporal_bright = src.mt_logic(back_compensate, "max").mt_logic(forw_compensate, "max")
temporal_dark = src.mt_logic(back_compensate, "min").mt_logic(forw_compensate, "min")[/syntax]
如果我們想做一個luma自適應的deband,按照luma高時使用src,luma低時使用debanded,同時用edge mask來保護edge的話,可以用mt_logic來組合這個mask:[syntax lang="avisynth"]
edge_mask = src.mt_edge(thY2=255).mt_lut("x 1.2 ^")
luma_mask = src.RemoveGrain(20, -1).mt_lut("x 16 - 255 * 219 /") # 擴張到PC range以填滿0-255
final_mask = mt_logic(edge_mask, luma_mask, "max")
mt_merge(f3kdb, src, final_mask, luma=true)[/syntax]
這裡的f_mask就包含了edge mask與luma mask的最大值,從而對不需要做deband的亮區與線條都做了保護。

mt_invert,這是一個非常簡單的函數,相當於mt_lut("255 x -"),即每個像素直接取255-x,得到一個與原始畫面色彩顛倒的結果。如果用在mask上,就是將mask黑白顛倒過來,例如
mt_merge(a, b, mask, U=3, V=3)就相當於mt_merge(b, a, mask.mt_invert, U=3, V=3)

mt_binarize(clip c, int "threshold", bool "upper", string "mode")
直接將值域為[0, 255]的mask轉為二值mask的函數。例如前面的mt_edge(thY1=10, thY2=10, thC1=10, thC2=10, U=3, V=3)就相當於mt_edge(thY1=0, thY2=255, thC1=0, thC2=255, U=3, V=3).mt_binarize(threshold=10, U=3, V=3),將高於10的像素全部變成255,而低於10的像素全部變成0
上次由 06_taro 在 2012-08-02 17:42,总共编辑 2 次。
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

11. convolution及其他mask處理技巧

mt_convolution(clip c, string "horizontal", string "vertical", bool "saturate", float "total")是一個convolution filter,你可以用mt_convolution("1 6 1", "1 6 1")進行一次簡單的blur,也可以用mt_convolution("1 -6 1", "1 -6 1")進行一次低質量的sharpen。當然用作一般用途這個函數並不合適,但是如果是要對mask或者diff進行一些粗糙的處理的話,這是一個較為快速的方法。convolution是對鄰域內像素按照kernel做一次線性組合當作最終的像素值,具體理論可以按查閱圖像處理裡convolution的相關資料。

mt_mappedblur(clip c, clip map, string "kernel", string "mode")是另一個convolution用的函數。與mt_convolution不同的是,它將horizontal與vertical兩個kernel參數合併為一個kernel,例如用kernel="1 2 1 2 8 2 1 2 1"進行一次簡單的blur。另外,mt_mappedblur需要一個map clip,在convolution過程中,如果像素變化超過map clip的話,則使用中心像素替代它的值(mode="replace"時)/完全不考慮這個像素(mode="dump"時)。這種機制比較特殊,雖然並非沒有用,不過我個人還很少見到有實際使用這種方式進行convolution的…

在實際mask的處理當中,雖然對mask進行一定的blur增強其穩定性非常常見,不過我們通常很少用mt_convolution或者mt_mappedblur來完成這個任務。相比之下,RemoveGrain與mt_lut更加常見。RemoveGrain有著非常快的處理速度,而且它內部包含了大量的3x3的kernel,可以適應大部分我們需要的處理。而mt_lut則常常用於對mask進行一些數值上的處理,例如用mt_lut("x 32 > x 1.4 ^ 0 ?")這種方式將mask中值在32以內的點都去除,以降低mask中不穩定的部分,而對值在32以上的有效部分做一次1.4次方的處理(最低的32被提升到128,而53或以上的值被提升到255)。

多個mask過程常常可以合併,以減少重複計算,提高整體速度。例如對一個視頻我們需要對線條做anti-aliasing,需要對線條邊緣做dehalo,需要對非線條的暗場進行deband,而非線條的亮場略微進行一次spatial denoise,對非動態部分進行一次temporal stabilize,同時還想對動態部分被motion blur之後的線條稍微做一點銳化,我們只需要edge、luma與motion三個mask為核心做這樣的處理:[syntax lang="avisynth"]
m_edge = mt_edge("sobel", 7, 20).mt_inflate
zero_l = 64 # 最容易出banding的其實不是luma=0的暗場,而是Y在64附近的區域,因此將64設定為luma mask裡的0值,向上下遞增
m_luma = mt_lut("x "+String(zero_l)+" - Abs 255 * "+String(zero_l)+" 128 - Abs 128 + /")
# Abs(x-zero_l)*255 / (Abs(zero_l-128)+128)
m_motn = mt_motion

m_aa = m_edge.mt_expand
m_halo = m_aa.mt_expand.mt_lutxy(m_edge, "x y -")
m_fin = mt_logic(m_edge, m_motn, "max")

aa_clp = AAA
dh_clp = aa_clp.Dehalo_alpha
db_clp = f3kdb
nr_clp = dfttest(tbsize=1)

flat = mt_merge(db_clp, nr_clp, m_luma, luma=true)
non_hl = mt_merge(flat, aa_clp, m_aa)
spat = mt_merge(non_hl, dh_clp, m_halo)

stab = spat.TTempSmoothF
sharp = spat.Sharpen
temp = mt_merge(stab, sharp, m_fin)[/syntax]
這樣一個edge mask被使用了多次,一個luma mask和motion mask也分別用於兩個處理,大大減少了對每一個處理單獨mask的開銷。

mask的處理中,mt_expand/mt_inpand/mt_inflate/mt_deflate是非常重要的函數,根據鄰域像素進行的擴張/收縮對於一個未處理的核心mask作用範圍的控制最主要就是依靠這四個函數來快速處理,一般來說只有在比較特殊的情況下我們才會考慮使用複雜的mt_luts(x)。

mask的處理根據需求不同,有大量不同的用法,在應用中才能積累出大量經驗。在這裡我就不多講經驗性的東西了,希望各位能在自己的使用中多多體會。
上次由 06_taro 在 2012-06-22 7:32,总共编辑 1 次。
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

12. 輔助函數——鄰域字符串生成工具

最後,對於鄰域範圍的定義,我們之前只使用了mt_square這個函數來建立一個描述鄰域內3x3的部分,還有一次用到了"-1 -1 -1 0 -1 1 0 -1 0 1 1 -1 1 0 1 1"來描述in/deflate的鄰域範圍。現在來介紹一下這個鄰域像素的定義方式,以及masktools提供的其他預設好的描述鄰域範圍的函數。

先來看上面這個"-1 -1 -1 0 -1 1 0 -1 0 1 1 -1 1 0 1 1",它實際上是鄰域點相對於中心像素的坐標位置。我們將數組裡的值按兩個一組來劃分:
(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)
中心像素的坐標為(0, 0),所以上面這八組描述的就是中心像素周圍3x3的方塊內不包含中心像素自身的8個像素:

代码: 全选

(-1, -1), (0, -1), (1, -1)
(-1,  0),          (1,  0)
(-1,  1), (0,  1), (1,  1)
這就是鄰域像素點的定義模式。在mt_luts(x)裡的pixels與mt_ex/inpand裡的mode參數都是用這樣的相對坐標數組字符串來定義鄰域像素範圍的。

masktools預設了9個用於生成相對坐標數組用的模板函數:
mt_square(int "radius", bool "zero")
生成描述以中心像素為中心,邊長為2*radius+1的正方形的字符串。
mt_rectangle(int "hor_radius", int "ver_radius", bool "zero")
生成描述以中心像素為中心,水平邊長為2*hor_radius+1,垂直邊長為2*ver_radius+1的矩形的字符串。
mt_freerectangle(int "top_x", int "top_y", int "bottom_x", int "bottom_y", bool "zero")
生成描述任意相對坐標的,位置為從(top_x, top_y)到(bottom_x, bottom_y)範圍的矩形的字符串。

mt_diamond(int "radius", bool "zero")
生成描述以中心像素為中心,對角線長為2*radius+1的正菱形的字符串。
mt_losange(int "hor_radius", int "ver_radius", bool "zero")
生成描述以中心像素為中心,水平對角線長為2*hor_radius+1,垂直對角線長為2*ver_radius+1的菱形的字符串。
mt_freelosange(int "top_x", int "top_y", int "bottom_x", int "bottom_y", bool "zero")
生成描述任意相對坐標的,位置在(top_x, top_y)到(bottom_x, bottom_y)範圍的菱形(四個頂點為這個矩形範圍的各邊中點)的字符串。

mt_circle(int "radius", bool "zero")
生成描述以中心像素為圓心,半徑為radius的圓形的字符串。
mt_ellipse(int "hor_radius", int "ver_radius", bool "zero")
生成描述以中心像素為圓心,水平軸半徑為hot_radius,垂直軸半徑為ver_radius的橢圓形的字符串。
mt_freeellipse(int "top_x", int "top_y", int "bottom_x", int "bottom_y", bool "zero")
生成描述任意相對坐標的,位置在(top_x, top_y)到(bottom_x, bottom_y)範圍內橢圓形(與這個矩形範圍的四條邊相切)的字符串。

每個函數最後的bool "zero"參數表示的是十分包含(0, 0)這個中心像素,zero=true時包含,否則不包含。例如,前面的
"-1 -1 -1 0 -1 1 0 -1 0 1 1 -1 1 0 1 1"
可以寫作mt_square(1, zero=false),也可以寫作mt_rectangle(1, 1, zero=false),還可以寫作mt_freerectangle(-1, -1, 1, 1, zero=false)

讓我們來試著用這些函數做一些圖形看看:[syntax lang="avisynth"]
BlankClip(width=200, height=200, pixel_type="YV12")

mt_lutspa(expr="x 0.5 == y 0.5 == 255 0 ? 0 ?")
# 設定整個畫面中心的像素值爲255,其餘像素值爲0

ellipse = mt_lutxy(mt_expand(mode=mt_circle(85)), /* 最外邊的正圓 */
\ mt_expand(mode=mt_ellipse(85, 60)), /* 內切的橢圓 */
\ "x y -")

rect_los = mt_lutxy(mt_expand(mode=mt_freerectangle(-60, -40, 60, 40)), /* 內接的矩形 */
\ mt_expand(mode=mt_losange(60, 40)), /* 最裏邊的菱形 */
\ "x y -")

mt_lutxy(ellipse, rect_los, "x y +", chroma="128")[/syntax]
結果如圖所示:
图片

到這裡我們已經把masktools裡所有的函數都介紹完畢了,相信如果掌握了這裡所有的用法,應該已經可以完全了解mask、mt_lut、make/adddiff等核心函數的用途,以及mask的創建、處理、使用的過程,masktools對於數字圖像處理中專業性的知識要求僅集中在mt_edge、mt_lut、mt_convolution等少數函數中,而即使不具備這些知識,一般也能進行很多有效的處理。在使用過程中多熟悉各種函數的用法,在看別人的腳本過程中多注意masktools的應用,都會對masktools的掌握有所幫助。

本教程只涵蓋了最基礎的masktools的用法,但是配合官方文檔的說明,相信通過這些知識已經可以進階地練習一些中高級的應用,例如通過recursive的crop+mt_lut實現一個即可以像lut一樣使用像素值,也可以靠recursion過程傳遞過來的width/height參數像mt_lutspa一樣使用像素坐標,從而更加完善的mt_lutxspa等。希望大家能夠更好地挖掘masktools的可能性,在avs的視頻處理過程中取得更好的效果。
上次由 06_taro 在 2012-08-22 16:39,总共编辑 7 次。
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

Re: 暫勿回复

Changelog:

2012.08.02
三處腳本錯誤修正,感謝Holy指出。果然順手寫出來不經檢查的東西一堆typo…

2012.08.01
5. 基於mt_lut的強大工具——make/adddiff部分修復第一個腳本例子裡漏的一個問號,感謝james1201指出

2012.07.09
1. 了解Masktools部分修正,Overlay內部處理不是在RGB下,而是在YUV 4:4:4下。說它內部RGB處理是我自己之前理解錯誤,在此對之前受誤導的表示歉意。感謝SAPikachu巨巨指正。
12. 輔助函數——鄰域字符串生成工具部分的例子添加代碼註釋。之前寫這段的時候忘了加註釋了…

2012.06.23
4. 深入淺出mt_lut(xy(z))部分增加對OP/ED進行AA時,利用credit mask,只處理背景畫面,而不影響credit的例子。
上次由 06_taro 在 2012-08-02 17:45,总共编辑 7 次。
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

Re: 暫勿回复

佔樓備用~
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

Re: 暫勿回复

其實我想把前兩頁都佔滿…
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

Re: 暫勿回复

不過估計用不到那麼多備用的…
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
06_taro
核心会员
核心会员
帖子: 998
注册时间: 2010-09-22 18:32
来自: United Kingdom
联系: 网站

Re: 暫勿回复

所以就到此為止~
つまんねー事聞くなよ!

I, personally, for me, believe (obviously sometimes) that my OS choice is right. That's me. I'm not telling you that you should believe it. Learn the facts, and the origins behind the facts, and make up your own damn mind. That's why you have one. (source)

Follow me: @06_taro

304——
为纪念伟大的宇宙史上最强压制304先生,联合国教科文组织决定,将每年的第304天,即平年的10月31日或者闰年的10月30日,定为世界304日。
头像
yabbay
帖子: 62
注册时间: 2012-05-31 10:39
来自: Tokyo

Re: 【教程】 MaskTools入門教程

このポストは人類の知恵の結晶でありんす
経験値急上昇の予感でありんす
さっそくipadに導入してじっくりがっくりと拝読させていただくでありんす {:cat_16}
          .∧__,,∧
         ( ´・ω・`) ブルブル
          (つまくら) アリと明日(ant and tomorrow)
          `u―u´ レッツ・エッグ・ペイン(Let`s egg pain)
头像
ikamusume
帖子: 77
注册时间: 2011-03-02 23:13

Re: 【教程】 MaskTools入門教程

{:cat_11} 好帖留名 {:cat_17}

回到 “AviSynth”