最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

功能上近似“秒鴨相機(jī)”?從代碼層面一探究竟阿里達(dá)摩院 FaceChain

2023-09-12 10:13 作者:極市平臺(tái)  | 我要投稿

作者丨wwdok

編輯丨極市平臺(tái)

本文首發(fā)于極市平臺(tái),轉(zhuǎn)載須經(jīng)授權(quán)并注明來(lái)源


facechain

  • 官方代碼:https://github.com/modelscope/facechain

  • 論文:《FaceChain: A Playground for Identity-Preserving Portrait Generation》

  • 我的注釋代碼:https://github.com/wwdok/facechain/tree/annotation

  • 魔搭體驗(yàn):https://www.modelscope.cn/studios/CVstudio/cv_human_portrait/summary

  • huggingface體驗(yàn):https://huggingface.co/spaces/modelscope/FaceChain

  • 視頻介紹:https://www.bilibili.com/video/BV12x4y1f7Ga

日期:2023/9/6 目前facechain還處于快速迭代中,當(dāng)你看到這篇文章時(shí),可能代碼倉(cāng)庫(kù)有了新變化。

FaceChain 是阿里達(dá)摩院開(kāi)源的一個(gè)功能上近似“秒鴨相機(jī)”的項(xiàng)目。作為程序員和AIGC愛(ài)好者,我決定從代碼層面看看它的實(shí)現(xiàn)流程是什么樣的。facechain,顧名思義,就是對(duì)人臉(face)做一連串(chain)的處理。那這些處理包括哪些呢,又是怎么串聯(lián)起來(lái)的呢?它的基本原理在官方文檔README_ZH.md里有介紹,這里再粘貼一下。整體工作流程圖是這樣的:

訓(xùn)練階段

輸入:用戶(hù)上傳的包含清晰人臉區(qū)域的圖像?

輸出:人臉LoRA模型?

描述:首先,我們分別使用基于朝向判斷的圖像旋轉(zhuǎn)模型,以及基于人臉檢測(cè)和關(guān)鍵點(diǎn)模型的人臉精細(xì)化旋轉(zhuǎn)方法處理用戶(hù)上傳圖像,得到包含正向人臉的圖像;接下來(lái),我們使用人體解析模型和人像美膚模型,以獲得高質(zhì)量的人臉訓(xùn)練圖像;隨后,我們使用人臉屬性模型和文本標(biāo)注模型,結(jié)合標(biāo)簽后處理方法,產(chǎn)生訓(xùn)練圖像的精細(xì)化標(biāo)簽;最后,我們使用上述圖像和標(biāo)簽數(shù)據(jù)微調(diào)Stable Diffusion模型得到人臉LoRA模型。


推斷階段

輸入:訓(xùn)練階段用戶(hù)上傳圖像,預(yù)設(shè)的用于生成個(gè)人寫(xiě)真的輸入提示詞?

輸出:個(gè)人寫(xiě)真圖像?

描述:首先,我們將人臉LoRA模型和風(fēng)格LoRA模型的權(quán)重融合到Stable Diffusion模型中;接下來(lái),我們使用Stable Diffusion模型的文生圖功能,基于預(yù)設(shè)的輸入提示詞初步生成個(gè)人寫(xiě)真圖像;隨后,我們使用人臉融合模型進(jìn)一步改善上述寫(xiě)真圖像的人臉細(xì)節(jié),其中用于融合的模板人臉通過(guò)人臉質(zhì)量評(píng)估模型在訓(xùn)練圖像中挑選;最后,我們使用人臉識(shí)別模型計(jì)算生成的寫(xiě)真圖像與模板人臉的相似度,以此對(duì)寫(xiě)真圖像進(jìn)行排序,并輸出排名靠前的個(gè)人寫(xiě)真圖像作為最終輸出結(jié)果。

安裝

為了了解背后的工作流程,我得先跑通代碼。安裝上與官方教程有所不同,因人而異。

  1. 克隆到本地:

GIT_LFS_SKIP_SMUDGE=1?git?clone?https://github.com/modelscope/facechain.git?--depth?1
cd?facechain

  1. 安裝依賴(lài)包。為了加快安裝速度,可以配置一下pip源或臨時(shí)使用國(guó)內(nèi)源。

pip3?install?-r?requirements.txt?-i?https://pypi.tuna.tsinghua.edu.cn/simple/

  1. 因?yàn)槲业腢buntu上是無(wú)GUI界面的,所以我得安裝headless版,而且最新版本會(huì)報(bào)錯(cuò):“partially initialized module 'CV2' has no attribute 'gapi_wip_gst_GStreamerPipeline' (most likely due to a circular import)”,解決辦法是先寫(xiě)卸載干凈opencv:

pip3?uninstall?opencv-python
pip3?uninstall?opencv-contrib-python
pip3?uninstall?opencv-python-headless
pip3?uninstall?opencv-contrib-python-headless

然后安裝headless的指定版本:

pip3?install?opencv-python-headless==4.4.0.46?-i?https://pypi.tuna.tsinghua.edu.cn/simple/
pip3?install?opencv-contrib-python-headless==4.4.0.46?-i?https://pypi.tuna.tsinghua.edu.cn/simple?

  1. 安裝mmcv,但mim install mmcv-full==1.7.0失敗,我改成用pip3 install mmcv-full==1.7.0.

  2. 我的服務(wù)器原本安裝的diffusers版本是0.14,結(jié)果報(bào)錯(cuò):“No module named 'diffusers.models.attention_processor'”,后面通過(guò)pip3 install diffusers -U -i https://pypi.tuna.tsinghua.edu.cn/simple/升級(jí)成0.20后就好了。onnxruntime也要升級(jí)到最新版,不然有報(bào)錯(cuò)的風(fēng)險(xiǎn)。

  3. 后面如果你運(yùn)行python app.py來(lái)啟動(dòng)web ui界面的話(huà),可能會(huì)遇到報(bào)錯(cuò):“ImportError: cannot import name 'DEFAULT_CIPHERS' from 'urllib3.util.ssl_' (/opt/conda/lib/python3.8/site-packages/urllib3/util/ssl_.py)”,這個(gè)原因是因?yàn)閡rllib3版本太高,太低的話(huà)又會(huì)另外一個(gè)報(bào)錯(cuò):“?init() got an unexpected keyword argument 'allowed_methods'”,安裝特定版本就可以了:pip install urllib3==1.26.16。

訓(xùn)練

雖然我的服務(wù)器是無(wú)GUI的ubuntu系統(tǒng),但實(shí)測(cè)仍然可以打開(kāi)gradio webui進(jìn)行訓(xùn)練和推理,不過(guò)下面的筆記仍然是用命令行的方式操作。

  1. 首先在根目錄下創(chuàng)建了文件夾 imgs,放入你要合成的人臉的照片,我這里的例子是從百度圖片下載下來(lái)的五月天阿信的照片,要求每張照片中只有一個(gè)主角人臉。代碼內(nèi)會(huì)自己選擇最相似、最可能是同一個(gè)人的最多15張圖片作為訓(xùn)練集,也就是說(shuō)你準(zhǔn)備的圖片太多也沒(méi)有太大用處,數(shù)量多不如質(zhì)量高。

  1. 運(yùn)行以下命令行啟動(dòng)訓(xùn)練:

PYTHONPATH=. sh train_lora.sh "ly261666/cv_portrait_model" "v2.0" "film/film" "./imgs" "./processed" "./output"

命令行中的ly261666/cv_portrait_model是一個(gè)預(yù)訓(xùn)練模型,也就是基模型leosamsMoonfilm_filmGrain20,不用修改,它來(lái)自https://modelscope.cn/models/ly261666/cv_portrait_model/summary。訓(xùn)練十幾分鐘就訓(xùn)練好了。但是,在訓(xùn)練前會(huì)下載很多依賴(lài)模型,這個(gè)時(shí)間可能就要半個(gè)小時(shí)以上。訓(xùn)練出來(lái)的LoRA模型位于facechain/output/pytorch_lora_weights.bin。

代碼解析

PYTHONPATH=. sh train_lora.sh "ly261666/cv_portrait_model" "v2.0" "film/film" "./imgs" "./processed" "./output"可知,我們執(zhí)行的是train_lora.sh,它里面又調(diào)用了facechain/train_text_to_image_lora.py,所以我們重點(diǎn)看一下這個(gè)train_text_to_image_lora.py這個(gè)文件。

train_text_to_image_lora.py 應(yīng)該是改編自:https://github.com/huggingface/diffusers/blob/main/examples/text_to_image/train_text_to_image_lora.py?,以后自己訓(xùn)練其他LoRA模型的話(huà),也可以基于這個(gè)腳本進(jìn)行改編。

我們直達(dá)它的def main()函數(shù),主要的兩個(gè)訓(xùn)練前處理函數(shù)的注釋如下:

#?note:?檢查圖片中的人臉是否需要旋轉(zhuǎn)角度,矯正過(guò)的圖片保存在processed文件夾內(nèi)
prepare_dataset(args.dataset_name,?args.output_dataset_name)
#?note:?背后調(diào)用的是class?Blipv2()的def?__call__()
#?依次對(duì)圖片進(jìn)行:縮放、檢測(cè)出人臉,將人臉矯正、縮放、裁剪出人臉區(qū)域、美膚、分割出人頭區(qū)域、
#?人臉關(guān)鍵點(diǎn)檢測(cè)(如果檢測(cè)不出或置信度低于閾值,則跳過(guò))、使用DeepDanbooru對(duì)分割出的人頭區(qū)域打標(biāo)簽、
#?估計(jì)人臉屬性(包括性別年齡,后處理會(huì)合并進(jìn)標(biāo)簽里)、生成的結(jié)果位于processed_labeled文件夾
data_process_fn(input_img_dir=args.output_dataset_name,?use_data_process=True)

函數(shù)data_process_fn里那么多處理步驟要用到模型列表(https://github.com/modelscope/facechain/blob/main/README_ZH.md#%E6%A8%A1%E5%9E%8B%E5%88%97%E8%A1%A8)里的很多模型。比如cv_ddsar_face-detection_iclr23-damofd負(fù)責(zé)檢測(cè)出圖片中的人臉,cv_resnet101_image-multiple-human-parsing負(fù)責(zé)分割出人頭區(qū)域、cv_unet_skin_retouching_torch負(fù)責(zé)對(duì)人臉美膚。因?yàn)橐螺d這些模型,所以這一步會(huì)比較耗時(shí)。

訓(xùn)練流程跟常規(guī)的stable diffusion訓(xùn)練一樣,沒(méi)啥特別之處,這里不再?gòu)?fù)述:

#?note:?開(kāi)始訓(xùn)練人臉LoRA模型
for?epoch?in?range(first_epoch,?args.num_train_epochs):

訓(xùn)練結(jié)束保存LoRA模型權(quán)重:

#?note:?使用diffusers的save_attn_procs保存LoRA模型權(quán)重,導(dǎo)出facechain/output/pytorch_lora_weights.bin
unet.save_attn_procs(args.output_dir,safe_serialization=False)

我們?cè)賮?lái)看看訓(xùn)練階段的中間產(chǎn)物。這是processed_labeled文件夾內(nèi)的內(nèi)容,也就是訓(xùn)練stable diffusion用的數(shù)據(jù)集:

可以看到人頭區(qū)域被分割了出來(lái),當(dāng)然它做過(guò)了矯正和美膚。metadata.jsonl里是每張圖片的標(biāo)簽,它里面的內(nèi)容就是:

推理

執(zhí)行推理的命令行是python run_inference.py。順利的話(huà),一會(huì)兒之后就能在generated文件夾內(nèi)看到5張合成的證件照了,效果如下(如果侵犯了肖像權(quán),請(qǐng)聯(lián)系我刪除掉):

我又跑了一次,生成的效果如下:

看完這些結(jié)果,我發(fā)現(xiàn)一個(gè)人的外貌特征除了五官外,還有發(fā)型、頭型、頭身比例,這些也很有區(qū)分度。

代碼解析

run_inference.py背后調(diào)用的主要是facechain\inference.py這個(gè)文件,讓我們來(lái)看一下這個(gè)文件。首先看def main_diffusion_inference的注釋?zhuān)?/p>

?pipe?=?StableDiffusionPipeline.from_pretrained(base_model_path,?torch_dtype=torch.float32)
?lora_style_path?=?style_model_path
?lora_human_path?=?lora_model_path
?# note:?將ly261666/cv_portrait_model這個(gè)基礎(chǔ)模型,連同我們訓(xùn)練的人物L(fēng)oRA模型和默認(rèn)風(fēng)格LoRA模型,三者的權(quán)重合并成一個(gè)新模型。
?pipe?=?merge_lora(pipe,?lora_style_path,?multiplier_style,?from_safetensor=True)
?pipe?=?merge_lora(pipe,?lora_human_path,?multiplier_human,?from_safetensor=lora_human_path.endswith('safetensors'))

使用融合三者權(quán)重后的擴(kuò)散模型進(jìn)行生圖,在txt2img函數(shù)內(nèi),你可以對(duì)其進(jìn)行進(jìn)一步的定制化(比如調(diào)節(jié)圖片寬高、去噪步數(shù)等):

?#?note:?萬(wàn)事具備,開(kāi)始運(yùn)行擴(kuò)散模型生成10張候選圖片
?images_style?=?txt2img(pipe,?trigger_style?+?add_prompt_style?+?pos_prompt,?neg_prompt,?num_images=10)

然后看class GenPortraitdef __call__的注釋?zhuān)?/p>

#?note:?內(nèi)部會(huì)調(diào)用擴(kuò)散模型生成10張候選圖片,也就是調(diào)用了上面的def?main_diffusion_inference
gen_results=main_model_inference(self.pose_model_path,self.pose_image,self.use_depth_control,
self.pos_prompt,self.neg_prompt,
self.style_model_path,self.multiplier_style,self.multiplier_human,
self.use_main_model,input_img_dir=input_img_dir,
lora_model_path=lora_model_path,base_model_path=base_model_path)
#?note:?從processed_labeled文件夾內(nèi)選擇一張質(zhì)量最好的摳出來(lái)的人頭圖片
selected_face=select_high_quality_face(input_img_dir)
#?note:?保存中間結(jié)果以便可視化(我自己加的)
intermediate_folder="./intermediate"
os.makedirs(intermediate_folder,exist_ok=True)
selected_face.save(os.path.join(intermediate_folder,"selected_face.jpg"))
fori,imginenumerate(gen_results):
img.save(os.path.join(intermediate_folder,f"{i}.jpg"))
#?note:?將gen_results列表里的10張圖片中的人臉都換成selected_face
swap_results=face_swap_fn(self.use_face_swap,gen_results,selected_face)
#?將10張換臉后的圖片的embedding和selected_face的embedding作比較,選出跟selected_face最相似的num_gen_images張圖片
rank_results=post_process_fn(self.use_post_process,swap_results,selected_face,
num_gen_images=num_gen_images)
#?stylization
final_gen_results=stylization_fn(self.use_stylization,rank_results)
returnfinal_gen_results

run_inference.py使用的是默認(rèn)風(fēng)格,默認(rèn)風(fēng)格其實(shí)也是一種風(fēng)格,這種風(fēng)格是zjz_mj_jiyi_small_addtxt_fromleo(https://www.modelscope.cn/models/Cherrytest/zjz_mj_jiyi_small_addtxt_fromleo/summary)。默認(rèn)風(fēng)格模型的話(huà)支持這些服裝風(fēng)格:工作服、盔甲風(fēng)、T恤衫、漢服風(fēng)、女士晚禮服、賽博朋克。如果是其他風(fēng)格模型,有鳳冠霞帔、冬季漢服、校服風(fēng)、婚紗風(fēng)、拍立得風(fēng)、仙女風(fēng),這些風(fēng)格模型自帶服裝風(fēng)格,不再支持自定義服裝風(fēng)格。

換臉用到的模型是:https://modelscope.cn/models/damo/cv_unet_face_fusion_torch/summary ,這讓我想到了deepfacelab也是用到了這個(gè)技術(shù)。

我在想,如果不換臉的話(huà),SD的原始輸出是什么樣的,于是我在代碼里加入了保存SD生圖后、換臉前的中間結(jié)果(即gen_results、selected_face)的代碼,可視化如下:

可以看到,SD輸出的原始輸出圖片中的人臉跟實(shí)際真人差距還是比較大,說(shuō)明光靠幾張圖片和LoRA很難學(xué)習(xí)到一個(gè)相似的人臉,還得靠cv_unet_face_fusion_torch來(lái)?yè)Q臉。

另外,我發(fā)現(xiàn)constants.py里的pos_prompt_with_clothpos_prompt_with_style自帶了slim body,我覺(jué)得這會(huì)降低相似度,畢竟每個(gè)人的體型是不一樣的,我刪除掉后重新生成了一下,整體效果好像好了一點(diǎn)點(diǎn):



功能上近似“秒鴨相機(jī)”?從代碼層面一探究竟阿里達(dá)摩院 FaceChain的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國(guó)家法律
北辰区| 富源县| 武隆县| 喜德县| 柘城县| 扶绥县| 河西区| 闽清县| 革吉县| 芮城县| 辽中县| 庄浪县| 应城市| 秀山| 广汉市| 从化市| 龙陵县| 周至县| 娄烦县| 盘山县| 浮山县| 宁陕县| 怀柔区| 哈尔滨市| 九龙县| 武山县| 淮北市| 德江县| 潮州市| 夏津县| 三明市| 闵行区| 朝阳市| 连云港市| 曲沃县| 聊城市| 恭城| 三明市| 深圳市| 册亨县| 台江县|