Skip to content

Commit d76d727

Browse files
authored
Add SkyAR module (#1218)
1 parent 1226702 commit d76d727

18 files changed

+667
-0
lines changed
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
## 模型概述
2+
* SkyAR 是一种用于视频中天空置换与协调的视觉方法,该方法能够在风格可控的视频中自动生成逼真的天空背景。
3+
* 该算法是一种完全基于视觉的解决方案,它的好处就是可以处理非静态图像,同时不受拍摄设备的限制,也不需要用户交互,可以处理在线或离线视频。
4+
* 算法主要由三个核心组成:
5+
* 天空抠图网络(Sky Matting Network):就是一种 Matting 图像分隔,用于检测视频帧中天空区域的视频,可以精确地获得天空蒙版。
6+
* 运动估计(Motion Estimation):恢复天空运动的运动估计器,使生成的天空与摄像机的运动同步。
7+
* 图像融合(Image Blending):将用户指定的天空模板混合到视频帧中。除此之外,还用于重置和着色,使混合结果在其颜色和动态范围内更具视觉逼真感。
8+
* 整体框架图如下:
9+
10+
![](http://p4.itc.cn/q_70/images03/20201114/42eaf00af8dd4aa4ae3c0cdc6e50b793.jpeg)
11+
* 参考论文:Zhengxia Zou. [Castle in the Sky: Dynamic Sky Replacement and Harmonization in Videos](https://arxiv.org/abs/2010.11800). CoRR, abs/2010.118003, 2020.
12+
* 官方开源项目: [jiupinjia/SkyAR](https://github.com/jiupinjia/SkyAR)
13+
## 模型安装
14+
```shell
15+
$hub install SkyAR
16+
```
17+
18+
## 效果展示
19+
* 原始视频:
20+
21+
![原始视频](https://img-blog.csdnimg.cn/20210126142046572.gif)
22+
23+
* 木星:
24+
25+
![木星](https://img-blog.csdnimg.cn/20210125211435619.gif)
26+
* 雨天:
27+
28+
![雨天](https://img-blog.csdnimg.cn/2021012521152492.gif)
29+
* 银河:
30+
31+
![银河](https://img-blog.csdnimg.cn/20210125211523491.gif)
32+
* 第九区飞船:
33+
34+
![第九区飞船](https://img-blog.csdnimg.cn/20210125211520955.gif)
35+
* 原始视频:
36+
37+
![原始视频](https://img-blog.csdnimg.cn/20210126142038716.gif)
38+
* 漂浮城堡:
39+
40+
![漂浮城堡](https://img-blog.csdnimg.cn/20210125211514997.gif)
41+
* 电闪雷鸣:
42+
43+
![电闪雷鸣](https://img-blog.csdnimg.cn/20210125211433591.gif)
44+
* 超级月亮:
45+
46+
![超级月亮](https://img-blog.csdnimg.cn/20210125211417524.gif)
47+
48+
## API 说明
49+
50+
```python
51+
def MagicSky(
52+
video_path, save_path, config='jupiter',
53+
is_rainy=False, preview_frames_num=0, is_video_sky=False, is_show=False,
54+
skybox_img=None, skybox_video=None, rain_cap_path=None,
55+
halo_effect=True, auto_light_matching=False,
56+
relighting_factor=0.8, recoloring_factor=0.5, skybox_center_crop=0.5
57+
)
58+
```
59+
60+
深度估计API
61+
62+
**参数**
63+
64+
* video_path(str):输入视频路径
65+
* save_path(str):视频保存路径
66+
* config(str): 预设 SkyBox 配置,所有预设配置如下,如果使用自定义 SkyBox,请设置为 None:
67+
```
68+
[
69+
'cloudy', 'district9ship', 'floatingcastle', 'galaxy', 'jupiter',
70+
'rainy', 'sunny', 'sunset', 'supermoon', 'thunderstorm'
71+
]
72+
```
73+
* skybox_img(str):自定义的 SkyBox 图像路径
74+
* skybox_video(str):自定义的 SkyBox 视频路径
75+
* is_video_sky(bool):自定义 SkyBox 是否为视频
76+
* rain_cap_path(str):自定义下雨效果视频路径
77+
* is_rainy(bool): 天空是否下雨
78+
* halo_effect(bool):是否开启 halo effect
79+
* auto_light_matching(bool):是否开启自动亮度匹配
80+
* relighting_factor(float): Relighting factor
81+
* recoloring_factor(float): Recoloring factor
82+
* skybox_center_crop(float):SkyBox center crop factor
83+
* preview_frames_num(int):设置预览帧数量,即只处理开头这几帧,设为 0,则为全部处理
84+
* is_show(bool):是否图形化预览
85+
86+
## 预测代码示例
87+
88+
```python
89+
import paddlehub as hub
90+
91+
model = hub.Module(name='SkyAR')
92+
93+
model.MagicSky(
94+
video_path=[path to input video path],
95+
save_path=[path to save video path]
96+
)
97+
```
98+
99+
## 模型相关信息
100+
101+
### 模型代码
102+
103+
https://github.com/jm12138/SkyAR_Paddle_GUI
104+
105+
### 依赖
106+
107+
paddlepaddle >= 2.0.0rc0
108+
109+
paddlehub >= 2.0.0rc0
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
import os
2+
import paddle.nn as nn
3+
from .skyfilter import SkyFilter
4+
from paddlehub.module.module import moduleinfo
5+
6+
7+
@moduleinfo(
8+
name="SkyAR",
9+
type="CV/Video_editing",
10+
author="jm12138",
11+
author_email="",
12+
summary="SkyAR",
13+
version="1.0.0"
14+
)
15+
class SkyAR(nn.Layer):
16+
def __init__(self, model_path=None):
17+
super(SkyAR, self).__init__()
18+
self.imgs = ['cloudy', 'district9ship', 'floatingcastle',
19+
'galaxy', 'jupiter', 'rainy', 'sunny', 'sunset', 'supermoon']
20+
self.videos = ['thunderstorm']
21+
if model_path:
22+
self.model_path = model_path
23+
else:
24+
self.model_path = os.path.join(self.directory, './ResNet50FCN')
25+
26+
def MagicSky(
27+
self, video_path, save_path, config='jupiter',
28+
is_rainy=False, preview_frames_num=0, is_video_sky=False, is_show=False,
29+
skybox_img=None, skybox_video=None, rain_cap_path=None,
30+
halo_effect=True, auto_light_matching=False,
31+
relighting_factor=0.8, recoloring_factor=0.5, skybox_center_crop=0.5
32+
):
33+
if config in self.imgs:
34+
skybox_img = os.path.join(
35+
self.directory, 'skybox', '%s.jpg' % config)
36+
skybox_video = None
37+
is_video_sky = False
38+
elif config in self.videos:
39+
skybox_img = None
40+
skybox_video = os.path.join(
41+
self.directory, 'skybox', '%s.mp4' % config)
42+
is_video_sky = True
43+
elif skybox_img:
44+
is_video_sky = False
45+
skybox_video = None
46+
elif is_video_sky and skybox_video:
47+
skybox_img = None
48+
else:
49+
raise 'please check your configs'
50+
51+
if not rain_cap_path:
52+
rain_cap_path = os.path.join(
53+
self.directory, 'rain_streaks', 'videoplayback.mp4')
54+
55+
skyfilter = SkyFilter(
56+
model_path=self.model_path,
57+
video_path=video_path,
58+
save_path=save_path,
59+
in_size=(384, 384),
60+
halo_effect=halo_effect,
61+
auto_light_matching=auto_light_matching,
62+
relighting_factor=relighting_factor,
63+
recoloring_factor=recoloring_factor,
64+
skybox_center_crop=skybox_center_crop,
65+
rain_cap_path=rain_cap_path,
66+
skybox_img=skybox_img,
67+
skybox_video=skybox_video,
68+
is_video=is_video_sky,
69+
is_rainy=is_rainy,
70+
is_show=is_show
71+
)
72+
73+
skyfilter.run(preview_frames_num)
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import cv2
2+
import numpy as np
3+
4+
__all__ = ['Rain']
5+
6+
7+
class Rain():
8+
def __init__(self, rain_cap_path, rain_intensity=1.0, haze_intensity=4.0, gamma=2.0, light_correction=0.9):
9+
self.rain_intensity = rain_intensity
10+
self.haze_intensity = haze_intensity
11+
self.gamma = gamma
12+
self.light_correction = light_correction
13+
self.frame_id = 1
14+
15+
self.cap = cv2.VideoCapture(rain_cap_path)
16+
17+
def _get_rain_layer(self):
18+
ret, frame = self.cap.read()
19+
if ret:
20+
rain_layer = frame
21+
else: # if reach the last frame, read from the begining
22+
self.cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
23+
ret, frame = self.cap.read()
24+
rain_layer = frame
25+
26+
rain_layer = cv2.cvtColor(rain_layer, cv2.COLOR_BGR2RGB) / 255.0
27+
rain_layer = np.array(rain_layer, dtype=np.float32)
28+
29+
return rain_layer
30+
31+
def _create_haze_layer(self, rain_layer):
32+
return 0.1*np.ones_like(rain_layer)
33+
34+
def forward(self, img):
35+
# get input image size
36+
h, w, c = img.shape
37+
38+
# create a rain layer
39+
rain_layer = self._get_rain_layer()
40+
41+
rain_layer = cv2.resize(rain_layer, (w, h))
42+
rain_layer = cv2.blur(rain_layer, (3, 3))
43+
rain_layer = rain_layer * \
44+
(1 - cv2.boxFilter(img, -1, (int(w/10), int(h/10))))
45+
46+
# create a haze layer
47+
haze_layer = self._create_haze_layer(rain_layer)
48+
49+
# combine the rain layer and haze layer together
50+
rain_layer = self.rain_intensity*rain_layer + \
51+
self.haze_intensity*haze_layer
52+
53+
# synthesize an output image (screen blend)
54+
img_out = 1 - (1 - rain_layer) * (1 - img)
55+
56+
# gamma and light correction
57+
img_out = self.light_correction*(img_out**self.gamma)
58+
59+
# check boundary
60+
img_out = np.clip(img_out, a_min=0, a_max=1.)
61+
62+
return img_out
Binary file not shown.

0 commit comments

Comments
 (0)