在數位金融開戶、遠距保險理賠等線上身份驗證(KYC)場景中,「防偽防翻拍偵測(Anti-Spoofing / Liveness Detection)」 是確保系統安全性的關鍵防線。
隨著高解析度手機鏡頭與 4K 螢幕的普及,詐欺犯只需要在螢幕上展示一張從網路或非法管道取得的他人證件照片,或者列印出一張高品質的彩色影印本,並對著手機鏡頭拍照上傳,就能輕易騙過傳統的 OCR 辨識引擎。
為了防範這類偽造詐欺,企業級系統主要結合了前端動態防偽與後端雙重靜態防偽技術。本文將深入剖析這兩項技術的運作原理,並提供基於 Python + OpenCV 的二維傅立葉變換(2D FFT)防翻拍與微觀網點密度分析偵測實作。
1. 動態防偽(Dynamic Liveness Detection):前端的第一道防線
動態防偽是目前金融機構數位開戶最推崇的「黃金標準」,其核心目的在於檢測**「被拍物是否為一個具有三維立體物理特性的真實卡片」**。
運作機制與防偽原理
- 雷射全像圖案動態折射:真品證件(如身份證、健保卡)上印有高度複雜的雷射防偽全像標籤(Hologram,如台灣身份證的防偽蝴蝶與 TAIWAN 字樣)。這些標籤的反射光澤會隨著「卡片與光源的夾角變化」而動態位移。
- 引導式晃動錄影:前端系統引導使用者開啟鏡頭,並在手上左右、上下輕微晃動證件,錄製一段 2~3 秒的短影片。
- 多影格光影校正:後端演算法會比對多個影格(Frames),追蹤雷射圖案在特定三維坐標上的反射光澤是否產生相對應的物理位移。
動態防偽的優缺點
- 優點:防禦力極高。因為彩色影印本(扁平無折射)與數位螢幕(液晶偏光且折射固定)完全無法模擬真品卡片在傾斜時產生的多維動態折射效果。
- 缺點(企業痛點):
- 使用者摩擦力高(User Friction):要求使用者錄影並擺動卡片會大幅降低使用者體驗,導致線上申請流失率(Drop-off rate)增加。
- 相容性問題:網頁端調用相機(WebRTC)容易因為不同瀏覽器、不同手機型號的權限阻擋而失敗。
- 無法用於歷史上傳檔案:當業務流程只允許使用者「上傳單張靜態照片」或處理歷史批次檔案時,動態防偽將完全無法施展。
2. 第一道靜態防線:用二維傅立葉變換(2D FFT)偵測螢幕翻拍
當系統被限制在「只能分析單張上傳的照片」時,第一步是檢測照片是否為螢幕翻拍。
什麼是摩爾紋?(空間網格干涉原理)
摩爾紋是一種空間干涉現象。當我們用手機相機拍攝電腦、平板或手機螢幕時,以下兩個具有週期性空間結構的網格會發生重疊:
- 螢幕的物理顯示網格(如 LCD/LED 的紅綠藍 RGB 子像素微觀排列)。
- 相機感光元件的採樣網格(如 CMOS 上的 Bayer 濾鏡感光陣列)。
這兩個網格的空間頻率(Spatial Frequency)稍微不一致且疊加時,就會在拍攝出來的影像上產生低頻干涉條紋,這就是摩爾紋。真實的紙張或塑膠卡片表面並沒有這種液晶像素網格,因此絕對不會產生摩爾紋。
傅立葉變換(FFT)的數學判定原理
在空間域中,摩爾紋表現為影像亮度的週期性波動。若將影像轉換到頻域(Frequency Domain),這些週期性波動就會凝聚成特徵極為明顯的能量分布。
二維離散傅立葉變換(2D DFT)的數學公式如下:
$$F(u,v) = \sum_{x=0}^{M-1} \sum_{y=0}^{N-1} f(x,y) e^{-j2\pi\left(\frac{ux}{M} + \frac{vy}{N}\right)}$$
其中,$f(x,y)$ 是影像在空間中的灰階像素值,$F(u,v)$ 是轉換後的頻域複數值。
- 普通圖像的頻域分布:大部分自然圖像的能量都集中在低頻(中心區),而邊緣細節會在頻域圖上沿著水平與垂直軸形成一個清晰的**「十字交叉十字星」**。
- 翻拍圖像的頻域分布:由於螢幕像素點陣在二維空間中是高度規律、等距排列的週期性高頻噪聲,這些規律的噪聲經過傅立葉變換後,會在十字交叉之外的高頻區域,產生一對或多對高度對稱、能量極高且孤立的「亮點(Spikes / Peaks)」。
3. 第二道靜態防線:基於微觀網點密度分析(Halftone Detection)防禦彩色影印
使用偵測摩爾紋的方式可以讓我們判斷是否證件照為螢幕翻拍,但如果是使用高品質彩色印表機將證件影像列印在紙張上,再進行拍攝上傳,此時,因為紙張表面不具備螢幕的液晶像素排列,摩爾紋偵測將會失效。因此,我們需要再進一步檢測證件照是否有防偽浮水印。 在目前工業界與學術界中,針對靜態證件照進行防偽水印與真實卡片材質檢測,主流的做法主要有以下三種:
- 單應性對齊與標準樣版比對 (Homography Alignment & Template Matching)
- 原理:利用 SIFT 或 ORB 等特徵描述子,將拍攝的證件照與標準真品樣版進行特徵點匹配,並透過單應性矩陣(Homography Matrix)將證件畫面完美透視對齊(Warp)到標準尺寸。接著,直接切出防偽蝴蝶或國徽所在的精確座標區域,與標準防偽圖案進行結構相似度(SSIM)或歸一化互相關(NCC)比對。若為偽造印製,其圖案紋路通常會發生細微偏移或細節失真。
- HSV 鏡面反光與彩虹折射分割 (HSV Specular Refraction Segmentation)
- 原理:真品證件上的雷射防偽貼紙在光源直射下會產生強烈的鏡面反射(在灰階下接近純白高亮)以及彩虹般的色譜分裂(高色彩飽和度)。透過將影像轉換至 HSV 色彩空間,對亮度(V)與飽和度(S)設定特定的閥值區間進行二值化分割,即可抓取出雷射貼紙的反光區塊,進而驗證其幾何形狀與位置是否正確。
- 微觀網點與紋理密度分析 (Micro-Contour Halftone Detection)
- 原理:檢測紙張表面的微觀印刷紋理。一般的家用或辦公室彩色印表機(雷射或噴墨)受限於物理機制,無法印出連續的細線,而是透過青(C)、洋紅(M)、黃(Y)、黑(K)四種顏色的微小「半色調網點(Halftone Dots)」交錯堆疊來模擬色彩。而真品證件是使用高精度的專業「凹版與防偽線條印刷」,表面為流暢連續的實線。在空間域下利用拉普拉斯算子與輪廓分析,即可統計出印刷網點的密度。
我們在接下來的部份採用的是第三種「微觀網點與紋理密度分析」。這是一種不使用任何機器學習模型,純粹使用 OpenCV 影像處理與數學統計的極速防偽解決方案。
印刷技術的物理差異:防偽線條 vs. CMYK 網點
- 真實證件(凹版與平版防偽印刷):真實身份證或健保卡是由政府專用的防偽印刷機印製,其底紋是由極細且連續流暢的幾何實線(如吉洛雪底紋)構成,微觀下油墨均勻且無顆粒感。
- 偽造影印(CMYK 半色調網點):市售的普通噴墨或雷射印表機受限於物理機制,無法印出連續的細線。它們是透過將青(C)、洋紅(M)、黃(Y)、黑(K)四種顏色的**微小網點(Halftone Dots)**以特定的角度與密度交錯排列,在視覺上呈現漸層色彩。
在手機相機的高解析度微距拍攝下,這些印刷網點特徵會暴露無遺。
演算法實現步驟與數學邏輯
我們不需要對整個證件進行分析,只需對證件的中央區域進行區塊切割(例如切分成數個 512x512 像素的區塊),並對每個區塊執行以下空間域的微觀邊緣特徵提取:
- 高通濾波(High-pass Filtering):使用拉普拉斯算子(Laplacian Kernel)提取圖像中亮度劇烈變化的微觀紋理細節,排除卡片漸層光影的低頻干擾: $$\Delta f = \frac{\partial^2 f}{\partial x^2} + \frac{\partial^2 f}{\partial y^2}$$
- 二值化門檻分割(Binarization):將拉普拉斯響應的絕對值以全局低門檻(例如值為 5)進行二值化分割,將極細微的邊緣和網點分離出來。
- 微觀輪廓提取與面積篩選:利用
cv2.findContours抓取所有獨立的微小邊緣輪廓,並篩選出面積極小(如 $A \in [1, 100]$ 像素)的輪廓數量,排除正常文字或卡片大邊界的干擾。 - 密度統計與判定:統計所有區塊中平均每個區塊所含有的微細輪廓數量。
- 真實實體證件:由於採用專業的平版/凹版印刷,底紋均勻且流暢,微細輪廓數量極少(通常每區塊小於 600 個)。
- 彩色影印證件:因為表面鋪滿了密密麻麻的半色調 CMYK 網點,這些網點會產生海量的微小邊緣,導致輪廓數量暴增 3.5 倍以上(通常每區塊大於 1,200 個)。藉此高低落差即可直接精確判定是否為彩色影印紙張。
4. Python + OpenCV 雙重防偽演算法實作
以下是完整的 Python 偵測程式碼,包含「螢幕翻拍(FFT)」與「紙張影印(網點分析)」兩大核心偵測模組:
import cv2
import numpy as np
# ==========================================
# 模組一:第一道防線 - 螢幕翻拍 FFT 偵測器
# ==========================================
def analyze_block_for_moire(block):
h, w = block.shape
f = np.fft.fft2(block)
fshift = np.fft.fftshift(f)
magnitude = 20 * np.log(np.abs(fshift) + 1)
mag_min = magnitude.min()
mag_max = magnitude.max()
if mag_max - mag_min == 0:
return False
mag_norm = (magnitude - mag_min) / (mag_max - mag_min)
cy, cx = h // 2, w // 2
mask = np.ones((h, w), dtype=np.uint8)
cv2.circle(mask, (cx, cy), 60, 0, -1)
mask[cy-10:cy+10, :] = 0
mask[:, cx-10:cx+10] = 0
high_freq_vals = mag_norm[mask == 1]
mean_hf = np.mean(high_freq_vals)
std_hf = np.std(high_freq_vals)
threshold = mean_hf + 3.5 * std_hf
peaks = np.sum(high_freq_vals > threshold)
if 3 < peaks < 100:
return True
return False
def check_screen_spoofing(gray_img, block_size=512, step=256, threshold_ratio=0.30):
h, w = gray_img.shape
moire_blocks = 0
total_blocks = 0
for y in range(0, h - block_size, step):
for x in range(0, w - block_size, step):
block = gray_img[y:y+block_size, x:x+block_size]
total_blocks += 1
if analyze_block_for_moire(block):
moire_blocks += 1
ratio = moire_blocks / total_blocks if total_blocks > 0 else 0.0
return ratio > threshold_ratio, ratio
# ==========================================
# 模組二:第二道防線 - 紙張影印微觀網點偵測器
# ==========================================
def check_paper_printing(gray_img, block_size=512, step=256, contour_threshold=1200):
h, w = gray_img.shape
total_contours = 0
blocks_counted = 0
# 取證件中心 50% 的區域進行分析 (避開背景桌面的干擾)
start_y = h // 4
end_y = 3 * h // 4
start_x = w // 4
end_x = 3 * w // 4
for y in range(start_y, end_y - block_size, step):
for x in range(start_x, end_x - block_size, step):
block = gray_img[y:y+block_size, x:x+block_size]
if block.shape == (block_size, block_size):
blocks_counted += 1
# Laplacian 高通濾波
laplacian = cv2.Laplacian(block, cv2.CV_64F)
laplacian_abs = np.uint8(np.absolute(laplacian))
# 門檻值設定為 5 以分離印刷網點與紙張背景
_, thresh = cv2.threshold(laplacian_abs, 5, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 統計大小介於 1 到 100 像素的微觀網點邊緣數量
small_cnts = 0
for c in contours:
area = cv2.contourArea(c)
if 1 <= area <= 100:
small_cnts += 1
total_contours += small_cnts
avg_contours = total_contours / blocks_counted if blocks_counted > 0 else 0
is_printed = avg_contours > contour_threshold
return is_printed, avg_contours
5. 生產環境落地優化策略
在將防偽技術推向實際業務系統時,請務必考慮以下實務問題:
- 「模糊」會抹殺摩爾紋(防範 Low-pass 陷阱):
如果使用者上傳了一張極度模糊、或者失焦的螢幕翻拍照片,因為模糊本質上是一個「低通濾波器(Low-pass Filter)」,它會將高頻的液晶像素網格與印刷細節網點全部濾掉。這時 FFT 演算法會因為測不到高頻尖峰而出現漏判。
- 對策:在進入上述分析前,必須先用拉普拉斯算子(Laplacian)計算影像的模糊度門檻。若圖像低於特定清晰度閥值,直接退件要求重新拍照。
- 多因子混合判定 Pipeline: 在商用產品中,建議將此技術與邊緣裁切檢測(檢測照片中是否拍到了電腦螢幕外框、滑鼠游標、反光眩光)相結合,構建多維度的防偽判斷邏輯,以達到最穩定的防護效果。