Initial clean project import
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
## MODNet - Custom Portrait Video Matting Demo
|
||||
This is a MODNet portrait video matting demo that allows you to process custom videos.
|
||||
|
||||
### 1. Requirements
|
||||
The basic requirements for this demo are:
|
||||
- Ubuntu System
|
||||
- Python 3+
|
||||
|
||||
|
||||
### 2. Introduction
|
||||
We use ~400 unlabeled video clips (divided into ~50,000 frames) downloaded from the internet to perform SOC to adapt MODNet to the video domain. **Nonetheless, due to insufficient labeled training data (~3k labeled foregrounds), our model may still make errors in portrait semantics estimation under challenging scenes.** Besides, this demo does not currently support the OFD trick.
|
||||
|
||||
|
||||
For a better experience, please make sure your videos satisfy:
|
||||
|
||||
* the portrait and background are distinguishable, <i>i.e.</i>, are not similar
|
||||
* captured in soft and bright ambient lighting
|
||||
* the contents do not move too fast
|
||||
|
||||
### 3. Run Demo
|
||||
We recommend creating a new conda virtual environment to run this demo, as follow:
|
||||
|
||||
1. Clone the MODNet repository:
|
||||
```
|
||||
git clone https://github.com/ZHKKKe/MODNet.git
|
||||
cd MODNet
|
||||
```
|
||||
|
||||
2. Download the pre-trained model from this [link](https://drive.google.com/file/d/1Nf1ZxeJZJL8Qx9KadcYYyEmmlKhTADxX/view?usp=sharing) and put it into the folder `MODNet/pretrained/`.
|
||||
|
||||
|
||||
3. Create a conda virtual environment named `modnet` (if it doesn't exist) and activate it. Here we use `python=3.6` as an example:
|
||||
```
|
||||
conda create -n modnet python=3.6
|
||||
source activate modnet
|
||||
```
|
||||
|
||||
4. Install the required python dependencies (please make sure your CUDA version is supported by the PyTorch version installed):
|
||||
```
|
||||
pip install -r demo/video_matting/custom/requirements.txt
|
||||
```
|
||||
|
||||
5. Execute the main code:
|
||||
```
|
||||
python -m demo.video_matting.custom.run --video YOUR_VIDEO_PATH
|
||||
```
|
||||
where `YOUR_VIDEO_PATH` is the specific path of your video.
|
||||
There are some optional arguments:
|
||||
- `--result-type (default=fg)` : fg - save the alpha matte; fg - save the foreground
|
||||
- `--fps (default=30)` : fps of the result video
|
||||
@@ -0,0 +1,6 @@
|
||||
numpy
|
||||
Pillow
|
||||
opencv-python
|
||||
torch >= 1.0.0
|
||||
torchvision
|
||||
tqdm
|
||||
@@ -0,0 +1,114 @@
|
||||
import os
|
||||
import cv2
|
||||
import argparse
|
||||
import numpy as np
|
||||
from PIL import Image
|
||||
from tqdm import tqdm
|
||||
|
||||
import torch
|
||||
import torch.nn as nn
|
||||
import torchvision.transforms as transforms
|
||||
|
||||
from src.models.modnet import MODNet
|
||||
|
||||
|
||||
torch_transforms = transforms.Compose(
|
||||
[
|
||||
transforms.ToTensor(),
|
||||
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)),
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
def matting(video, result, alpha_matte=False, fps=30):
|
||||
# video capture
|
||||
vc = cv2.VideoCapture(video)
|
||||
|
||||
if vc.isOpened():
|
||||
rval, frame = vc.read()
|
||||
else:
|
||||
rval = False
|
||||
|
||||
if not rval:
|
||||
print('Failed to read the video: {0}'.format(video))
|
||||
exit()
|
||||
|
||||
num_frame = vc.get(cv2.CAP_PROP_FRAME_COUNT)
|
||||
h, w = frame.shape[:2]
|
||||
if w >= h:
|
||||
rh = 512
|
||||
rw = int(w / h * 512)
|
||||
else:
|
||||
rw = 512
|
||||
rh = int(h / w * 512)
|
||||
rh = rh - rh % 32
|
||||
rw = rw - rw % 32
|
||||
|
||||
# video writer
|
||||
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
||||
video_writer = cv2.VideoWriter(result, fourcc, fps, (w, h))
|
||||
|
||||
print('Start matting...')
|
||||
with tqdm(range(int(num_frame)))as t:
|
||||
for c in t:
|
||||
frame_np = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
|
||||
frame_np = cv2.resize(frame_np, (rw, rh), cv2.INTER_AREA)
|
||||
|
||||
frame_PIL = Image.fromarray(frame_np)
|
||||
frame_tensor = torch_transforms(frame_PIL)
|
||||
frame_tensor = frame_tensor[None, :, :, :]
|
||||
if GPU:
|
||||
frame_tensor = frame_tensor.cuda()
|
||||
|
||||
with torch.no_grad():
|
||||
_, _, matte_tensor = modnet(frame_tensor, True)
|
||||
|
||||
matte_tensor = matte_tensor.repeat(1, 3, 1, 1)
|
||||
matte_np = matte_tensor[0].data.cpu().numpy().transpose(1, 2, 0)
|
||||
if alpha_matte:
|
||||
view_np = matte_np * np.full(frame_np.shape, 255.0)
|
||||
else:
|
||||
view_np = matte_np * frame_np + (1 - matte_np) * np.full(frame_np.shape, 255.0)
|
||||
view_np = cv2.cvtColor(view_np.astype(np.uint8), cv2.COLOR_RGB2BGR)
|
||||
view_np = cv2.resize(view_np, (w, h))
|
||||
video_writer.write(view_np)
|
||||
|
||||
rval, frame = vc.read()
|
||||
c += 1
|
||||
|
||||
video_writer.release()
|
||||
print('Save the result video to {0}'.format(result))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('--video', type=str, required=True, help='input video file')
|
||||
parser.add_argument('--result-type', type=str, default='fg', choices=['fg', 'matte'],
|
||||
help='matte - save the alpha matte; fg - save the foreground')
|
||||
parser.add_argument('--fps', type=int, default=30, help='fps of the result video')
|
||||
|
||||
print('Get CMD Arguments...')
|
||||
args = parser.parse_args()
|
||||
|
||||
if not os.path.exists(args.video):
|
||||
print('Cannot find the input video: {0}'.format(args.video))
|
||||
exit()
|
||||
|
||||
print('Load pre-trained MODNet...')
|
||||
pretrained_ckpt = './pretrained/modnet_webcam_portrait_matting.ckpt'
|
||||
modnet = MODNet(backbone_pretrained=False)
|
||||
modnet = nn.DataParallel(modnet)
|
||||
|
||||
GPU = True if torch.cuda.device_count() > 0 else False
|
||||
if GPU:
|
||||
print('Use GPU...')
|
||||
modnet = modnet.cuda()
|
||||
modnet.load_state_dict(torch.load(pretrained_ckpt))
|
||||
else:
|
||||
print('Use CPU...')
|
||||
modnet.load_state_dict(torch.load(pretrained_ckpt, map_location=torch.device('cpu')))
|
||||
modnet.eval()
|
||||
|
||||
result = os.path.splitext(args.video)[0] + '_{0}.mp4'.format(args.result_type)
|
||||
alpha_matte = True if args.result_type == 'matte' else False
|
||||
matting(args.video, result, alpha_matte, args.fps)
|
||||
Reference in New Issue
Block a user