不知道你有沒有收過那種立體生日卡,打開來裡面的圖會分成好幾層,前面一層、後面一層,稍微轉一下角度,前面的東西會相對後面的東西移動一點點。就那麼一點點,但整張卡片就活了。
想讓一張靜態背景在鏡頭推拉時有一點空間感,做的就是那張卡片:把一張平的圖切成幾層,各層移動的幅度不同。不需要生成模型。兩個開源視覺模型就夠:Depth Anything V2 估每個像素的深度,SAM 2 切出前景物件的遮罩。把深度圖分成幾段、對照遮罩,就得到遠、中、近三個平面,算繪時各自以不同幅度移動。
兩個模型各做什麼
Depth Anything V2 是 2024 年發表的單張影像深度估計模型,輸入一張圖,輸出一張相對深度圖,越近越亮、越遠越暗,看起來像一張灰階的鬼片劇照。SAM 2 是 Meta 的分割模型,2.1 版有 Hiera Tiny 到 Large 幾個尺寸,自動遮罩產生器不用提示就能把畫面切成幾十個區域,這張桌子是一塊、那盞燈是一塊。
為什麼要兩個?深度圖決定「多遠」,遮罩決定「哪些像素屬於同一個東西」。只用深度圖的話,一張桌子的桌面和桌腳可能被判成不同深度,切層的時候桌子就斷成兩截,轉鏡頭的時候桌面飛走、桌腳留在原地,非常靈異。遮罩讓「同一個東西」留在同一層。
全部在 CPU 上
這兩個模型跑在一個獨立的 CPU 環境裡,CPU 版的 PyTorch,SAM 2 安裝時關掉 CUDA 擴充的編譯,SAM2_BUILD_CUDA=0。顯卡留給更需要它的工作,例如語音合成,那個才是真正的吃卡大戶。
成本量過:深度推論用四個執行緒 1.8 秒,含冷啟動 4.3 秒;SAM 的自動遮罩約四十二秒,四十七個或七十個區域差不多;每張合計一分鐘上下,峰值記憶體約 5.6 GB。每張背景只處理一次,結果重用。一分鐘聽起來很久,但想想你自己用繪圖軟體手動把一張圖去背切三層要多久,一分鐘是很划算的。
授權:只用 Small,而且要明講
這一段請一定要看,因為它會省你一場官司。
Depth Anything V2 的程式是 Apache-2.0,權重分兩種:Small 是 Apache-2.0,Base、Large、Giant 都是 CC-BY-NC-4.0。NC 是 non-commercial,不能商用。用途涉及商業就只能用 Small,而且要在程式裡明寫檔名,不允許自動換成較大的 checkpoint。
最陰險的是官方範例預設用的是最大的那一個。你照抄範例,程式跑起來很漂亮,深度圖比 Small 細緻很多,你很開心,然後你就踩進非商用授權了,而且是在你最沒有防備的時候。SAM 2 的程式和 2.1 的權重都是 Apache-2.0,這邊沒有陷阱。
兩個模型都釘在固定的 commit,程式檔對 GitHub 的 tree 驗證,LFS 權重對 Hugging Face 的 API 驗證,結果寫進一份清單。任何一項缺了,流程就把背景分層標記為關閉並附原因,畫面維持平面,不會半做。半做出來的東西最難處理,因為你不知道它是壞了還是本來就這樣。
視差刻意很小
我用的漂移振幅是 32×8 像素、週期十八秒,遠景相對中景約移動十八像素,前景約九到十像素。這是空間感,不是運鏡。回到立體卡片,你轉個五度會覺得它活了,轉九十度就會看到卡片後面的膠水。大幅運鏡會露出分層後面沒有補的洞,而補洞就得用生成模型,那是另一個授權和品質的世界。幅度就停在這裡。
知道工具做不到什麼
SAM 切出來的是遮罩,不是細髮邊緣的去背,也不會補被遮住的部分。Depth Anything 給的是相對深度,不是公尺,它只知道這個比那個近,不知道近多少。把它們當成「粗略但穩定的分層工具」,預期就會對,你就不會在某個晚上對著一根被切歪的頭髮生氣。
小劇場:這跟那些一鍵 3D 的 app 差在哪
「手機上不是有那種一鍵把照片變 3D 的 app 嗎?」
「有,而且效果比我這個好。」
「那你為什麼不用?」
「因為我要處理幾百張,要能跑在自己的機器上,要知道它用了什麼模型、授權能不能商用,還要每次結果一樣。app 一個都做不到。」
「聽起來很累。」
「是很累。但那種 app 哪天下架、哪天改條款、哪天開始收費,我一點辦法都沒有。自己的工具鏈至少壞掉的時候我知道為什麼。」
素材的授權跟模型分開算
模型是 Apache-2.0,不表示你丟進去的背景圖也可以商用。這是兩件完全不同的事,很多人會混在一起。實驗用的素材如果來自別人的免費素材庫,它們和衍生的分層只在本機製作時使用,不進發布包,這件事要寫進授權紀錄。工具乾淨、素材不乾淨,做出來的東西還是不乾淨。
那張立體生日卡我還留著,放在抽屜裡。每次調視差參數的時候我都會想起它,然後提醒自己:一點點就夠了,多了就會看到膠水。
兩個模型的來歷
Segment Anything 是 Meta 在 2023 年 4 月發表的,那篇論文最驚人的不是模型,是資料集:一千一百萬張圖、十一億個遮罩,用模型和人互相協助的方式標出來的。「Anything」這個字是認真的,它不認得「這是貓」,它只認得「這一塊是同一個東西」,所以它可以切任何它沒看過的東西。2024 年 7 月的 SAM 2 加上了影片,可以追蹤一個物件在連續畫面裡的遮罩,骨幹網路換成 Hiera,速度快了很多,這也是為什麼 Tiny 版可以在 CPU 上跑。
Depth Anything 是 2024 年 1 月出來的,香港大學和 TikTok 合作,V2 在同年 6 月。它的做法是先用一小批有標籤的資料訓練,再用那個模型替六千多萬張沒標籤的圖產生偽標籤,再用全部的資料訓練一次。名字裡的 Anything 跟 SAM 一樣是認真的:它對任何場景都給一張看起來合理的深度圖,室內、室外、動畫、照片。
這兩個模型放在一起用,是很多人不約而同想到的組合。一個管「多遠」,一個管「哪些在一起」,剛好互補。
常見的三個誤會
第一個誤會是「深度圖就是 3D」。它是每個像素一個「相對距離」,沒有背面、沒有體積、沒有遮擋後面的東西。你轉個大角度,後面是空的。這是為什麼視差要小。
第二個誤會是「SAM 會告訴你切出來的是什麼」。它不會,它只切,不命名。要知道那一塊是桌子還是燈,要另外一個模型。對分層的用途來說這反而好,我不需要知道那是什麼,知道它們是一塊就夠了。
第三個誤會是「用了 Small 版效果一定很差」。對分層這種粗略的用途,Small 和 Large 的差別幾乎看不出來,因為最後只分三層。用 Large 的人多半是照抄範例,不是真的需要。
一個週末可以試的小練習
不需要寫程式。找一張你拍的照片,最好有明顯的前景和背景,例如桌上一杯飲料、後面是窗戶。到 Depth Anything 或 SAM 的官方示範頁面(Hugging Face 上有),把照片丟進去,看深度圖和遮罩長什麼樣。
然後打開任何一個繪圖軟體,照著深度圖手動把照片切成三層:前景的杯子、中景的桌面、遠景的窗戶。把三層各自往左移不同的距離,前景移最多、遠景移最少,存一張圖;再往右移,存另一張。兩張圖快速切換看,你會看到那個立體卡片的效果。這半小時做的事就是程式在做的事,只是你用手。做過一次之後,你會很清楚為什麼視差要小,因為你會親眼看到層與層之間那條沒有內容的縫。
後記
那張立體生日卡是國小同學送的,上面是一隻貓咪從蛋糕裡跳出來。我當時覺得它是世界上最厲害的東西,怎麼會有人想到把圖分層。二十年後我在用兩個神經網路做同一件事,然後發現最難的部分跟當年做卡片的人遇到的一模一樣:層要切在哪裡,才會看起來是一個世界而不是三張紙。技術會變,這個問題不會。
專案頁面:github.com/DepthAnything/Depth-Anything-V2、github.com/facebookresearch/sam2
留言(0)
還沒有留言。讀完有想法,歡迎留下第一則。