這頁講實際怎麼做的,包括幾個不那麼直覺、但實測後才知道非這樣不可的決定。

模型與流程

用的是 MiniMax H3 的圖生圖(image-to-image)能力,int8 量化版,搭一個把取樣步數壓到 4 步的 turbo LoRA。跑在自己的 RTX 5070 Ti 上,一張約 40 秒。照片不會離開這台機器, 七天後連同結果一起自動刪除。

三種變化要用三組提示詞

年齡編輯其實是三件不同的事,用同一段文字描述會三邊都做不好:

所以程式裡有一張路由表,依照「現在幾歲、想看幾歲」決定套哪一組描述, 以及一個叫 source fidelity 的參數要放多鬆:改骨架要放到 0.40,只改皮膚要壓到 0.80 以上。 壓不夠緊,模型就會直接換一張臉給你。

差 10 歲和差 40 歲不能寫同一句

這是今天才修好的。變老那邊本來就依年齡差分四段寫;變年輕那邊沒有, 不管差幾歲都只寫「法令紋變淺」。結果 70 歲要變 30 歲時,模型很聽話地照做,變淺一點點, 臉還是老的,只有頭髮變黑了。

改成分段之後,差 20 歲以上就不能寫「變淺」,要寫成絕對條件:沒有法令紋、沒有魚尾紋、 沒有眼袋、原圖上每一條皺紋都不存在。模型才會真的重畫那塊皮膚。

強化之後第一次跑出來,八字鬍被一起抹掉了。指令一強,模型會把鬍子當成 「要抹平的東西」。所以又補了一句:鬍子、鬍鬚、眉毛的形狀大小位置粗細都不准動。

表情偶爾會飄,還沒解決

改年齡的時候,模型偶爾會順手把表情也改掉:嚴肅的臉變成微微在笑、眼睛瞇起來。 提示詞裡早就寫了「表情、眼睛、嘴巴都要跟原圖一致」以及「皺紋是刻在皮膚上的,不是笑出來的」, 我也實測過再加一句更強硬的限制(眼睛不准瞇、沒在笑就不准笑),同一個隨機種子跑出來還是一樣。

所以問題不在提示詞,這是模型在目前這個保真度下的行為。真的遇到就重跑一次, 每次的隨機種子不同,結果會不一樣。

兒童變成人為什麼要看臉佔畫面多少

如果照片看得到身體,成長模板要寫「整個身體長大、頭相對變小」; 如果是大頭照,同一段話會讓模型硬生一個身體出來,把小孩的臉印在衣服上變成鬼影(實測發生過)。 所以上傳後會先用人臉偵測算出臉佔畫面的比例,低於 20% 才用全身版。

40 秒花在哪裡

一張約 40 秒,但那 40 秒不是平均分配的。逐節點量下來,把照片與文字指令編碼成模型 看得懂的形式將近 20 秒,是最久的一段;實際取樣只有 4 步,反而最短;把結果解碼回畫面 再花十幾秒。

所以「減少取樣步數」對總時間的幫助遠比直覺小。真正的大頭在編碼與解碼, 以及把模型權重搬進顯示記憶體。16 GB 的顯示卡裝不下原本 30 GB 的模型,每跑一次都得搬。這也是機器閒置後第一張特別慢的原因。

為什麼用通用的圖生圖模型,不用專門的年齡模型

市面上有專門做人臉年齡變換的模型,多半是在人臉資料集上訓練的 GAN。 它們對正臉大頭照的效果很好,但有兩個問題:只吃裁切好的人臉,背景與衣著會被丟掉; 而且訓練資料的人種與年齡分布會直接反映在結果上。

用通用的圖生圖模型加上寫得很細的指令,代價是速度慢、要自己控制 fidelity, 換來的是背景、衣著、構圖全部保留,而且同一套流程可以處理黑白老照片、 側四分之三臉、有帽子有眼鏡的照片。對「把家裡的舊照片拿來看」這個用途, 保留原本的畫面比把臉做得完美有用。

同一張照片跑兩次結果不一樣

每次生成都用不同的隨機種子,所以同一張照片、同一組設定,兩次的結果會有差異。 差異主要在細節與表情,年齡幅度不會亂跑。

這件事可以拿來用:如果某一次的表情或某個細節不理想,直接再跑一次通常就好, 不必先去改照片或調年齡。反過來說,這也表示我們沒辦法保證重現某一張特定的成品。

年齡下限 16 歲是怎麼擋的

擋的位置在後端的路由判斷裡,不是把前端的選項藏起來。 前端的數字欄位可以被繞過,後端不能。把目標年齡填成小於 16 的值, 請求會被拒絕,不會進到生成佇列。

臉部偵測用在兩個地方

上傳時會跑一次 YuNet 臉部偵測,回傳畫面裡最大那張臉的高度佔畫面的比例。 這個數字有兩個用途:判斷照片裡有沒有人(沒有就先提醒你), 以及決定兒童變成人時要用大頭版還是全身版的成長模板,門檻是 20%。

偵測不準的時候(例如戴帽子的側臉)一律放行,不會擋住你。 寧可讓少數照片做出奇怪的結果,也不要把正常的照片擋在門外。

內容安全

上傳的照片與生成的結果都會過一次自動檢查,判定為不適當的內容會被擋下並隔離, 不會進到生成佇列,也不會出現在任何地方。細節寫在隱私權政策。

回工具頁

站上其他工具

全部跑在同一台家用機器上;資料類工具用的是政府公開資料,每個都有寫清楚限制。