From f5be3a9db0155fccf0e7e205d91200e59a373f44 Mon Sep 17 00:00:00 2001
From: lijianshe02 <48898730+lijianshe02@users.noreply.github.com>
Date: Fri, 6 Nov 2020 16:07:31 +0800
Subject: [PATCH] remove duplicate frames and keep timestamp, fix psgan docs
(#74)
* remove duplicate frames and keep timestamp, fix psgan docs
---
docs/en_US/tutorials/psgan.md | 6 +--
docs/zh_CN/tutorials/psgan.md | 8 +--
ppgan/apps/dain_predictor.py | 95 +++++++++++++++++++++++++----------
3 files changed, 76 insertions(+), 33 deletions(-)
diff --git a/docs/en_US/tutorials/psgan.md b/docs/en_US/tutorials/psgan.md
index 4b1f723..c5046bf 100644
--- a/docs/en_US/tutorials/psgan.md
+++ b/docs/en_US/tutorials/psgan.md
@@ -35,14 +35,14 @@ python tools/psgan_infer.py \
```
mv landmarks/makeup MT-Dataset/landmarks/makeup
mv landmarks/non-makeup MT-Dataset/landmarks/non-makeup
-mv landmarks/train_makeup.txt MT-Dataset/makeup.txt
-mv tlandmarks/train_non-makeup.txt MT-Dataset/non-makeup.txt
+cp landmarks/train_makeup.txt MT-Dataset/train_makeup.txt
+cp landmarks/train_non-makeup.txt MT-Dataset/train_non-makeup.txt
```
The final data directory should be looked like:
```
-data
+data/MT-Dataset
├── images
│ ├── makeup
│ └── non-makeup
diff --git a/docs/zh_CN/tutorials/psgan.md b/docs/zh_CN/tutorials/psgan.md
index 6b03960..5b5b2de 100644
--- a/docs/zh_CN/tutorials/psgan.md
+++ b/docs/zh_CN/tutorials/psgan.md
@@ -2,7 +2,7 @@
## 1. PSGAN原理
-[PSGAN](https://arxiv.org/abs/1909.06956)模型的任务是妆容迁移, 即将任意参照图像上的妆容迁移到不带妆容的源图像上。很多人像美化应用都需要这种技术。近来的一些妆容迁移方法大都基于生成对抗网络(GAN)。它们通常采用 CycleGAN 的框架,并在两个数据集上进行训练,即无妆容图像和有妆容图像。但是,现有的方法存在一个局限性:只在正面人脸图像上表现良好,没有为处理源图像和参照图像之间的姿态和表情差异专门设计模块。PSGAN是一种全新的姿态稳健可感知空间的生生成对抗网络。PSGAN 主要分为三部分:妆容提炼网络(MDNet)、注意式妆容变形(AMM)模块和卸妆-再化妆网络(DRNet)。这三种新提出的模块能让 PSGAN 具备上述的完美妆容迁移模型所应具备的能力。
+[PSGAN](https://arxiv.org/abs/1909.06956)模型的任务是妆容迁移, 即将任意参照图像上的妆容迁移到不带妆容的源图像上。很多人像美化应用都需要这种技术。近来的一些妆容迁移方法大都基于生成对抗网络(GAN)。它们通常采用 CycleGAN 的框架,并在两个数据集上进行训练,即无妆容图像和有妆容图像。但是,现有的方法存在一个局限性:只在正面人脸图像上表现良好,没有为处理源图像和参照图像之间的姿态和表情差异专门设计模块。PSGAN是一种全新的姿态稳健可感知空间的生成对抗网络。PSGAN 主要分为三部分:妆容提炼网络(MDNet)、注意式妆容变形(AMM)模块和卸妆-再化妆网络(DRNet)。这三种新提出的模块能让 PSGAN 具备上述的完美妆容迁移模型所应具备的能力。
@@ -35,13 +35,13 @@ python tools/psgan_infer.py \
```
mv landmarks/makeup MT-Dataset/landmarks/makeup
mv landmarks/non-makeup MT-Dataset/landmarks/non-makeup
-mv landmarks/train_makeup.txt MT-Dataset/makeup.txt
-mv tlandmarks/train_non-makeup.txt MT-Dataset/non-makeup.txt
+cp landmarks/train_makeup.txt MT-Dataset/train_makeup.txt
+cp landmarks/train_non-makeup.txt MT-Dataset/train_non-makeup.txt
```
最后数据集目录如下所示:
```
-data
+data/MT-Dataset
├── images
│ ├── makeup
│ └── non-makeup
diff --git a/ppgan/apps/dain_predictor.py b/ppgan/apps/dain_predictor.py
index 2e4b83d..28e0a62 100644
--- a/ppgan/apps/dain_predictor.py
+++ b/ppgan/apps/dain_predictor.py
@@ -82,14 +82,9 @@ class DAINPredictor(BasePredictor):
vidname = video_path.split('/')[-1].split('.')[0]
frames = sorted(glob.glob(os.path.join(out_path, '*.png')))
- orig_frames = len(frames)
- need_frames = orig_frames * times_interp
if self.remove_duplicates:
frames = self.remove_duplicate_frames(out_path)
- left_frames = len(frames)
- timestep = left_frames / need_frames
- num_frames = int(1.0 / timestep) - 1
img = imread(frames[0])
@@ -125,9 +120,11 @@ class DAINPredictor(BasePredictor):
if not os.path.exists(os.path.join(frame_path_combined, vidname)):
os.makedirs(os.path.join(frame_path_combined, vidname))
- for i in tqdm(range(frame_num - 1)):
+ for i in range(frame_num - 1):
first = frames[i]
second = frames[i + 1]
+ first_index = int(first.split('/')[-1].split('.')[-2])
+ second_index = int(second.split('/')[-1].split('.')[-2])
img_first = imread(first)
img_second = imread(second)
@@ -173,22 +170,43 @@ class DAINPredictor(BasePredictor):
padding_left:padding_left + int_width],
(1, 2, 0)) for item in y_
]
- time_offsets = [kk * timestep for kk in range(1, 1 + num_frames, 1)]
-
- count = 1
- for item, time_offset in zip(y_, time_offsets):
- out_dir = os.path.join(frame_path_interpolated, vidname,
- "{:0>6d}_{:0>4d}.png".format(i, count))
- count = count + 1
- imsave(out_dir, np.round(item).astype(np.uint8))
-
- num_frames = int(1.0 / timestep) - 1
+ if self.remove_duplicates:
+ num_frames = times_interp * (second_index - first_index) - 1
+ time_offsets = [
+ kk * timestep for kk in range(1, 1 + num_frames, 1)
+ ]
+ start = times_interp * first_index + 1
+ for item, time_offset in zip(y_, time_offsets):
+ out_dir = os.path.join(frame_path_interpolated, vidname,
+ "{:08d}.png".format(start))
+ imsave(out_dir, np.round(item).astype(np.uint8))
+ start = start + 1
+
+ else:
+ time_offsets = [
+ kk * timestep for kk in range(1, 1 + num_frames, 1)
+ ]
+
+ count = 1
+ for item, time_offset in zip(y_, time_offsets):
+ out_dir = os.path.join(
+ frame_path_interpolated, vidname,
+ "{:0>6d}_{:0>4d}.png".format(i, count))
+ count = count + 1
+ imsave(out_dir, np.round(item).astype(np.uint8))
input_dir = os.path.join(frame_path_input, vidname)
interpolated_dir = os.path.join(frame_path_interpolated, vidname)
combined_dir = os.path.join(frame_path_combined, vidname)
- self.combine_frames(input_dir, interpolated_dir, combined_dir,
- num_frames)
+
+ if self.remove_duplicates:
+ self.combine_frames_with_rm(input_dir, interpolated_dir,
+ combined_dir, times_interp)
+
+ else:
+ num_frames = int(1.0 / timestep) - 1
+ self.combine_frames(input_dir, interpolated_dir, combined_dir,
+ num_frames)
frame_pattern_combined = os.path.join(frame_path_combined, vidname,
'%08d.png')
@@ -223,6 +241,26 @@ class DAINPredictor(BasePredictor):
except Exception as e:
print(e)
+ def combine_frames_with_rm(self, input, interpolated, combined,
+ times_interp):
+ frames1 = sorted(glob.glob(os.path.join(input, '*.png')))
+ frames2 = sorted(glob.glob(os.path.join(interpolated, '*.png')))
+ num1 = len(frames1)
+ num2 = len(frames2)
+
+ for i in range(num1):
+ src = frames1[i]
+ index = int(src.split('/')[-1].split('.')[-2])
+ dst = os.path.join(combined,
+ '{:08d}.png'.format(times_interp * index))
+ shutil.copy2(src, dst)
+
+ for i in range(num2):
+ src = frames2[i]
+ imgname = src.split('/')[-1]
+ dst = os.path.join(combined, imgname)
+ shutil.copy2(src, dst)
+
def remove_duplicate_frames(self, paths):
def dhash(image, hash_size=8):
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
@@ -241,14 +279,19 @@ class DAINPredictor(BasePredictor):
for (h, hashed_paths) in hashes.items():
if len(hashed_paths) > 1:
- for p in hashed_paths[1:]:
- os.remove(p)
-
- frames = sorted(glob.glob(os.path.join(paths, '*.png')))
- for fid, frame in enumerate(frames):
- new_name = '{:08d}'.format(fid) + '.png'
- new_name = os.path.join(paths, new_name)
- os.rename(frame, new_name)
+ first_index = int(hashed_paths[0].split('/')[-1].split('.')[-2])
+ last_index = int(
+ hashed_paths[-1].split('/')[-1].split('.')[-2]) + 1
+ gap = 2 * (last_index - first_index) - 1
+ if gap > 9:
+ mid = len(hashed_paths) // 2
+ for p in hashed_paths[1:mid - 1]:
+ os.remove(p)
+ for p in hashed_paths[mid + 1:]:
+ os.remove(p)
+ else:
+ for p in hashed_paths[1:]:
+ os.remove(p)
frames = sorted(glob.glob(os.path.join(paths, '*.png')))
return frames
--
GitLab