当前位置:   article > 正文

单图换脸roop源码与环境配置_roop换脸

roop换脸

前言

1.roop是新开源了一个单图就可以进行视频换脸的项目,只需要一张所需面部的图像。不需要数据集,不需要训练。

2.大概的测试了一下,正脸换脸效果还不错,融合也比较自然。但如果人脸比较大,最终换出的效果可能会有些模糊。侧脸部分的幅度不宜过大,否则会出现人脸乱飘的情况。在多人场景下,也容易出现混乱。

3.使用简单,在处理单人视频和单人图像还是的换脸效果还是可以的,融合得也不错,适合制作一些小视频或单人图像。

4.效果如下:

 环境安装

1.我这里部署部署环境是win 10、cuda 11.7、cudnn 8.5、GPU是N卡的3060(6G显存),加anaconda3.

2.源码下载,如果用不了git,可以下载打包好的源码和模型。

  1. git clone https://github.com/s0md3v/roop.git
  2. cd roop

3.创建环境

  1. conda create --name roop python=3.10
  2. activate roop
  3. conda install pytorch==2.0.0 torchvision==0.15.0 torchaudio==2.0.0 pytorch-cuda=11.7 -c pytorch -c nvidia
  4. pip install -r requirements.txt

4.安装onnxruntime-gpu推理库

pip install onnxruntime-gpu

5.运行程序

python run.py

运行,它会下载一个500多m的模型,国内的网可能下载得很慢,也可以单独下载之后放到roop根目录下。

7.报错

ffmpeg is not installed!

这个是缺少了FFmpeg,FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。简单说来就是我们可以用它来进行视频的编解码,可以将视频文件转化为视频流,也可以将视频流转存储为视频文件。还有一个重点就是它是开源的。去官网下载后,加到环境变量就可以了。

8.如果在本地的机子跑起来很慢,把它做成服务器的方式运行,这样就可以在网页或者以微信公众 号或者小程序的方式访问,服务器端代码:

  1. #!/usr/bin/env python3
  2. import os
  3. import sys
  4. # single thread doubles performance of gpu-mode - needs to be set before torch import
  5. if any(arg.startswith('--gpu-vendor') for arg in sys.argv):
  6. os.environ['OMP_NUM_THREADS'] = '1'
  7. import platform
  8. import signal
  9. import shutil
  10. import glob
  11. import argparse
  12. import psutil
  13. import torch
  14. import tensorflow
  15. from pathlib import Path
  16. import multiprocessing as mp
  17. from opennsfw2 import predict_video_frames, predict_image
  18. from flask import Flask, request
  19. # import base64
  20. import numpy as np
  21. from gevent import pywsgi
  22. import cv2, argparse
  23. import time
  24. os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
  25. import roop.globals
  26. from roop.swapper import process_video, process_img, process_faces, process_frames
  27. from roop.utils import is_img, detect_fps, set_fps, create_video, add_audio, extract_frames, rreplace
  28. from roop.analyser import get_face_single
  29. import roop.ui as ui
  30. signal.signal(signal.SIGINT, lambda signal_number, frame: quit())
  31. parser = argparse.ArgumentParser()
  32. parser.add_argument('-f', '--face', help='use this face', dest='source_img')
  33. parser.add_argument('-t', '--target', help='replace this face', dest='target_path')
  34. parser.add_argument('-o', '--output', help='save output to this file', dest='output_file')
  35. parser.add_argument('--keep-fps', help='maintain original fps', dest='keep_fps', action='store_true', default=False)
  36. parser.add_argument('--keep-frames', help='keep frames directory', dest='keep_frames', action='store_true', default=False)
  37. parser.add_argument('--all-faces', help='swap all faces in frame', dest='all_faces', action='store_true', default=False)
  38. parser.add_argument('--max-memory', help='maximum amount of RAM in GB to be used', dest='max_memory', type=int)
  39. parser.add_argument('--cpu-cores', help='number of CPU cores to use', dest='cpu_cores', type=int, default=max(psutil.cpu_count() / 2, 1))
  40. parser.add_argument('--gpu-threads', help='number of threads to be use for the GPU', dest='gpu_threads', type=int, default=8)
  41. parser.add_argument('--gpu-vendor', help='choice your GPU vendor', dest='gpu_vendor', default='nvidia', choices=['apple', 'amd', 'intel', 'nvidia'])
  42. args = parser.parse_known_args()[0]
  43. if 'all_faces' in args:
  44. roop.globals.all_faces = True
  45. if args.cpu_cores:
  46. roop.globals.cpu_cores = int(args.cpu_cores)
  47. # cpu thread fix for mac
  48. if sys.platform == 'darwin':
  49. roop.globals.cpu_cores = 1
  50. if args.gpu_threads:
  51. roop.globals.gpu_threads = int(args.gpu_threads)
  52. # gpu thread fix for amd
  53. if args.gpu_vendor == 'amd':
  54. roop.globals.gpu_threads = 1
  55. if args.gpu_vendor:
  56. roop.globals.gpu_vendor = args.gpu_vendor
  57. else:
  58. roop.globals.providers = ['CPUExecutionProvider']
  59. sep = "/"
  60. if os.name == "nt":
  61. sep = "\\"
  62. def limit_resources():
  63. # prevent tensorflow memory leak
  64. gpus = tensorflow.config.experimental.list_physical_devices('GPU')
  65. for gpu in gpus:
  66. tensorflow.config.experimental.set_memory_growth(gpu, True)
  67. if args.max_memory:
  68. memory = args.max_memory * 1024 * 1024 * 1024
  69. if str(platform.system()).lower() == 'windows':
  70. import ctypes
  71. kernel32 = ctypes.windll.kernel32
  72. kernel32.SetProcessWorkingSetSize(-1, ctypes.c_size_t(memory), ctypes.c_size_t(memory))
  73. else:
  74. import resource
  75. resource.setrlimit(resource.RLIMIT_DATA, (memory, memory))
  76. def pre_check():
  77. if sys.version_info < (3, 9):
  78. quit('Python version is not supported - please upgrade to 3.9 or higher')
  79. if not shutil.which('ffmpeg'):
  80. quit('ffmpeg is not installed!')
  81. model_path = os.path.join(os.path.abspath(os.path.dirname(__file__)), '../inswapper_128.onnx')
  82. if not os.path.isfile(model_path):
  83. quit('File "inswapper_128.onnx" does not exist!')
  84. if roop.globals.gpu_vendor == 'apple':
  85. if 'CoreMLExecutionProvider' not in roop.globals.providers:
  86. quit("You are using --gpu=apple flag but CoreML isn't available or properly installed on your system.")
  87. if roop.globals.gpu_vendor == 'amd':
  88. if 'ROCMExecutionProvider' not in roop.globals.providers:
  89. quit("You are using --gpu=amd flag but ROCM isn't available or properly installed on your system.")
  90. if roop.globals.gpu_vendor == 'nvidia':
  91. CUDA_VERSION = torch.version.cuda
  92. CUDNN_VERSION = torch.backends.cudnn.version()
  93. if not torch.cuda.is_available():
  94. quit("You are using --gpu=nvidia flag but CUDA isn't available or properly installed on your system.")
  95. if CUDA_VERSION > '11.8':
  96. quit(f"CUDA version {CUDA_VERSION} is not supported - please downgrade to 11.8")
  97. if CUDA_VERSION < '11.4':
  98. quit(f"CUDA version {CUDA_VERSION} is not supported - please upgrade to 11.8")
  99. if CUDNN_VERSION < 8220:
  100. quit(f"CUDNN version {CUDNN_VERSION} is not supported - please upgrade to 8.9.1")
  101. if CUDNN_VERSION > 8910:
  102. quit(f"CUDNN version {CUDNN_VERSION} is not supported - please downgrade to 8.9.1")
  103. def get_video_frame(video_path, frame_number = 1):
  104. cap = cv2.VideoCapture(video_path)
  105. amount_of_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
  106. cap.set(cv2.CAP_PROP_POS_FRAMES, min(amount_of_frames, frame_number-1))
  107. if not cap.isOpened():
  108. print("Error opening video file")
  109. return
  110. ret, frame = cap.read()
  111. if ret:
  112. return cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
  113. cap.release()
  114. def preview_video(video_path):
  115. cap = cv2.VideoCapture(video_path)
  116. if not cap.isOpened():
  117. print("Error opening video file")
  118. return 0
  119. amount_of_frames = cap.get(cv2.CAP_PROP_FRAME_COUNT)
  120. ret, frame = cap.read()
  121. if ret:
  122. frame = get_video_frame(video_path)
  123. cap.release()
  124. return (amount_of_frames, frame)
  125. def status(string):
  126. value = "Status: " + string
  127. if 'cli_mode' in args:
  128. print(value)
  129. else:
  130. ui.update_status_label(value)
  131. def process_video_multi_cores(source_img, frame_paths):
  132. n = len(frame_paths) // roop.globals.cpu_cores
  133. if n > 2:
  134. processes = []
  135. for i in range(0, len(frame_paths), n):
  136. p = POOL.apply_async(process_video, args=(source_img, frame_paths[i:i + n],))
  137. processes.append(p)
  138. for p in processes:
  139. p.get()
  140. POOL.close()
  141. POOL.join()
  142. def select_face_handler(path: str):
  143. args.source_img = path
  144. def select_target_handler(path: str):
  145. args.target_path = path
  146. return preview_video(args.target_path)
  147. def toggle_all_faces_handler(value: int):
  148. roop.globals.all_faces = True if value == 1 else False
  149. def toggle_fps_limit_handler(value: int):
  150. args.keep_fps = int(value != 1)
  151. def toggle_keep_frames_handler(value: int):
  152. args.keep_frames = value
  153. def save_file_handler(path: str):
  154. args.output_file = path
  155. def create_test_preview(frame_number):
  156. return process_faces(
  157. get_face_single(cv2.imread(args.source_img)),
  158. get_video_frame(args.target_path, frame_number)
  159. )
  160. app = Flask(__name__)
  161. @app.route('/face_swap', methods=['POST'])
  162. def face_swap():
  163. if request.method == 'POST':
  164. args.source_img=request.form.get('source_img')
  165. args.target_path = request.form.get('target_path')
  166. args.output_file = request.form.get('output_path')
  167. keep_fps = request.form.get('keep_fps')
  168. if keep_fps == '0':
  169. args.keep_fps = False
  170. else:
  171. args.keep_fps = True
  172. Keep_frames = request.form.get('Keep_frames')
  173. if Keep_frames == '0':
  174. args.Keep_frames = False
  175. else:
  176. args.Keep_frames = True
  177. all_faces = request.form.get('all_faces')
  178. if all_faces == '0':
  179. args.all_faces = False
  180. else:
  181. args.all_faces = True
  182. if not args.source_img or not os.path.isfile(args.source_img):
  183. print("\n[WARNING] Please select an image containing a face.")
  184. return
  185. elif not args.target_path or not os.path.isfile(args.target_path):
  186. print("\n[WARNING] Please select a video/image to swap face in.")
  187. return
  188. if not args.output_file:
  189. target_path = args.target_path
  190. args.output_file = rreplace(target_path, "/", "/swapped-", 1) if "/" in target_path else "swapped-" + target_path
  191. target_path = args.target_path
  192. test_face = get_face_single(cv2.imread(args.source_img))
  193. if not test_face:
  194. print("\n[WARNING] No face detected in source image. Please try with another one.\n")
  195. return
  196. if is_img(target_path):
  197. if predict_image(target_path) > 0.85:
  198. quit()
  199. process_img(args.source_img, target_path, args.output_file)
  200. # status("swap successful!")
  201. return 'ok'
  202. seconds, probabilities = predict_video_frames(video_path=args.target_path, frame_interval=100)
  203. if any(probability > 0.85 for probability in probabilities):
  204. quit()
  205. video_name_full = target_path.split("/")[-1]
  206. video_name = os.path.splitext(video_name_full)[0]
  207. output_dir = os.path.dirname(target_path) + "/" + video_name if os.path.dirname(target_path) else video_name
  208. Path(output_dir).mkdir(exist_ok=True)
  209. # status("detecting video's FPS...")
  210. fps, exact_fps = detect_fps(target_path)
  211. if not args.keep_fps and fps > 30:
  212. this_path = output_dir + "/" + video_name + ".mp4"
  213. set_fps(target_path, this_path, 30)
  214. target_path, exact_fps = this_path, 30
  215. else:
  216. shutil.copy(target_path, output_dir)
  217. # status("extracting frames...")
  218. extract_frames(target_path, output_dir)
  219. args.frame_paths = tuple(sorted(
  220. glob.glob(output_dir + "/*.png"),
  221. key=lambda x: int(x.split(sep)[-1].replace(".png", ""))
  222. ))
  223. # status("swapping in progress...")
  224. if roop.globals.gpu_vendor is None and roop.globals.cpu_cores > 1:
  225. global POOL
  226. POOL = mp.Pool(roop.globals.cpu_cores)
  227. process_video_multi_cores(args.source_img, args.frame_paths)
  228. else:
  229. process_video(args.source_img, args.frame_paths)
  230. # status("creating video...")
  231. create_video(video_name, exact_fps, output_dir)
  232. # status("adding audio...")
  233. add_audio(output_dir, target_path, video_name_full, args.keep_frames, args.output_file)
  234. save_path = args.output_file if args.output_file else output_dir + "/" + video_name + ".mp4"
  235. print("\n\nVideo saved as:", save_path, "\n\n")
  236. # status("swap successful!")
  237. return 'ok'
  238. if __name__ == "__main__":
  239. print('Statrt server----------------')
  240. server = pywsgi.WSGIServer(('127.0.0.1', 5020), app)
  241. server.serve_forever()

9.客户端代码

  1. import requests
  2. import base64
  3. import numpy as np
  4. import cv2
  5. import time
  6. source_img = "z1.jpg" #要换的脸
  7. target_path= "z2.mp4" #目标图像或者视频
  8. output_path = "zface2.mp4" #保存的目录和文件名
  9. keep_fps = '0' #视频,是否保持原帧率
  10. Keep_frames = '0'
  11. all_faces = '0' #
  12. data = {'source_img': source_img,'target_path' : target_path,'output_path':output_path,
  13. 'keep-fps' : keep_fps,'Keep_frames':Keep_frames,'all_faces':all_faces}
  14. resp = requests.post("http://127.0.0.1:5020/face_swap", data=data)
  15. print(resp.content)

:如果对该项目感兴趣或者在安装的过程中遇到什么错误的的可以加我的企鹅群:487350510,大家一起探讨。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/413704
推荐阅读
相关标签
  

闽ICP备14008679号