很多人都知道用手機可以粗略地檢測頻閃。但頻閃到底有多嚴重?手機檢測不到的是否真的就沒有頻閃呢?本文將用相機做出定量的分析。
問題由來
最近買了個小米Yeelight吸頂燈,用來替換家裡壞掉的燈。用手機給幾個吸頂燈拍了下照,本想看看光源的均勻程度。
圖:手機拍攝的光源(左上:松下三基色螢光燈;右上:松下LED;左下:松下未來光;右下:小米Yeelight)
拍照的時候發現有的燈是有閃爍的。於是想系統地測量一下它們的頻閃。正好手頭有逐行掃描的相機,可以幹這事。
原理
交流電
光源的頻閃主要來自交流電。因為在交流電的驅動下,光的強度會隨時間變化。
市電的波形是正弦波,而其功率可以簡化為正弦波的平方。可以看到頻率是2倍關係。
圖:正弦波及其平方的波形
所以,對於50Hz的市電,白熾燈的頻閃就是100Hz。
而對於其它燈具,可能存在交直流變換,恆流驅動,PWM調光,不管怎樣,只要其中存在一定的低頻交流成份,就會有頻閃。
逐行掃描
對於100Hz的頻閃,人的肉眼一般是感覺不到的。假設我們用一個每秒能拍1000張照片的相機,固定曝光量(光圈/快門/ISO),對著燈光下白紙拍照,這些照片的明暗程度會呈現出周期性的變化。我們可以通過這些照片分析出亮度隨時間的變化。
然而我並沒有這麼快的相機。但我有一個逐行掃描的相機,它可以10ms「拍」2000行(其實只是一張照片),我們分析每行的亮度變化,可以幹同樣的事。
逐行掃描的相機(圖像傳感器CCD或CMOS)其實是相對低端的,有時候也叫作捲簾快門(它的反面是全局快門)。其實它們都是電子開關。捲簾快門可類比於捲簾式的窗簾。下面是原理示意圖。
圖:全局快門
在全局快門模式下,所有CCD/CMOS點陣同時曝光,然後再逐行讀出。
圖:捲簾快門
在捲簾快門模式下,每行的曝光有個時間差,邊曝光,邊讀出數據(但並不是嚴格順序的,曝光的時間是可以重疊的)。
「每行的時間差」對這個測量很重要。我用的這個相機,這個參數是35us。這就是說,按行採樣的採樣率是1/35us,即28.57KHz。這個值比每秒1000張高多了。
測量方法及注意事項
這種測量方法有一個重要的前提:在同一時刻下,場景中的每一行亮度是相等的。否則,如果拍攝出來的照片每行亮度不同,這到底是場景中亮度本來就不同,還是光源亮度的隨時間波動所致呢?簡言之,想測時間上的波動,就不要有空間上的波動。
對了達到這個目的,我們需要讓光源嚴格與白紙垂直,然後,相機也要與白紙垂直。但這比較難操作。於是我使用了一種邪門的辦法:讓相機直接對著光源,但不用鏡頭。這樣「底片」上不會對光源的形狀成像,而只是一團均勻的白光(類似於鏡頭未對上焦時的虛化)。
圖:測量方法(不使用鏡頭)
另外,曝光時間越短越好。試想,如果對於100Hz的光源,使用10ms的曝光時間,每一行的曝光時間都是交流電的一個完整周期,它們的曝光量是相等的,將觀察不到頻閃。
測量數據
測量中使用的節能燈、日光燈已經比較舊了,護眼檯燈是雜牌。
圖:測量中用的節能燈和護眼檯燈
測量的原始數據就是一張張的照片。有些照片可以明顯地看到滾動的條紋,有些則不明顯。
圖:不同光源的照片(含曝光時間)
比如,
70us和5ms曝光的白熾燈,條紋明顯;而10ms曝光的白熾燈則看不到條紋,因為正好是一個周期;11ms曝光的白熾燈有條紋但不那麼明顯,因為相當於1個周期曝光的底色上再疊加0.1個周期的波動。
數據分析
要得到量化的結果,需要對照片進行分析。在ImageJ裡寫幾行腳本,很容易得到每行的平均亮度。
圖:用ImageJ進行每行亮度分析
把每行的亮度畫成曲線,就得到了這個圖。
圖:白熾燈亮度曲線
頻閃指數或波動深度定義為亮度的波動幅度比上平均亮度,波動幅度是峰谷差的一半,即:
波動深度(頻閃指數)= (H-L)/(H+L) = (196-160)/(196+160) = 10.1%
測量結果
下圖是亮度的波形。可以看到:
除了松下未來光(*),小米Yeelight,護眼檯燈外,其它都有頻閃。除了手電外,有頻閃的市電光源都是100Hz的頻閃。松下未來光,其實也可以看到100Hz的波動,但幅度很小。
圖:不同光源的亮度波動曲線(為了便於擺放整齊,不同的光源的曲線在Y軸乘上了不同的係數,這不影響結果)
日光燈的曲線有點特別,可能和電路及其發光原理有關。
圖:日光燈亮度波動曲線
護眼檯燈的曲線也不一樣,散點圖放大後是這樣,進一步放大,可以看到還是周期波動的曲線,只是頻率更高。
圖:護眼檯燈亮度波動曲線及放大
將數據存為PCM,在Audacity裡可以看到其頻譜。峰值在8379Hz,我們可以認為這是其頻閃頻率。
圖:護眼檯燈頻閃頻譜
下圖是匯總的測量結果。主要指標就兩個:頻閃頻率和波動深度(頻閃指數)。峰值和谷值是計算時選取的中間結果;曝光時間是當次測量對應的曝光時間。嚴格來講,曝光時間越短結果越精確;曝光時間加長,頻閃指數會降低。
圖:不同光源頻閃的量化指標
對測量的若干思考
一致性問題
多次測量時,相機和光源的距離會變,曝光時間也可能會變,結果能否保持一致?
做了幾次試驗。
圖:測量一致性比較
圖中A1和A2測得的亮度值不同,但最後波動深度的結果是一樣的。A3的曝光時間加長,結果變小一點,這是符合預期的。B1是另一根燈管,結果也比較接近。這基本說明測量是可信的。
曲線不平的問題
前面的很多圖中,可以看到亮度曲線整體上並不是平的。這並不是說明光的亮度有低頻波動,而是因為相機和燈光不垂直或有暗角,會導致光在平面上的分布不均勻,每行的平均亮度裡會反映出這種波動。這個很難避免,但不影響對頻閃頻率和波幅的測量。
所以,在計算波動深度時,我選取了兩個相鄰的波峰做平均,選兩個波峰中間的波谷。參見上圖。
至於光強是否真的有低頻波動?首先理論上不大可能有50Hz以下的波動。實驗上,我們可以用普通的30幀率的相機,按幀取樣做測試,看有沒有低頻波動。
採樣頻率和曝光時間
前文說過,我使用的相機是行掃描的相機,行採樣頻率是28.57KHz。根據採樣定理,它可以檢測出14.28KHz及以下的頻閃。
如果曝光時間是140us,這看起來頻率只能到1/140us即7.14KHz。是這樣嗎?
實際上,只要曝光時間不是頻閃周期的整數倍,即使10.1倍,通過積分後,還是會有波動,因為每次採樣有相位差。但這個波動幅度會被拉平,所以測量的準確性會降低。
前面護眼檯燈的測量,頻閃頻率是8379Hz,而曝光時間140us已經超過了頻閃周期(119us),所以測得的頻閃指數應該會偏小。
按幀採樣的測量
在燈光下,對著白紙或白牆拍一段視頻,然後計算每幀的平均亮度。
shell腳本如下,將輸出存為CSV,即可畫出曲線。
ffmpeg -i video.mov %d.jpgfor i in {1..600}doecho -n $i, identify -verbose $i.jpg | grep mean | tail -n 1 | awk '{print $2}'done
圖:幀採樣得到的日光燈亮度曲線
由於頻閃周期、採樣周期、曝光時間三者沒有任何倍數關係,採樣亮度呈現出非常複雜的「類周期」波動。
由於曝光時間是頻閃周期的3.3倍,波動已經平滑了很多。從圖中計算出波動深度是0.51%。而前面的測量方法得出的結果是5.3%。
所以,用低幀率的幀採樣,只能看出有無頻閃,並不能準確得到頻閃頻率和波動深度。
結語
通過逐行掃描的相機可以對光源的頻閃進行定量檢測,要點在於減少曝光時間,保持感光面的光照均勻。普通的整幀曝光的相機,由於幀率不高,僅能用來檢測有無頻閃,並不能準確測量出頻閃頻率和波幅。
測量的結果令我頗意外:松下的LED和三基色螢光燈連普通白熾燈都比不上。而小米Yeelight的數據非常好。
當然,這個對比有不公平的地方,松下的燈是舊的(三四年2000小時左右的使用時間),而小米的燈是新的。不過松下未來光也是同樣舊的(使用時間甚至更長),但表現還不錯。這說明普通產品的質量還是有差距。小米的Yeelight則需要時間的檢驗,看幾年後指標如何。
一些測量結果僅反映我家的燈具,並不能代表市面上所有的產品。本文主要還是探討測量方法。