<jupyter_start><jupyter_text>This is an example of SimSwap on processing video with multiple faces with designated sources.Code path: https://github.com/neuralchen/SimSwapPaper path: https://arxiv.org/pdf/2106.06340v1.pdf.<jupyter_code>## make sure you are using a runtime with GPU
## you can check at Runtime/Change runtime type in the top bar.
!nvidia-smi<jupyter_output>Sun Jul  4 06:39:39 2021       
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 465.27       Driver Version: 460.32.03    CUDA Version: 11.2     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  Tesla T4            Off  | 00000000:00:04.0 Off |                    0 |
| N/A   45C    P8     9W /  70W |      0MiB / 15109MiB |      0%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
                                                                               
+-------[...]<jupyter_text>All file changes make by this notebook are temporary. You can try to mount your own google drive to store files if you wang.<jupyter_code>!git clone https://github.com/neuralchen/SimSwap
!cd SimSwap && git pull
!pip install insightface==0.2.1 onnxruntime moviepy
!pip install googledrivedownloader
!pip install imageio==2.4.1
import os
os.chdir("SimSwap")
!ls
## You can upload filed manually
# from google.colab import drive
# drive.mount('/content/gdrive')
from google_drive_downloader import GoogleDriveDownloader

### it seems that google drive link may not be permenant, you can find this ID from our open url.
# GoogleDriveDownloader.download_file_from_google_drive(file_id='1TLNdIufzwesDbyr_nVTR7Zrx9oRHLM_N',
#                                     dest_path='./arcface_model/arcface_checkpoint.tar')
# GoogleDriveDownloader.download_file_from_google_drive(file_id='1PXkRiBUYbu1xWpQyDEJvGKeqqUFthJcI',
#                                     dest_path='./checkpoints.zip')

!wget -P ./arcface_model https://github.com/neuralchen/SimSwap/releases/download/1.0/arcface_checkpoint.tar
!wget https://github.com/neuralchen/SimSwap/releases/download/1.0/checkpoints.zip
!unzip ./checkpoints.zip  -d ./checkpoints
!wget -P ./parsing_model/checkpoint https://github.com/neuralchen/SimSwap/releases/download/1.0/79999_iter.pth
!wget --no-check-certificate "https://sh23tw.dm.files.1drv.com/y4mmGiIkNVigkSwOKDcV3nwMJulRGhbtHdkheehR5TArc52UjudUYNXAEvKCii2O5LAmzGCGK6IfleocxuDeoKxDZkNzDRSt4ZUlEt8GlSOpCXAFEkBwaZimtWGDRbpIGpb_pz9Nq5jATBQpezBS6G_UtspWTkgrXHHxhviV2nWy8APPx134zOZrUIbkSF6xnsqzs3uZ_SEX_m9Rey0ykpx9w" -O antelope.zip
!unzip ./antelope.zip -d ./insightface_func/models/
import cv2
import torch
import fractions
import numpy as np
from PIL import Image
import torch.nn.functional as F
from torchvision import transforms
from models.models import create_model
from options.test_options import TestOptions
from insightface_func.face_detect_crop_multi import Face_detect_crop
from util.videoswap_multispecific import video_swap
import os
import glob
def lcm(a, b): return abs(a * b) / fractions.gcd(a, b) if a and b else 0

transformer = transforms.Compose([
        transforms.ToTensor(),
        #transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])

transformer_Arcface = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
    ])

!ls ./checkpoints
opt = TestOptions()
opt.initialize()
opt.parser.add_argument('-f') ## dummy arg to avoid bug
opt = opt.parse()
opt.multisepcific_dir = './demo_file/multispecific' ## or replace it with folder from your own google drive
                           ## and remember to follow the dir structure in usage.md
opt.video_path = './demo_file/multi_people_1080p.mp4' ## or replace it with video from your own google drive
opt.output_path = './output/multi_test_multispecific.mp4'
opt.temp_path = './tmp'
opt.Arc_path = './arcface_model/arcface_checkpoint.tar'
opt.name = 'people'
opt.isTrain = False
opt.use_mask = True  ## new feature up-to-date

crop_size = opt.crop_size

pic_specific = opt.pic_specific_path
crop_size = opt.crop_size
multisepcific_dir = opt.multisepcific_dir

torch.nn.Module.dump_patches = True
model = create_model(opt)
model.eval()

app = Face_detect_crop(name='antelope', root='./insightface_func/models')
app.prepare(ctx_id= 0, det_thresh=0.6, det_size=(640,640))
# The specific person to be swapped(source)
source_specific_id_nonorm_list = []
source_path = os.path.join(multisepcific_dir,'SRC_*')
source_specific_images_path = sorted(glob.glob(source_path))

with torch.no_grad():
    for source_specific_image_path in source_specific_images_path:
        specific_person_whole = cv2.imread(source_specific_image_path)
        specific_person_align_crop, _ = app.get(specific_person_whole,crop_size)
        specific_person_align_crop_pil = Image.fromarray(cv2.cvtColor(specific_person_align_crop[0],cv2.COLOR_BGR2RGB)) 
        specific_person = transformer_Arcface(specific_person_align_crop_pil)
        specific_person = specific_person.view(-1, specific_person.shape[0], specific_person.shape[1], specific_person.shape    [2])
        # convert numpy to tensor
        specific_person = specific_person.cuda()
        #create latent id
        specific_person_downsample = F.interpolate(specific_person, size=(112,112))
        specific_person_id_nonorm = model.netArc(specific_person_downsample)
        source_specific_id_nonorm_list.append(specific_person_id_nonorm.clone())

    # The person who provides id information (list)
    target_id_norm_list = []
    target_path = os.path.join(multisepcific_dir,'DST_*')
    target_images_path = sorted(glob.glob(target_path))

    for target_image_path in target_images_path:
        img_a_whole = cv2.imread(target_image_path)
        img_a_align_crop, _ = app.get(img_a_whole,crop_size)
        img_a_align_crop_pil = Image.fromarray(cv2.cvtColor(img_a_align_crop[0],cv2.COLOR_BGR2RGB)) 
        img_a = transformer_Arcface(img_a_align_crop_pil)
        img_id = img_a.view(-1, img_a.shape[0], img_a.shape[1], img_a.shape[2])
        # convert numpy to tensor
        img_id = img_id.cuda()
        #create latent id
        img_id_downsample = F.interpolate(img_id, size=(112,112))
        latend_id = model.netArc(img_id_downsample)
        latend_id = F.normalize(latend_id, p=2, dim=1)
        target_id_norm_list.append(latend_id.clone())
        
    assert len(target_id_norm_list) == len(source_specific_id_nonorm_list), "The number of images in source and target  directory must be same !!!"
    video_swap(opt.video_path, target_id_norm_list,source_specific_id_nonorm_list, opt.id_thres, \
        model, app, opt.output_path,temp_results_dir=opt.temp_path,no_simswaplogo=opt.no_simswaplogo,use_mask=opt.use_mask)<jupyter_output>input mean and std: 127.5 127.5
find model: ./insightface_func/models/antelope/glintr100.onnx recognition
find model: ./insightface_func/models/antelope/scrfd_10g_bnkps.onnx detection
set det-size: (640, 640)
{'fraction_non_alphanumeric': 0.13638192302534533, 'fraction_numerical': 0.03070940056322918, 'mean_word_length': 3.1595092024539877, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 7, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 22, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '2', 'dir': 'jupyter-structured-clean-dedup', 'id': '462764', 'license': 'Apache-2.0', 'n_tokens_mistral': 2668, 'n_tokens_neox': 2487, 'n_words': 479, 'path': 'MultiSpecific.ipynb', 'repo_name': 'Jinwook-shim/SimSwap', 'size': '7457'}