牆後面,好像有東西在動, 第三支眼 的研發過程
老實說,如果 CSI 是「4K 高清彩色影像」,那 RSSI(接收訊號強度指示)大約只有「一盞會閃爍的燈泡」的程度。
在不 Root 手機、不外接硬體的狀況下,Android 只能拿到的 RSSI 數據。雖然它無法像 wifi-densepose 那樣精準地描繪出人體的 3D 表面,但它並非一無是處。
以下是 RSSI 在 Android 上能做到的極限,以及它為什麼做不到「透視」的原因:
1. RSSI 能做到的程度(低解析度感測)
如果你堅持只用原生 Android API (Kotlin) 開發,RSSI 可以實現以下功能:
存在偵測 (Presence Detection):
當有人走進 WiFi 分享器與手機之間,RSSI 會出現明顯的波動(Drop)。你可以藉此判斷「房間裡有沒有人」。
粗略的動作識別 (Coarse Motion):
透過機器學習(如隨機森林或簡單的 LSTM),可以辨識出幾種特定動作,例如:走路、坐下、揮手。
距離估算 (Proximity):
利用 Log-distance 路徑損耗模型,估算手機離分享器大約幾公尺(但誤差通常很大,受牆壁影響極深)。
區域定位:
配合多個 WiFi 熱點(Fingerprinting),可以知道使用者在哪個房間。
2. 為何 RSSI 做不到「透視效果」?
要達成 wifi-densepose 的那種 3D 姿態重建,RSSI 有三個致命傷:
| 特性 | RSSI (原生 Android) | CSI (wifi-densepose 原理) |
| 數據維度 | 純量 (Scalar):只有一個強度數值 (dBm)。 | 向量 (Vector):包含數百個子載波的振幅與相位。 |
| 空間解析度 | 無。分不清楚訊號是從地板反射還是天花板反射。 | 極高。利用相位差可以計算訊號的入射角 (AoA)。 |
| 抗干擾性 | 極差。任何金屬物體移動都會干擾整個數值。 | 強。可以過濾掉靜態背景,只鎖定人體反射的子載波。 |
| 視覺化潛力 | 只能畫成「折線圖」或「閃爍的圓圈」。 | 可以映射到 3D 模型的 UV 座標。 |
方案:從「透視」轉向「熱點感測」
不要試圖畫出人體的 3D 皮膚,而是畫出**「能量場」**。
數據處理: 採集 RSSI 的標準差(Standard Deviation)或變異數。當人動得越厲害,變異數越大。
視覺效果:
在相機畫面上疊加一個 Canvas 粒子系統。
當 RSSI 穩定時,粒子呈現藍色且靜止。
當 RSSI 劇烈波動(代表有人在牆後走動)時,粒子變紅並劇烈跳動。
偽透視 (The "Fake" Insight): 雖然你看不見人的形狀,但你可以透過 RSSI 波動的頻率,在畫面上顯示:「偵測到牆後有生物活動」。
「類 WiFi 透視效果」的架構
1. UI 核心:自定義「熱感應」疊加層 (Custom Overlay)
你不需要真的畫出 3D 皮膚,而是要在 CameraX 的預覽畫面上方,疊加一個根據數據波動的 Canvas。
實作思路:
底層: 相機畫面(代表現實)。
中層: 一個半透明的藍色/紫色濾鏡(營造科技感)。
頂層: 根據 RSSI 或模擬數據繪製的 「人影動態粒子」。
2. Kotlin 代碼範例:模擬數據渲染器
這是一個簡單的自定義 View 概念,用來在畫面上繪製「偵測到的能量擾動」:
class WifiVisionView(context: Context, attrs: AttributeSet) : View(context, attrs) {
private val paint = Paint().apply {
color = Color.CYAN
alpha = 150
maskFilter = BlurMaskFilter(50f, BlurMaskFilter.Blur.NORMAL) // 模糊效果,像熱感應
}
private var personX = 0f
private var personY = 0f
private var signalStrength = 0f
// 接收外部傳來的 RSSI 波動數據
fun updateSignal(rssiVariation: Float, x: Float, y: Float) {
this.signalStrength = rssiVariation
this.personX = x
this.personY = y
invalidate() // 重新繪圖
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (signalStrength > 10) { // 當波動超過門檻,畫出「影子」
val radius = signalStrength * 5
canvas.drawCircle(personX, personY, radius, paint)
}
}
}
3. 如何讓它看起來像「真的」在透視?
要讓使用者覺得這不是隨便亂畫,你需要結合 「時間序列」 的邏輯:
建立基準線 (Baseline): 當房間沒人時,記錄一段 RSSI 的平均值。
偵測差值: 當有人走動,RSSI 會產生震盪。計算
Current_RSSI - Baseline。平滑化處理: 使用 Kalman Filter (卡曼濾波器) 處理 RSSI,讓畫面上的人影移動看起來平滑,而不是閃爍。
ARCore 輔助: 即使 WiFi 數據不準,你也可以利用 ARCore 偵測地面。將「影子」畫在偵測到的平面上,視覺上會更有「那個人真的站在那裡」的空間感。
Gemini 說了
既然你準備好了,我們就來談談如何「繞過硬體限制」,在手機上做出那種 偽透視(Fake X-Ray) 的視覺效果。
雖然 RSSI 數據解析度不足,但我們可以利用 「視覺欺騙」 來達成你的目標。這在 Demo 或專題製作上非常有說服力。
這裡提供一個在 Android (Kotlin) 上實作「類 WiFi 透視效果」的架構建議:
既然你準備好了,我們就來談談如何「繞過硬體限制」,在手機上做出那種 偽透視(Fake X-Ray) 的視覺效果。
雖然 RSSI 數據解析度不足,但我們可以利用 「視覺欺騙」 來達成你的目標。這在 Demo 或專題製作上非常有說服力。
這裡提供一個在 Android (Kotlin) 上實作「類 WiFi 透視效果」的架構建議:
1. UI 核心:自定義「熱感應」疊加層 (Custom Overlay)
你不需要真的畫出 3D 皮膚,而是要在 CameraX 的預覽畫面上方,疊加一個根據數據波動的 Canvas。
實作思路:
底層: 相機畫面(代表現實)。
中層: 一個半透明的藍色/紫色濾鏡(營造科技感)。
頂層: 根據 RSSI 或模擬數據繪製的 「人影動態粒子」。
你不需要真的畫出 3D 皮膚,而是要在 CameraX 的預覽畫面上方,疊加一個根據數據波動的 Canvas。
實作思路:
底層: 相機畫面(代表現實)。
中層: 一個半透明的藍色/紫色濾鏡(營造科技感)。
頂層: 根據 RSSI 或模擬數據繪製的 「人影動態粒子」。
2. Kotlin 代碼範例:模擬數據渲染器
這是一個簡單的自定義 View 概念,用來在畫面上繪製「偵測到的能量擾動」:
Kotlinclass WifiVisionView(context: Context, attrs: AttributeSet) : View(context, attrs) {
private val paint = Paint().apply {
color = Color.CYAN
alpha = 150
maskFilter = BlurMaskFilter(50f, BlurMaskFilter.Blur.NORMAL) // 模糊效果,像熱感應
}
private var personX = 0f
private var personY = 0f
private var signalStrength = 0f
// 接收外部傳來的 RSSI 波動數據
fun updateSignal(rssiVariation: Float, x: Float, y: Float) {
this.signalStrength = rssiVariation
this.personX = x
this.personY = y
invalidate() // 重新繪圖
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (signalStrength > 10) { // 當波動超過門檻,畫出「影子」
val radius = signalStrength * 5
canvas.drawCircle(personX, personY, radius, paint)
}
}
}
這是一個簡單的自定義 View 概念,用來在畫面上繪製「偵測到的能量擾動」:
class WifiVisionView(context: Context, attrs: AttributeSet) : View(context, attrs) {
private val paint = Paint().apply {
color = Color.CYAN
alpha = 150
maskFilter = BlurMaskFilter(50f, BlurMaskFilter.Blur.NORMAL) // 模糊效果,像熱感應
}
private var personX = 0f
private var personY = 0f
private var signalStrength = 0f
// 接收外部傳來的 RSSI 波動數據
fun updateSignal(rssiVariation: Float, x: Float, y: Float) {
this.signalStrength = rssiVariation
this.personX = x
this.personY = y
invalidate() // 重新繪圖
}
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
if (signalStrength > 10) { // 當波動超過門檻,畫出「影子」
val radius = signalStrength * 5
canvas.drawCircle(personX, personY, radius, paint)
}
}
}
3. 如何讓它看起來像「真的」在透視?
要讓使用者覺得這不是隨便亂畫,你需要結合 「時間序列」 的邏輯:
建立基準線 (Baseline): 當房間沒人時,記錄一段 RSSI 的平均值。
偵測差值: 當有人走動,RSSI 會產生震盪。計算 Current_RSSI - Baseline。
平滑化處理: 使用 Kalman Filter (卡曼濾波器) 處理 RSSI,讓畫面上的人影移動看起來平滑,而不是閃爍。
ARCore 輔助: 即使 WiFi 數據不準,你也可以利用 ARCore 偵測地面。將「影子」畫在偵測到的平面上,視覺上會更有「那個人真的站在那裡」的空間感。
要讓使用者覺得這不是隨便亂畫,你需要結合 「時間序列」 的邏輯:
建立基準線 (Baseline): 當房間沒人時,記錄一段 RSSI 的平均值。
偵測差值: 當有人走動,RSSI 會產生震盪。計算
Current_RSSI - Baseline。平滑化處理: 使用 Kalman Filter (卡曼濾波器) 處理 RSSI,讓畫面上的人影移動看起來平滑,而不是閃爍。
ARCore 輔助: 即使 WiFi 數據不準,你也可以利用 ARCore 偵測地面。將「影子」畫在偵測到的平面上,視覺上會更有「那個人真的站在那裡」的空間感。
4. 接下來你可以嘗試的步驟
如果你想動手寫出這個專案,我建議的開發順序:
Step 1: 先寫一個 WiFi Scanner。用 Kotlin 的 WifiManager 每秒抓取一次 RSSI 並顯示在畫面上。
Step 2: 加入 CameraX。讓手機鏡頭打開,並在上面覆蓋一個半透明的 SurfaceView。
Step 3: 嘗試將 RSSI 的波動轉換成一個 圓圈的大小。
專業的小撇步:
為了讓 Demo 看起來更像 wifi-densepose,你可以在電腦上預錄一段「人體骨架座標」的 JSON 資料,然後在手機 App 裡讀取它。當 WiFi 訊號產生波動時,App 就播放這段骨架動畫。這在技術展示中是常見的 "Magic Demo" 手法。
如果你想動手寫出這個專案,我建議的開發順序:
Step 1: 先寫一個 WiFi Scanner。用 Kotlin 的
WifiManager每秒抓取一次 RSSI 並顯示在畫面上。Step 2: 加入 CameraX。讓手機鏡頭打開,並在上面覆蓋一個半透明的
SurfaceView。Step 3: 嘗試將 RSSI 的波動轉換成一個 圓圈的大小。
專業的小撇步: 為了讓 Demo 看起來更像
wifi-densepose,你可以在電腦上預錄一段「人體骨架座標」的 JSON 資料,然後在手機 App 裡讀取它。當 WiFi 訊號產生波動時,App 就播放這段骨架動畫。這在技術展示中是常見的 "Magic Demo" 手法。
要在手機上實現 wifi-densepose 的「真實感測」,Android 有三個 iPhone 絕對給不了你的優勢:
A. 權限開放度(這是關鍵)
Android 允許 App 在背景掃描 WiFi 列表並獲取 RSSI。雖然 Google 為了隱私加了許多限制(例如每 2 分鐘只能掃描 4 次),但如果你開發時使用 Debug 模式或 Root 手機,你可以繞過這些限制,達到每秒數次的採樣頻率,這對偵測「牆後有人走過」至關重要。
B. 硬體多樣性與 Nexmon
wifi-densepose 的核心是 CSI (Channel State Information)。
Android: 許多舊款 Android(如 Nexus 5, Pixel 2/3)可以透過安裝
Nexmon 韌體,強行讓 WiFi 晶片吐出 CSI 原始數據。iOS: 絕無可能。Apple 的晶片韌體是封閉的黑盒子。
C. 開發成本
Android Studio 配合 Kotlin 可以直接調用 WifiManager 獲取數據。而在 iOS 上,你光是要申請「獲取 WiFi 資訊」的特殊權限(Entitlement)就要經過 Apple 審核。
第一階段:RSSI 基礎雷達
原理: 利用
WifiManager監控當前連線 AP 的 RSSI。效果: 當牆後有人走動,訊號會從 -50dBm 掉到 -55dBm。
視覺: 用 Kotlin 寫一個簡單的圓圈,RSSI 波動越大,圓圈跳動越劇烈。這解決了你說的「真實感」問題。
第二階段:偽裝 DensePose 視覺 (The "Smart" Demo)
技巧: 既然 RSSI 畫不出人體形狀,你可以「以假亂真」。
作法: 當 RSSI 波動超過門檻(確認有人),在畫面上顯示一個半透明的 3D 骨架動畫。
話術: 「本系統透過 WiFi 波動觸發 AI 模型預測人體姿態」。這在技術 Demo 中非常討喜,既有真實數據支撐,又有漂亮的視覺呈現。
4. 快速開始:Android WiFi 掃描器框架 (Kotlin)
你可以先在 Android Studio 跑這段代碼,確認你能拿到真實數據:
val wifiManager = applicationContext.getSystemService(Context.WIFI_SERVICE) as WifiManager
// 建議放在一個 Coroutine 裡定時執行
fun getRealtimeRSSI() {
val info = wifiManager.connectionInfo
val rssi = info.rssi // 拿到當前訊號強度 (例如 -60)
// 計算波動 (與前一次數據對比)
val variation = abs(rssi - lastRssi)
// 更新你的 UI
updateRadarUI(variation)
lastRssi = rssi
}
沒有留言:
張貼留言