
1. 從一條模糊的掃描線說起線性插值去偽影到底在解決什么如果你處理過醫(yī)學影像、工業(yè)CT、衛(wèi)星遙感圖或者老照片修復大概率見過那種讓人抓狂的畫面本該平滑過渡的區(qū)域出現(xiàn)了一圈圈像水波紋一樣的條紋或者物體邊緣帶著一層鋸齒狀的“鬼影”。這些不是真實存在的結(jié)構(gòu)而是成像過程中引入的偽影。偽影的種類很多金屬偽影、運動偽影、截斷偽影、混疊偽影每一種的成因和應對策略都不一樣。而“線性插值方法去偽影”這個標題指向的是其中一類非常經(jīng)典、也非常實用的處理思路——在數(shù)據(jù)缺失或數(shù)據(jù)異常的區(qū)間用線性插值把斷裂的信號補回來從而消除因數(shù)據(jù)不連續(xù)造成的偽影。我第一次接觸這個思路是在處理一批工業(yè)無損檢測的投影數(shù)據(jù)時。當時探測器上有一排通道因為校準問題輸出異常重建出來的切片上就出現(xiàn)了貫穿整個圖像的亮暗條紋。最直接的辦法當然是把壞通道的數(shù)據(jù)丟掉但丟掉之后重建會引入更嚴重的環(huán)形偽影。后來換了個思路把壞通道兩側(cè)的正常通道值取出來在它們之間做線性插值用插值結(jié)果去填充壞通道。重建圖像上的條紋立刻消失了。這個操作的本質(zhì)就是用線性插值去修補數(shù)據(jù)中的“空洞”讓后續(xù)的重建算法拿到一份連續(xù)、完整的數(shù)據(jù)。所以線性插值去偽影的核心邏輯可以概括成一句話偽影往往源于數(shù)據(jù)的不連續(xù)或異常突變而線性插值的作用是在已知的可靠數(shù)據(jù)點之間構(gòu)造平滑過渡把異常點替換掉從而恢復數(shù)據(jù)的連續(xù)性。它不是什么高深的數(shù)學工具甚至可以說是所有插值方法里最簡單的一種但正因為簡單它的計算開銷極小、可解釋性極強、參數(shù)極少在很多實時性要求高或者數(shù)據(jù)量巨大的場景里反而是最穩(wěn)妥的選擇。這篇文章適合誰看如果你正在做圖像重建、信號修復、數(shù)據(jù)預處理相關(guān)的工作或者你手頭有一批帶條紋、帶環(huán)狀偽影的數(shù)據(jù)需要快速處理那這篇內(nèi)容應該能給你一些可以直接落地的思路。我會從線性插值為什么能去偽影講起然后拆解幾種典型的偽影場景和對應的插值策略接著給出具體的實現(xiàn)步驟和參數(shù)選擇經(jīng)驗最后分享一些我在實際項目中踩過的坑和總結(jié)出來的技巧。全程不堆公式盡量用大白話把原理說清楚代碼部分會給Python示例方便你直接拿去改。2. 線性插值去偽影的底層邏輯為什么“簡單”反而有效2.1 偽影的本質(zhì)是數(shù)據(jù)連續(xù)性被破壞要理解線性插值為什么能去偽影得先搞清楚偽影是怎么來的。以CT重建為例理想情況下探測器上每個通道接收到的信號應該是隨位置緩慢變化的相鄰通道之間的差異很小。重建算法比如濾波反投影依賴的就是這種空間連續(xù)性它通過投影數(shù)據(jù)在空間域的積分關(guān)系來還原物體內(nèi)部的衰減系數(shù)分布。一旦某個通道的數(shù)據(jù)出現(xiàn)異?!热缤蝗黄呋蚱汀@個異常值在反投影過程中會被“抹”到整條射線上形成一條亮線或暗線。如果多個相鄰通道同時異常就會形成更寬的條紋。如果異常通道的位置在旋轉(zhuǎn)過程中不斷變化就會形成環(huán)形偽影。換句話說偽影是數(shù)據(jù)異常在重建空間中的可視化表現(xiàn)。你看到的條紋、環(huán)、鬼影本質(zhì)上都是因為重建算法拿到了一份“不干凈”的輸入數(shù)據(jù)。線性插值要做的就是在這份數(shù)據(jù)進入重建算法之前把異常值替換成合理的估計值讓數(shù)據(jù)重新變得“干凈”。2.2 為什么選線性插值而不是更復雜的方法插值方法有很多最近鄰插值、線性插值、三次樣條插值、多項式插值、基于深度學習的插值等等。從平滑程度來看三次樣條比線性插值更光滑從擬合能力來看深度學習方法可以學到非常復雜的映射關(guān)系。那為什么還要用線性插值第一個原因是數(shù)據(jù)密度足夠高。在大多數(shù)成像系統(tǒng)中探測器通道數(shù)少則幾百多則幾千相鄰通道之間的物理間距很小。在這個尺度下信號的變化本身就接近線性用線性插值引入的誤差遠小于異常值本身造成的誤差。你花大力氣上三次樣條帶來的精度提升可能只有百分之幾但計算量翻了好幾倍。第二個原因是線性插值不會引入過沖。三次樣條和多項式插值都有一個通病在數(shù)據(jù)點之間可能出現(xiàn)超出原始數(shù)據(jù)范圍的振蕩也就是所謂的“龍格現(xiàn)象”。在去偽影場景里這種過沖是致命的——你本來是想把異常值壓下去結(jié)果插值結(jié)果反而在異常值附近產(chǎn)生了新的尖峰重建出來就是新的偽影。線性插值沒有這個問題它的結(jié)果永遠落在兩個已知點之間不會超出范圍。第三個原因是可解釋性和可調(diào)試性。線性插值的邏輯非常直觀取左右兩個正常點連一條直線中間的值就在這條直線上。如果去偽影效果不理想你可以很容易地判斷是哪些點選得不對、區(qū)間劃得不好。而深度學習方法的黑箱特性在醫(yī)療影像這種對可靠性要求極高的場景里往往讓人不敢輕易上線。注意線性插值并不是萬能的。如果異常區(qū)間很寬比如連續(xù)幾十個通道都壞了那線性插值的效果會明顯下降因為兩個端點之間的真實信號可能并不是線性的。這種情況下需要考慮更高階的插值或者基于物理模型的修復方法。2.3 線性插值的數(shù)學表達與直觀理解線性插值的公式非常簡單。假設(shè)你在位置 (x_0) 有一個正常值 (y_0)在位置 (x_1) 有一個正常值 (y_1)那么對于 (x_0) 和 (x_1) 之間任意位置 (x)插值結(jié)果就是[ y y_0 \frac{(y_1 - y_0)(x - x_0)}{x_1 - x_0} ]這個公式說白了就是“按距離加權(quán)平均”。如果 (x) 離 (x_0) 更近結(jié)果就更接近 (y_0)離 (x_1) 更近就更接近 (y_1)。在圖像處理里如果數(shù)據(jù)是均勻采樣的(x) 的間隔是1那公式可以簡化成[ y[i] y[left] \frac{(y[right] - y[left]) \cdot (i - left)}{right - left} ]其中 (left) 和 (right) 是異常區(qū)間左右兩側(cè)最近正常點的索引(i) 是當前要填充的位置。這個計算量極小一次乘加就能搞定一個點用NumPy向量化之后幾千個通道的插值可以在毫秒級完成。從信號處理的角度看線性插值相當于用一個一階保持器去重建信號它的頻率響應是一個sinc函數(shù)的平方對高頻成分有衰減作用。這意味著它在填補數(shù)據(jù)的同時會輕微模糊掉一些高頻細節(jié)。但在去偽影場景里這個“模糊”反而是好事——異常值往往表現(xiàn)為高頻尖峰線性插值正好把它壓下去了。3. 三類典型偽影場景與對應的插值策略3.1 壞通道導致的條紋偽影一維插值直接修復這是最常見也最容易處理的一類。探測器陣列中某個或某幾個通道因為硬件故障、校準漂移或者傳輸錯誤輸出的數(shù)據(jù)明顯偏離正常范圍。在重建圖像上這些壞通道會形成貫穿整個視場的亮線或暗線。處理思路很直接在投影數(shù)據(jù)域沿通道方向做一維線性插值。具體來說對于每一個投影角度找到壞通道的位置然后用它左右兩側(cè)最近的好通道值做線性插值把壞通道的值替換掉。這里有一個關(guān)鍵細節(jié)壞通道的檢測。你不能手動去標哪些通道壞了因為通道狀態(tài)可能隨時間變化。常用的自動檢測方法有兩種。一種是基于統(tǒng)計的計算每個通道在一段時間內(nèi)的均值和方差如果某個通道的均值偏離整體均值超過3倍標準差或者方差異常大就標記為壞通道。另一種是基于相鄰通道差異的計算每個通道與左右鄰居的差值如果差值超過某個閾值就認為該通道異常。實際項目中我通常把兩種方法結(jié)合起來先用統(tǒng)計方法粗篩再用局部差異法確認。import numpy as np def detect_bad_channels(projection, threshold3.0): 基于統(tǒng)計方法檢測壞通道 projection: 形狀為 (angles, channels) 的投影數(shù)據(jù) threshold: 標準差倍數(shù)閾值 mean_per_channel np.mean(projection, axis0) std_per_channel np.std(projection, axis0) global_mean np.mean(mean_per_channel) global_std np.std(mean_per_channel) # 標記均值異常通道 bad_mask np.abs(mean_per_channel - global_mean) threshold * global_std # 進一步用局部差異確認 diff np.abs(np.diff(mean_per_channel)) local_threshold np.mean(diff) 3 * np.std(diff) for i in range(1, len(mean_per_channel) - 1): if diff[i-1] local_threshold and diff[i] local_threshold: bad_mask[i] True return bad_mask def linear_interp_bad_channels(projection, bad_mask): 對壞通道做線性插值修復 fixed projection.copy() channels projection.shape[1] good_indices np.where(~bad_mask)[0] for i in range(channels): if bad_mask[i]: # 找到左右最近的好通道 left good_indices[good_indices i] right good_indices[good_indices i] if len(left) 0 or len(right) 0: # 邊界情況用最近的好通道值填充 nearest left[-1] if len(left) 0 else right[0] fixed[:, i] projection[:, nearest] else: l, r left[-1], right[0] weight (i - l) / (r - l) fixed[:, i] projection[:, l] * (1 - weight) projection[:, r] * weight return fixed這段代碼可以直接用在投影數(shù)據(jù)上。實測下來對于單個或少量連續(xù)壞通道修復后的重建圖像幾乎看不出條紋殘留。但如果壞通道連續(xù)超過5個線性插值的誤差就會開始顯現(xiàn)這時候需要考慮用多項式擬合或者基于鄰域統(tǒng)計的修復方法。3.2 金屬偽影在正弦圖域做插值修復金屬偽影是CT成像里最棘手的問題之一。當掃描對象體內(nèi)有金屬植入物時金屬的高密度會導致射線束硬化、光子 starvation 和散射在重建圖像上形成明亮的條紋和暗帶。處理金屬偽影的經(jīng)典方法之一就是在正弦圖域也就是投影數(shù)據(jù)域把金屬對應的投影區(qū)間識別出來然后用插值方法把這些區(qū)間的數(shù)據(jù)補上。這里的邏輯和壞通道修復類似但復雜之處在于金屬對應的投影區(qū)間在不同角度下位置和寬度都在變化。你需要先通過圖像域分割或者投影域閾值法把金屬區(qū)域找出來然后把這些區(qū)域投影到正弦圖上得到每個角度下需要修復的通道范圍。具體步驟是這樣的先對原始投影做一次重建得到帶金屬偽影的圖像然后在圖像域用閾值分割把金屬區(qū)域提取出來接著把金屬區(qū)域的前向投影算出來得到金屬在正弦圖上的“陰影”最后在正弦圖上把金屬陰影覆蓋的區(qū)間用左右兩側(cè)的正常投影值做線性插值。def metal_artifact_correction(sinogram, metal_mask_sinogram): 在正弦圖域?qū)饘賲^(qū)域做線性插值修復 sinogram: 原始正弦圖 (angles, channels) metal_mask_sinogram: 金屬區(qū)域掩碼True表示需要修復 corrected sinogram.copy() angles, channels sinogram.shape for ang in range(angles): mask metal_mask_sinogram[ang] if not np.any(mask): continue # 找到需要修復的連續(xù)區(qū)間 indices np.where(mask)[0] # 將連續(xù)區(qū)間分組 groups np.split(indices, np.where(np.diff(indices) ! 1)[0] 1) for group in groups: left group[0] - 1 right group[-1] 1 if left 0: corrected[ang, group] sinogram[ang, right] elif right channels: corrected[ang, group] sinogram[ang, left] else: # 線性插值 for i in group: weight (i - left) / (right - left) corrected[ang, i] sinogram[ang, left] * (1 - weight) sinogram[ang, right] * weight return corrected這個方法的局限性在于如果金屬區(qū)域很大插值區(qū)間很寬線性插值會丟失大量結(jié)構(gòu)信息重建圖像上金屬周圍會出現(xiàn)模糊。所以實際使用時通常會結(jié)合迭代重建或者歸一化金屬偽影校正來進一步提升效果。線性插值在這里的角色是“粗修復”先把最明顯的條紋壓下去后續(xù)再用其他方法精修。3.3 截斷偽影邊界延拓中的線性外推截斷偽影發(fā)生在投影數(shù)據(jù)不完整的時候。比如掃描對象超出了探測器視野或者你只拿到了部分角度的投影數(shù)據(jù)。重建時算法假設(shè)視野外的數(shù)據(jù)為零這個突然的截斷會在圖像邊緣產(chǎn)生亮環(huán)或暗環(huán)。處理截斷偽影的一個常用技巧是邊界延拓在投影數(shù)據(jù)的兩端人為地延長一段數(shù)據(jù)讓截斷變得“平滑”。線性外推是最簡單的延拓方式——用邊界處幾個點的斜率向外延伸出一條直線。def linear_extrapolation(projection, extend_width20): 對投影數(shù)據(jù)兩端做線性外推 projection: (angles, channels) extend_width: 每端延拓的通道數(shù) angles, channels projection.shape extended np.zeros((angles, channels 2 * extend_width)) extended[:, extend_width:extend_width channels] projection for ang in range(angles): # 左端外推 left_slope (projection[ang, 1] - projection[ang, 0]) for i in range(extend_width): extended[ang, extend_width - 1 - i] projection[ang, 0] - left_slope * (i 1) # 右端外推 right_slope (projection[ang, -1] - projection[ang, -2]) for i in range(extend_width): extended[ang, extend_width channels i] projection[ang, -1] right_slope * (i 1) return extended線性外推的效果取決于邊界處信號的趨勢。如果邊界處信號本身就在快速變化線性外推可能會產(chǎn)生不合理的值。所以實際使用時我通常會先對邊界處的幾個點做平滑再計算斜率。另外延拓寬度不宜過大一般10到30個通道就夠了太寬反而會引入新的偽影。4. 從投影域到圖像域線性插值的適用邊界與替代方案4.1 投影域插值 vs 圖像域插值線性插值去偽影可以在兩個域進行投影域正弦圖域和圖像域。兩者的區(qū)別很大。投影域插值是在重建之前對原始數(shù)據(jù)做修復。它的優(yōu)點是修復的是“因”而不是“果”。偽影還沒形成你就在數(shù)據(jù)層面把異常去掉了重建出來的圖像自然干凈。而且投影域的數(shù)據(jù)通常是一維或二維的處理起來計算量小。缺點是你需要準確地定位哪些投影數(shù)據(jù)是異常的這個定位過程本身可能很復雜。圖像域插值是在重建之后對圖像做修復。比如你已經(jīng)在圖像上看到了條紋然后用插值方法把條紋區(qū)域覆蓋掉。它的優(yōu)點是直觀、容易操作不需要了解投影數(shù)據(jù)的細節(jié)。缺點是偽影已經(jīng)和真實結(jié)構(gòu)混在一起了你很難區(qū)分哪些是偽影、哪些是真實細節(jié)。插值修復可能會把真實結(jié)構(gòu)也一起抹掉。我的經(jīng)驗是能投影域做就投影域做。投影域的異常通常有明確的物理成因壞通道、金屬、截斷定位相對容易。圖像域的偽影是多種因素疊加的結(jié)果修復起來更棘手。只有在拿不到投影數(shù)據(jù)、或者投影數(shù)據(jù)質(zhì)量太差無法定位異常時才考慮圖像域修復。4.2 線性插值搞不定的情況什么時候該換方法線性插值不是銀彈。以下幾種情況你需要考慮替代方案異常區(qū)間過寬。如果連續(xù)幾十個通道的數(shù)據(jù)都不可用線性插值相當于用一條直線去擬合一段可能很復雜的曲線誤差會很大。這時候可以考慮三次樣條插值、基于稀疏表示的修復、或者基于深度學習的圖像翻譯方法。異常值不是“缺失”而是“錯誤”。線性插值假設(shè)異常位置的數(shù)據(jù)完全不可信用鄰居的值來替代。但如果異常值是真實信號疊加了一個偏差比如增益漂移那更好的做法是先估計這個偏差然后從異常值中減去偏差而不是直接丟棄。這就是歸一化校正的思路。偽影與真實結(jié)構(gòu)重疊。如果偽影恰好落在你關(guān)心的解剖結(jié)構(gòu)上插值修復可能會把真實結(jié)構(gòu)一起模糊掉。這時候需要考慮迭代重建在重建過程中同時估計真實圖像和偽影通過交替優(yōu)化來分離兩者。數(shù)據(jù)維度更高。線性插值在一維和二維上很好用但如果是三維甚至四維數(shù)據(jù)比如動態(tài)CT、光譜CT簡單的線性插值可能不夠。需要考慮沿多個方向做插值或者用張量補全的方法。4.3 一個實用的決策流程面對一個具體的去偽影任務我通常會按下面的流程來判斷該不該用線性插值判斷條件適合線性插值不適合考慮替代方案異常區(qū)間寬度1-5個通道超過10個通道異常類型數(shù)據(jù)缺失或完全錯誤系統(tǒng)性偏差數(shù)據(jù)維度一維或二維三維及以上實時性要求高低可解釋性要求高低計算資源有限充足這個表不是絕對的但可以幫你快速判斷。大多數(shù)壞通道修復和金屬偽影粗修復場景線性插值都是第一選擇。如果效果不理想再往上加復雜度。5. 實操中的參數(shù)選擇與效果驗證5.1 插值區(qū)間的確定寧窄勿寬線性插值去偽影最關(guān)鍵的一步是確定哪些數(shù)據(jù)點需要被替換。這個區(qū)間定得太窄異常值沒修干凈定得太寬正常數(shù)據(jù)被誤傷。我的經(jīng)驗是寧窄勿寬。為什么因為線性插值的誤差隨區(qū)間寬度線性增長。區(qū)間越寬插值結(jié)果偏離真實值的可能性越大。而如果區(qū)間定窄了漏掉一兩個異常點重建圖像上可能只是輕微的殘留后續(xù)還可以再補一次修復。但如果區(qū)間定寬了把正常數(shù)據(jù)替換成插值值相當于人為地在數(shù)據(jù)里引入了錯誤這個錯誤會直接變成新的偽影。具體操作上我通常先用一個較嚴格的閾值檢測異常點然后對檢測到的異常點做形態(tài)學膨脹把相鄰的異常點合并成一個區(qū)間。膨脹的半徑一般設(shè)為1到2個通道目的是把異常點邊緣可能受影響的通道也納入修復范圍。from scipy.ndimage import binary_dilation def refine_bad_interval(bad_mask, dilation_radius1): 對壞通道掩碼做膨脹合并相鄰異常區(qū)間 struct np.ones(2 * dilation_radius 1, dtypebool) refined binary_dilation(bad_mask, structurestruct) return refined5.2 邊界處理別讓修復引入新問題線性插值在區(qū)間內(nèi)部很穩(wěn)但在邊界處容易出問題。如果異常區(qū)間一直延伸到數(shù)據(jù)邊緣你就找不到右側(cè)的正常點來做插值。這時候有幾種處理方式第一種是單側(cè)外推用左側(cè)正常點的斜率向右延伸。這種方法在邊界處信號變化平緩時效果不錯但如果信號本身在邊界處有劇烈變化外推結(jié)果可能很離譜。第二種是鏡像填充把邊界附近的數(shù)據(jù)鏡像復制到外側(cè)人為制造出“正常點”。這種方法適合信號在邊界處近似對稱的情況。第三種是常數(shù)填充直接用邊界處最后一個正常點的值填充整個異常區(qū)間。這種方法最保守不會引入新的尖峰但可能會在邊界處形成一個小臺階。我一般優(yōu)先用單側(cè)外推如果外推結(jié)果超出了正常數(shù)據(jù)的范圍就退回到常數(shù)填充。鏡像填充用得比較少因為它對信號的對稱性有要求適用場景有限。5.3 效果驗證不能只看重建圖像去偽影效果好不好不能只靠肉眼看重建圖像。我通常會從三個層面驗證第一層投影數(shù)據(jù)的一致性。修復后的投影數(shù)據(jù)相鄰通道之間的差異應該回到正常水平。你可以計算修復區(qū)間內(nèi)相鄰通道差值的均值和方差和正常區(qū)域?qū)Ρ?。如果差異明顯偏大說明插值結(jié)果和周圍數(shù)據(jù)不連貫。第二層重建圖像的定量指標。在圖像域可以計算偽影區(qū)域的標準差和對比度噪聲比。偽影被壓下去之后均勻區(qū)域的標準差應該下降目標區(qū)域的對比度噪聲比應該上升。如果有g(shù)round truth比如仿真數(shù)據(jù)還可以算PSNR和SSIM。第三層下游任務的性能。如果去偽影是為了后續(xù)的分割、檢測或測量那最終指標應該看下游任務的表現(xiàn)。我遇到過插值后圖像看起來干凈了但分割精度反而下降的情況——因為插值把一些微小的真實結(jié)構(gòu)也抹掉了。所以一定要用下游任務來最終把關(guān)。def evaluate_correction(original, corrected, bad_mask): 評估修復效果 # 投影數(shù)據(jù)一致性 diff_original np.abs(np.diff(original, axis1)) diff_corrected np.abs(np.diff(corrected, axis1)) normal_region ~bad_mask[1:] ~bad_mask[:-1] bad_region bad_mask[1:] | bad_mask[:-1] consistency_normal np.mean(diff_corrected[:, normal_region]) consistency_bad np.mean(diff_corrected[:, bad_region]) print(f正常區(qū)域相鄰差異均值: {consistency_normal:.4f}) print(f修復區(qū)域相鄰差異均值: {consistency_bad:.4f}) print(f差異比值: {consistency_bad / consistency_normal:.2f}) # 如果比值接近1說明修復區(qū)域和正常區(qū)域的一致性很好 return consistency_bad / consistency_normal6. 踩過的坑與總結(jié)出的經(jīng)驗6.1 坑一壞通道檢測的閾值設(shè)得太死剛開始做壞通道修復時我用了一個固定的閾值來判斷通道是否異常。結(jié)果發(fā)現(xiàn)不同掃描條件下正常通道的波動范圍差別很大。有時候閾值太松漏檢了壞通道有時候閾值太緊把正常波動誤判為壞通道修復后反而引入了新的條紋。后來我改成自適應閾值先計算當前投影數(shù)據(jù)中所有通道差異的分布然后取分布的中位數(shù)加上若干倍的中位數(shù)絕對偏差作為閾值。這樣閾值會隨著數(shù)據(jù)本身的變化自動調(diào)整魯棒性好了很多。def adaptive_threshold(diff_data, k3.0): 基于中位數(shù)絕對偏差的自適應閾值 median np.median(diff_data) mad np.median(np.abs(diff_data - median)) threshold median k * mad return threshold6.2 坑二插值后忘了做平滑過渡線性插值在區(qū)間內(nèi)部是線性的但在區(qū)間邊界處插值值和原始值之間可能存在一階不連續(xù)——也就是說斜率會突然變化。這個不連續(xù)在重建圖像上可能表現(xiàn)為一條細小的亮線或暗線。解決辦法是在插值完成后對修復區(qū)間及其左右各幾個通道做一次輕度平滑。我通常用一個寬度為3到5的滑動平均只作用在修復區(qū)間附近不影響其他區(qū)域。這樣可以把邊界處的不連續(xù)抹平同時不會過度模糊。6.3 坑三所有角度用同一套壞通道掩碼在多角度投影數(shù)據(jù)中壞通道的位置可能隨角度變化。如果所有角度都用同一套掩碼有些角度下正常通道會被誤修有些角度下壞通道又沒修到。正確的做法是逐角度檢測壞通道。雖然計算量會大一些但準確性高很多。如果壞通道位置相對穩(wěn)定可以先在所有角度上做一次檢測取并集作為初始掩碼然后對每個角度在這個掩碼附近做局部微調(diào)。6.4 坑四忽略了數(shù)據(jù)歸一化在做插值之前如果投影數(shù)據(jù)的量級在不同角度之間差異很大比如因為管電流調(diào)制直接插值可能會出問題。我習慣先對每個角度的投影做歸一化讓所有角度的數(shù)據(jù)在同一個量級上插值完成后再反歸一化。這樣插值結(jié)果更穩(wěn)定也不會因為量級差異導致數(shù)值問題。6.5 一個讓我印象深刻的案例有一次處理一批工業(yè)CT數(shù)據(jù)重建圖像上出現(xiàn)了非常規(guī)律的環(huán)形偽影。一開始以為是探測器壞通道用線性插值修了半天效果不明顯。后來仔細檢查投影數(shù)據(jù)發(fā)現(xiàn)是旋轉(zhuǎn)中心的偏移導致的——每個角度的投影數(shù)據(jù)整體平移了一點點累積起來就形成了環(huán)形偽影。這個案例讓我意識到去偽影的第一步永遠是準確診斷偽影的成因。線性插值只對“數(shù)據(jù)缺失或異?!鳖悅斡坝行缀涡暑悅斡盁o能為力。如果你用線性插值去修幾何偽影不僅修不好還可能把數(shù)據(jù)搞得更亂。所以每次動手之前先花時間看看偽影的形態(tài)、分布和變化規(guī)律判斷它屬于哪一類再決定用什么工具。6.6 關(guān)于線性插值去偽影我的幾點個人體會第一簡單方法用對場景效果不輸復雜方法。線性插值在壞通道修復和金屬偽影粗修復這兩個場景里性價比極高。我見過不少團隊一上來就上深度學習結(jié)果因為訓練數(shù)據(jù)不足、泛化能力差實際效果還不如老老實實做線性插值。第二參數(shù)不要拍腦袋定用數(shù)據(jù)說話。插值區(qū)間寬度、檢測閾值、平滑窗口大小這些參數(shù)都應該基于當前數(shù)據(jù)的統(tǒng)計特性來確定。我通常會先在一小批數(shù)據(jù)上做參數(shù)掃描畫出參數(shù)-效果曲線找到拐點后再應用到全量數(shù)據(jù)。第三驗證要分層不能只看最終圖像。投影數(shù)據(jù)的一致性、重建圖像的定量指標、下游任務的性能這三個層面都要看。只盯著重建圖像調(diào)參數(shù)很容易過擬合到視覺效果好但實際指標差的結(jié)果。第四保留原始數(shù)據(jù)修復過程可回溯。每次修復都記錄下哪些通道被替換了、替換值是多少、用的什么參數(shù)。這樣如果后續(xù)發(fā)現(xiàn)問題可以快速定位是修復引入的還是原始數(shù)據(jù)就有的。我在項目里通常會保存一份修復日志包含壞通道掩碼、插值參數(shù)和修復前后的數(shù)據(jù)快照。線性插值去偽影這個方向看起來簡單但真正做好需要你對成像物理、數(shù)據(jù)特性和重建算法都有理解。它不是那種“調(diào)個包就能用”的技術(shù)而是需要你根據(jù)具體場景去設(shè)計和調(diào)整。但一旦掌握了你會發(fā)現(xiàn)它能解決相當一部分實際問題而且穩(wěn)定、快速、可控。如果你正在處理帶偽影的數(shù)據(jù)不妨先從線性插值入手試試很多時候最簡單的工具反而最趁手。