ACGPN首先預測參考圖片的semantic layout,透過它可以更恰當地決定要生成或保存內容,接著主要由三個模型來運作:
Semantic Generation Module(SGM):此模型分成兩階段的方式生成語意掩碼(semantic masks),首先使用語意分割(semantic segmentation)來逐步生成身體部位的掩碼,再合成扭曲服裝區域的掩碼。
Clothes Warping Module(CWM):此模型根據semantic layout扭曲服裝,並且在warping loss 中引入the second-order difference constraint 使warping過程中更加穩定,特別是對於較複雜的衣服。
Content Fusion Module(CFM):將合成的身體部位掩碼、扭曲後的衣服圖片以及原始身體部位圖片三種元素做結合,使其更恰當地決定生成或保存合成圖片中不同的人體部位。
有了以上三種模型,ACPGN在VITON上的實驗採用split-transform-merge策略來生成有空間感的試穿圖片,因此能生成最逼真的試穿圖片。
訓練資料集的部分使用VITON和CPVITON,它們包含了19000對圖片,每個圖片對包含女性正面照片以及上衣的圖片,並且在刪除無效的圖片對後,會產生16253對圖片,再進一步拆分為訓練集14221對以及測試集2032對。
ACGPN中包含SGM、CWM、CFM三種模型,其中SGM、CFM的生成器都具有與U-Net相同的結構,並且所有鑑別器都來自pix2pixHD。CWM中的STN結構以五個卷積層開始,再來是stride為2的Max-pooling,在訓練中所有圖像會先resize為256*192,再來使用PyTorch及GPU分別訓練模型以及將它們組合起來生成最終的試穿圖片。
ACGPN整體架構圖、資料來源:Han Yang,2020
程式一開始會先執行Reisze進來的圖片,將其Resize成我們需要的大小。
並開始執行Self-Correction-Human-Parsing-for-ACGPN/simple_extractor.py,將身體的label從Data_preprocessing/test_label內的2032張label圖片提取出來,製作成輸入圖片的label,若顯示out of memory ,將會直接跳過這一步,會讓圖片生產出來是錯誤的,因此若產生記憶體不足,也可從Self-Correction-Human-Parsing-for-ACGPN/simple_extractor.py內的gpu_ids做更改。
以下圖例為epoch=12的訓練結果。
+
=
紅色部分為原圖片人物站立的位子,但因記憶體不足,故直接跳過產生label的部分,讓原先的圖片套用到舊的label,產生怪怪的圖片。
+
=
這樣才是正常的。
+
=
以下為epoch=49之生成結果:
+
=
因ACGPN的github上沒有說明如何輸入自身的圖片及衣服的圖片進入並生成出來,故參照github上提供的colab程式碼(ACGPN.ipynb,程式碼內容可讓使用者輸入自身圖片及一幅圖片並生成)來觀察如何達成目的,寫了以下程式碼。
import gdown
import numpy as np
from PIL import Image
import IPython
import gdown
import os
import sys
from predict_pose import generate_pose_keypoints
sys.path.append('/users/cbf107/cbf107020/ACGPN-master/U_2_Net')
import u2net_run
import u2net_load
u2net = u2net_load.model(model_name='u2netp')
f = open('return.txt','r')
cloth_number = int(f.readlines()[0])
print(cloth_number)
cloth_name = '000001_1.png'
cloth_path = os.path.join('inputs/cloth', sorted(os.listdir('inputs/cloth'))[cloth_number])
cloth = Image.open(cloth_path)
cloth = cloth.resize((192, 256), Image.BICUBIC).convert('RGB')
cloth.save(os.path.join('Data_preprocessing/test_color', cloth_name))
u2net_run.infer(u2net, 'Data_preprocessing/test_color' , 'Data_preprocessing/test_edge')
import time
start_time = time.time()
img_name = '000001_0.png'
img_path = os.path.join('inputs/img', sorted(os.listdir('inputs/img'))[0])
img = Image.open(img_path)
img = img.resize((192,256), Image.BICUBIC)
img_path = os.path.join('Data_preprocessing/test_img', img_name)
img.save(img_path)
resize_time = time.time()
print('Resized image in {}s'.format(resize_time-start_time))
os.system("python3 Self-Correction-Human-Parsing-for-ACGPN/simple_extractor.py --dataset 'lip' --model-restore 'lip_final.pth' --input-dir 'Data_preprocessing/test_img' --output-dir 'Data_preprocessing/test_label'")
parse_time = time.time()
print('Parsing generated in {}s'.format(parse_time-resize_time))
pose_path = os.path.join('Data_preprocessing/test_pose', img_name.replace('.png', '_keypoints.json'))
generate_pose_keypoints(img_path, pose_path)
pose_time = time.time()
print('Pose map generated in {}s'.format(pose_time-parse_time))
os.system("rm -rf Data_preprocessing/test_pairs.txt")
with open('Data_preprocessing/test_pairs.txt','w') as f:
f.write('000001_0.png 000001_1.png')
os.system("python test.py")
os.system("rm -rf Data_preprocessing/test_color/*")
os.system("rm -rf Data_preprocessing/test_colormask/*")
os.system("rm -rf Data_preprocessing/test_edge/*")
os.system("rm -rf Data_preprocessing/test_img/*")
os.system("rm -rf Data_preprocessing/test_label/*")
os.system("rm -rf Data_preprocessing/test_mask/*")
os.system("rm -rf Data_preprocessing/test_pose/*")
#os.system("rm -rf inputs/cloth/*")
os.system("rm -rf inputs/img/*")