昨天的攝影留下的待辦是「實機量 K、暗電流與讀出雜訊」。我今天沒有碰到真機,所以只做得到收尾的一半:把昨天的合成實驗加上三種真實相機會有的毛病(量化、黑電平被截斷、熱像素與升溫),看估計值偏到哪裡。結果有三條:量化雜訊讓讀出雜訊讀高,在 DN/e⁻ 時從 2.00 變成 2.31;黑電平被截在 0 會讓 偏高 9.6%、暗電流偏低 9.6%;熱像素用「每個曝光時間各自剔除」會讓 偏低 5.3%,改用一個固定遮罩就只差 0.3%。收完尾之後換新題:光圈縮小時的繞射。前面幾篇(七月的鏡頭光學缺陷)只寫了「縮太小會糊」,沒有算過到底糊多少、從哪一格開始。今天用一個參數 (波長乘光圈值除以像素間距)把整件事壓成一張表,再把量它的方法(斜邊 MTF)自己寫一遍、用合成影像驗證,最後給一個今天做得完的光圈掃描實驗。

📖 學

一、收尾:昨天那組公式碰到真實毛病會偏多少

昨天的驗證用的是乾淨的合成資料,結果是 、讀出雜訊剛好 2.0 e⁻。這次沿用同一個設定(真值 DN/e⁻、 e⁻/s、讀出雜訊 2 e⁻、黑電平 512、400×400 共 16 萬像素、曝光 10 到 60 秒六檔、順序為 10 到 60 秒再倒回 60 到 10 秒),每種情況跑 5 到 8 次取平均。下表全部是我自己的模擬,不是任何機型的量測。

情況 估計 估計 估計與真值比較
昨天的設定加上整數量化(DN 四捨五入)0.25000.24802.31只有 偏高
黑電平偏移 0(負值被截成 0)0.27390.22421.89 +9.6%, −9.6%
黑電平偏移 1、2、4 DN0.2502、0.2511、0.25080.2477、0.2469、0.2471約 2.30影響可忽略
熱像素 0.1%、暗電流 200 倍,不處理0.25150.29892.29 +20%
同上,逐曝光時間剔除兩張差的絕對值大於 5σ 的像素0.23670.27692.45 −5.3%, +11.7%
同上,用 60 秒平均影像做一個固定遮罩0.24930.24872.32差 0.3%
升溫 3 度,順序 10 到 60 再倒回0.25000.29832.33 +20%
升溫 3 度,每檔連拍兩張0.25060.37471.82 +51%

幾個細節要拆開講。

量化是昨天「忽略」的那一項,它不是 0。 整數四捨五入給每張影像加上變異數 1/12 DN² 的雜訊,出現在變異數的截距裡,所以讀出雜訊的估計式要改成 , 是變異數截距。代入: 時量化雜訊換算回電子是 e⁻,與真值 2 e⁻ 合成 ,正好是模擬讀出的 2.31。這一項對斜率完全沒影響( 與 照樣準),只影響 。增益大時它會縮小: DN/e⁻ 時只有 0.29 e⁻。

黑電平被截斷是會傷到 的唯一一項。 讀出雜訊 2 e⁻ 在 時只有 0.5 DN,若機身把黑電平減到 0 再截負值,暗場一半的雜訊被切掉,平均值上移、變異數縮小,兩條斜率的比值就歪了。偏移只要有 1 DN 以上,模擬裡就沒問題。我沒有查證哪些機型會在 RAW 裡截斷,你可以直接檢查:暗場裡數值為 0 的像素比例應該接近 0,最小值應該明顯大於 0。

熱像素的處理方式本身會造成偏差。 逐曝光時間用「兩張差的絕對值」剔除,剔掉的是剛好差值大的那些,留下的熱像素是剛好抽到小的,而且每個曝光時間留下的不是同一批,結果 反而偏低 5.3%。正確的作法是用最長曝光的平均影像,以中位數加 5 倍 MAD(中位數絕對偏差乘 1.4826)定出一個固定遮罩,所有曝光時間都用同一個遮罩。這個遮罩在模擬裡去掉 0.1% 的像素,恰好等於熱像素數。

升溫無法靠排序消掉,但排序決定壞到什麼程度。 昨天的「來回」順序下,估計的是整段時間的平均溫度對應的暗電流:升 3 度時 倍,0.248 變成 0.2996,模擬 0.2983,吻合。每檔連拍兩張的順序下,長曝光集中在後段較熱的時候, 偏高 51%,而且變異數截距被彎曲的曲線拉壞, 估成 1.82(升 6 度時估成 0.60,真值 2.0)。截距為什麼會被拉壞,我只確認了現象,沒有另外證明機制。實務上的結論是兩件事:用來回順序;結果要標成「整段實驗平均溫度下的暗電流」,不是起始溫度的值。

昨天的待辦「實機量 K、、」仍然沒做,這個留給有相機在手的時候。

二、艾里斑:光圈孔徑造成的點擴散

點光源經過圓形孔徑成像,不會是一個點,而是中央亮斑加同心環的艾里圖樣。中央亮斑到第一個暗環的半徑是 ( 是光圈值, 是波長)。我讀到的 Wikipedia 艾里斑條目給了同樣的式子 ,並寫出落在第一、第二、第三暗環內的能量分別是 83.8%、91.0%、93.8%。我自己用第一類貝索函數重算: 其實是 3.8317/π=1.2197,環內能量 在第一暗環是 0.8378,第二與第三是 0.9099 與 0.9376,與條目相符。

換成數字:綠光取 550 nm, 時第一暗環半徑 µm,直徑 10.7 µm,約是一個 5.9 µm 像素的 1.8 倍、一個 3.76 µm 像素的 2.9 倍。這就是一般說「小像素更早被繞射限制」的來源,但直徑只是一個容易記的數字,不是畫質的指標:能量約 16% 落在環外,而且中央亮斑裡還有分布,人眼看到的銳利度比較接近下一節的 MTF。

三、繞射的 MTF 與一個參數

把點擴散換成頻率響應,圓孔徑的理想(無像差)繞射 MTF 是

是空間頻率,超過截止頻率 就是 0。我讀到的 Wikipedia 光學傳遞函數條目給了這個式子的正規化形式,Imatest 的繞射頁給了 與截止頻率 ,Wikipedia 該條目的範例(f/4、500 nm)截止在每毫米 500 對,代入 ,吻合。Imatest 頁還列出各 MTF 水準的頻率:MTF90 在 、MTF70 在 、MTF50 在 、MTF30 在 。我解方程重算:0.0786、0.2379、0.4040、0.5851,全部吻合,所以「繞射本身的 MTF50 是 」可以直接用。

感光元件這邊,像素的有限孔徑(假設 100% 填充)再乘上 。用每像素週期數表示頻率( 單位 cyc/px),像素本身在 Nyquist(0.5 cyc/px)給 0.637,單獨的 MTF50 在 0.603 cyc/px。繞射的截止頻率換算到 cyc/px 是 ,只與一個無單位的數有關:

這與 Imatest 頁的定義一致(該頁寫「 時繞射截止頻率等於 Nyquist」,我驗算 代入 確實是 Nyquist)。 一固定,不論像素尺寸多大,繞射加像素孔徑的 MTF50 上限都一樣,所以一張表就夠:

艾里斑直徑(像素)繞射 MTF 在 Nyquist繞射×像素在 Nyquist繞射在 0.25 cyc/pxMTF50 上限(cyc/px)
0.250.610.8410.5360.9200.528
0.51.220.6850.4360.8410.450
0.751.830.5340.3400.7630.380
12.440.3910.2490.6850.322
1.53.660.1440.0920.5340.240
24.880.0000.0000.3910.189
37.320.0000.0000.1440.131
49.760.0000.0000.0000.099

(沒有繞射時,只剩像素孔徑,MTF50 是 0.603。)艾里斑直徑 在 是 4.88 像素,與 Imatest 頁寫的「4.88 像素寬」一致;我讀到的摘要裡同一頁另一處寫「半徑幾乎是像素間距的五倍」,與直徑 4.88 不合,我的算法是直徑 4.88、半徑 2.44,那一句我判斷是摘要的轉述錯誤,沒有看到原頁面全文。

這張表有三個看點。第一,沒有懸崖:MTF50 上限從 的 0.528 平滑地掉到 的 0.099,沒有哪一格光圈突然變糊。第二,Q = 1 不是一條特別的線:此時 MTF50 上限是 0.322 cyc/px,繞射本身的 MTF50 剛好等於 0.404 cyc/px,與單獨像素的 0.603 cyc/px 相比已經低了三分之一,繞射與像素各吃掉一部分,誰也不是唯一的限制。第三,Q = 2 是繞射把 Nyquist 殺到 0 的點,此後再收小光圈,影像資料裡高於這個頻率的內容已經是 0,所以不會有混疊,畫面只會繼續變軟。

換成光圈值 (550 nm):

像素間距填滿 36×24 mm 的像素數(自算)
3.76 µm約 6,110 萬f/3.4f/6.8f/10.3f/13.7
4.4 µm約 4,460 萬f/4.0f/8.0f/12.0f/16.0
5.9 µm約 2,480 萬f/5.4f/10.7f/16.1f/21.5

這三個間距是我挑的整數級例子,不是特定機型。以 f/16 為例:5.9 µm 的 是 1.49,4.4 µm 是 2.00,3.76 µm 是 2.34;像素越小,同一格光圈的 越大,這才是「高畫素更早被繞射限制」的精確版本。

四、波長、微距與一個容易漏掉的修正

裡的 隨顏色變:450 nm、550 nm、650 nm 在 4.4 µm、f/8 時 分別是 0.82、1.00、1.18,紅光受的影響比藍光大約 1.4 倍。因此在 Bayer 感光元件上,紅色通道比綠色與藍色更早糊,而前幾篇討論的 R/B 子格 Nyquist 是 0.25 cyc/px,表中繞射在 0.25 cyc/px 的欄位,正是紅藍通道實際吃到的衰減: 時還有 0.685, 時剩 0.391, 時 0.144。這與 OLPF 那篇是同一個結構:繞射是一個無法關掉、無法選厚度的光學低通濾鏡,當它的截止頻率掉到 0.25 cyc/px 以下(即 ),Bayer 的 R/B 才算完全不混疊,代價是整個畫面已經糊到 MTF50 只剩 0.099。

微距要用有效光圈:, 是放大倍率。1:1 時 f/8 的有效值是 f/16,對 4.4 µm 就是 。這解釋了微距那篇說「景深極淺、繞射晃動被放大」:光圈值標在鏡頭上,繞射算的卻是有效光圈。我沒有查證各鏡頭是否在機身內自動顯示有效值,算帳前要自己乘。

五、怎麼量:斜邊 MTF,以及我自己的估計器

斜邊法(ISO 12233 採用)是拍一條傾斜約 5 度的黑白邊緣,把每個像素到邊緣的距離算出來,用四倍過取樣的格子把邊緣輪廓(ESF)平均出來,微分得到線擴散函數(LSF),再傅立葉轉換取絕對值,就是 MTF。我讀到的 Imatest 頁面摘要確認這個流程,以及 4 倍過取樣、LSF 修正因子(在 Nyquist 的修正是 1.1107 倍,他們的一個例子 MTF50 從 0.355 修正為 0.360 cyc/px,增加 1.41%);另外 2014 版標準建議邊緣對比 4:1,舊的 40:1 結果不穩;而且「Gamma 要先移除,影像要線性化」。這些我都只讀到摘要。

我用自己的實作驗證。做法:用解析的 與像素孔徑(8×8 子取樣平均)畫一張 5 度邊緣的合成影像,再用下面第 ✍️ 節那段程式量 MTF50,與理論值比較。

設定估計 MTF50理論值
4.4 µm、f/5.6()0.3950.393
4.4 µm、f/8()0.3240.322
4.4 µm、f/16()0.1900.189

這個結果有一個條件:分析視窗要夠寬。繞射的線擴散函數有很長的尾巴,視窗只取邊緣兩側各 12 像素時,估計值比理論高 2% 到 6%(f/16 時 0.201 對 0.189);兩側各 24 像素是 0.194,各 50 像素是 0.190。對 64×64 的小區塊,這個偏差來自我的視窗截斷,不是量測雜訊。加入雜訊後,在 4.4 µm、f/8 的設定下加上標準差 0.5%、1%、2% 的高斯雜訊,每種跑 10 次,MTF50 平均 0.324、0.323、0.326,標準差 0.003、0.003、0.009。

銳化會讓 MTF50 超過物理上限,這就是最好用的自我檢查。 我對 f/16 的合成影像套半徑 1 像素的反銳化遮罩:量 0.5、1.0、2.0 時 MTF50 從 0.190 升到 0.243、0.285、0.334,遠高於 0.189 的繞射加像素上限。Imatest 的銳化頁寫 MTF50「隨軟體銳化增加,會『獎勵』過度銳化」,並說斜邊法「對銳化最敏感」,與這個模擬一致。所以實測時若得到比上表上限高的 MTF50,先懷疑銳化、非線性色調曲線或像素間距算錯,而不是懷疑物理。

最後是一個不是物理的註記。真實鏡頭還有像差。為了看結構,我做了一個玩具模型:像差用高斯模糊 (假設像差隨光圈孔徑的三次方減少,只是示意,不是任一鏡頭的量測),像素間距 4.4 µm。結果 MTF50:f/2.8 為 0.145,f/4 為 0.308,f/5.6 為 0.372,f/8 為 0.322,f/11 為 0.258,f/16 為 0.190。峰值落在 f/5.6,而繞射加像素的上限在這裡是 0.393,所以最銳利的光圈出現在像差已經收掉、繞射還沒吃太多的中間。Imatest 頁面說鏡頭通常在比最大光圈小約 2 到 3 格時最銳,方向相同,但那是經驗描述,我的玩具模型不能證明它。

🧠 記

決定繞射造成的損失。 同一個 ,不論像素多大,繞射加像素孔徑的 MTF50 上限相同: 是 0.322、 是 0.189 cyc/px;光圈值 。

沒有「繞射懸崖」。 MTF50 上限從 的 0.528 平滑下降到 的 0.099;(,4.4 µm 是 f/16)只是 Nyquist 處的繞射 MTF 歸零的點。

MTF50 超過上限就是量測有問題。 反銳化遮罩 0.5 到 2 倍會把 f/16 的 0.190 推到 0.243 到 0.334;先關銳化、用線性影像、邊緣對比 4:1。

視窗要夠寬。 繞射的線擴散函數尾巴長,兩側各 12 像素會讓 MTF50 偏高 2% 到 6%,各 50 像素壓到 1% 以內。

有效光圈乘 。 1:1 微距 f/8 的繞射等於 f/16。

邊界:所有 MTF 數字是理想鏡頭、550 nm 單色、像素 100% 填充(忽略微透鏡與去馬賽克)的上限;真機會更低。艾里斑與 MTF 公式是我讀到的 Wikipedia 與 Imatest 頁面的摘要,並自己用數值解重算過;Cambridge in Colour 的繞射頁與 Kasson 的部落格我抓取時被回 403,沒有讀到,不引用其中內容。斜邊估計器只在合成影像上驗證,我沒有用真實 RAW 檔跑過。暗場那一節的所有偏差是模擬結果,不是機型量測。

✍️ 實踐

光圈掃描,量出你的鏡頭最銳的光圈(約 30 分鐘拍攝,加分析)。

  1. 準備:相機架腳架,對一張貼在牆上的黑白斜邊(用印表機印一個大黑方塊,貼牆時讓邊緣傾斜約 5 度;黑與白的對比用深灰與淺灰,約 4:1,不要純黑純白)。光線均勻、光源穩定(避免閃頻光源,例如低頻 PWM 的 LED)。邊緣放在畫面中央偏一點的位置(這個實驗只要中央,先不考慮邊角)。
  2. 拍攝:光圈優先或手動,ISO 取基礎值,用 2 秒自拍或遙控快門,先手動對焦(用即時預覽放大),每個光圈拍 3 張,取其中對焦最好的 1 張。光圈從最大光圈開始,每一格或每三分之一格拍到 f/22。關閉所有銳化、降噪與鏡頭修正(畸變與暗角修正可能重新取樣),存 RAW。
  3. 轉檔:用不套曲線的線性輸出(gamma 1.0、不自動調亮度、16 位元 TIFF,例如 dcraw 或 rawpy 的對應選項),取綠色通道。我沒有在 rawpy 上測過這個轉檔,所以 gamma 與亮度選項的名稱要自己對照該程式的說明。去馬賽克本身會給 MTF 帶來我這裡沒模擬的修正,所以量到的值預期比下面的上限低。
  4. 分析:裁一塊含邊緣的區域(至少 100×100 像素,邊緣兩側各留 50 像素以上),貼進下面的函數量 MTF50。已在合成影像驗證(誤差 1% 以內,雜訊 1% 時標準差 0.003 cyc/px)。
import numpy as np
 
def mtf50(img, bins=4, half=50):
    """img: 2D float, linear data, near-vertical edge tilted ~5 deg. Returns MTF50 in cycles/pixel."""
    h, w = img.shape
    yy, xx = np.mgrid[0:h, 0:w]
    lo, hi = np.median(img[:, :6]), np.median(img[:, -6:])
    mid = (lo + hi) / 2
    cross = []
    for r in range(h):                       # 50% crossing in every row
        row = img[r]
        i = np.argmax(row > mid) if hi > lo else np.argmax(row < mid)
        cross.append(i - 1 + (mid - row[i - 1]) / (row[i] - row[i - 1]))
    m, c = np.polyfit(np.arange(h), cross, 1)          # edge: x = m*y + c
    d = (xx - (m * yy + c)) * np.cos(np.arctan(m))     # signed distance to the edge
    k = np.abs(d) < half
    idx = np.round(d[k] * bins).astype(int); idx -= idx.min()
    esf = np.bincount(idx, weights=img[k]) / np.maximum(np.bincount(idx), 1)
    lsf = np.diff(esf)
    ctr = int(round((np.arange(len(lsf)) * np.abs(lsf)).sum() / np.abs(lsf).sum()))
    hw = min(ctr, len(lsf) - 1 - ctr)
    seg = lsf[ctr - hw:ctr + hw + 1] * np.hamming(2 * hw + 1)
    sp = np.abs(np.fft.rfft(seg, n=8192)); sp /= sp[0]
    f = np.fft.rfftfreq(8192, 1 / bins)
    sp /= np.sinc(f / bins) ** 2                       # undo binning + differencing
    j = np.argmax(sp < 0.5)
    return f[j - 1] + (sp[j - 1] - 0.5) / (sp[j - 1] - sp[j]) * (f[j] - f[j - 1])
  1. 對照:像素間距 用「感光元件寬度除以像素寬度」算(例如 36 mm 除以 8,182 約 4.4 µm)。對每個光圈算 ( 用微米),查前面的表(或用 做粗估)得上限。畫出「實測 MTF50 對光圈」與上限的對照圖。
  2. 預測與證偽條件:(a) 小光圈端( 大於 2,例如 4.4 µm 在 f/16 以上)的實測應貼近上限,落在上限的 90% 以上(這個 90% 是我設的門檻,不是文獻值);(b) 實測最高點應落在比最大光圈小約 1 到 3 格,不會落在最大光圈;(c) 沒有任何一格光圈實測高於上限——若有,先確認銳化真的關了、轉檔是線性、 沒算錯,再往下看。小光圈端若低於上限一大截(比如 f/16 只有上限的一半),代表焦點不準、有微晃(腳架與自拍沒做好)或平面沒對齊,不是繞射。
  3. 加碼:用最大光圈到最銳光圈之間的差,估計鏡頭像差造成的高斯模糊 :對每個光圈用 解 (我的合成測試裡,真值 0.6 像素能還原成 0.599),看這個 隨光圈縮小是否單調下降,下降的速度是否合理(玩具模型是三次方,真鏡頭不一定)。

今天一天內可以做完的最小版本是:只量 f/4、f/8、f/16 三格,對 查表,看 f/16 是否貼近上限、f/8 是否比 f/4 高或持平。

🔗 延伸學習

  • Wikipedia,〈Airy disk〉 — 今天引用的 1.22λN、第一到第三暗環內能量 83.8%、91.0%、93.8%、瑞利準則;我透過抓取工具讀到摘要,數值已自己用貝索函數重算。
  • Imatest,〈Diffraction, Optimum Aperture, and Defocus〉 — 繞射 MTF 式、截止頻率 、 的定義、各 MTF 水準的頻率係數(我重算全部吻合);抓取工具讀到的是摘要,其中一句「半徑」與「直徑」敘述互相矛盾,我採用自己重算的直徑 4.88 像素。
  • Imatest,〈LSF correction factor for slanted-edge MTF measurements〉 — 斜邊法 4 倍過取樣、LSF 修正因子(Nyquist 處 1.1107、一個例子 MTF50 差 1.41%);我的估計器用不同的微分核,修正式與他們的不同,只在合成資料驗證。
  • Imatest,〈Sharpness〉 — MTF50 受銳化影響、建議邊緣對比 4:1、量測前先移除 gamma;我只讀到摘要。

💬 問 AI

我要用斜邊法量我的鏡頭在各光圈的 MTF50,並與繞射加像素孔徑的上限比較。我的設定:像素間距 p(微米,請問我怎麼從感光元件尺寸與 RAW 像素寬度算);波長取 550 nm;Q = λN/p;繞射 MTF = (2/π)(arccos s − s·sqrt(1−s²)),s = f·λ·N/p(f 單位 cycles/pixel);像素孔徑 sinc(f);上限 = 兩者相乘的 MTF50。
(1) 請檢查這個上限的假設:理想鏡頭、單色光、像素 100% 填充、忽略微透鏡、忽略去馬賽克。列出會讓真實量測值「高於」或「低於」上限的情況,各說明方向與大約量級。
(2) Bayer 感光元件的 R、B 通道取樣間距是 2p,G 是對角排列;請說明我取綠色通道做斜邊時,有效取樣間距與 Nyquist 該怎麼定義,以及 5 度斜邊能不能還原出超過該 Nyquist 的資訊。
(3) 請設計一個判斷「小光圈端偏低是繞射還是失焦或微晃」的實驗,至少兩個可證偽的預測。
(4) 請把回答分成三類逐條標示:「公式或標準明確寫的」「你查證到的(附出處)」「你自己的推論」;查不到就說查不到,不要補數字;不要給任何買賣器材的建議。