changes
This commit is contained in:
parent
9d0c377aa0
commit
1355549acf
@ -5,7 +5,7 @@ import cv2
|
|||||||
import numpy
|
import numpy
|
||||||
from cv2.typing import Size
|
from cv2.typing import Size
|
||||||
|
|
||||||
from facefusion.typing import Anchors, Angle, BoundingBox, Direction, Distance, FaceDetectorModel, FaceLandmark5, FaceLandmark68, Mask, Matrix, Points, PointsTemplate, PointsTemplateSet, Scale, Score, Translation, VisionFrame, WarpTemplate, WarpTemplateSet
|
from facefusion.typing import Anchors, Angle, BoundingBox, Distance, FaceDetectorModel, FaceLandmark5, FaceLandmark68, Mask, Matrix, Points, Scale, Score, Translation, VisionFrame, WarpTemplate, WarpTemplateSet
|
||||||
|
|
||||||
WARP_TEMPLATES : WarpTemplateSet =\
|
WARP_TEMPLATES : WarpTemplateSet =\
|
||||||
{
|
{
|
||||||
@ -33,13 +33,21 @@ WARP_TEMPLATES : WarpTemplateSet =\
|
|||||||
[ 0.38710391, 0.72160547 ],
|
[ 0.38710391, 0.72160547 ],
|
||||||
[ 0.61507734, 0.72034453 ]
|
[ 0.61507734, 0.72034453 ]
|
||||||
]).astype(numpy.float32),
|
]).astype(numpy.float32),
|
||||||
'deepfacelive': numpy.array(
|
'dfl_head': numpy.array(
|
||||||
[
|
[
|
||||||
[ 0.22549182, 0.21599032 ],
|
[ 0.39062554, 0.59114583 ],
|
||||||
[ 0.75476142, 0.21599032 ],
|
[ 0.60481776, 0.58951825 ],
|
||||||
[ 0.49012712, 0.51562511 ],
|
[ 0.49414062, 0.70898442 ],
|
||||||
[ 0.25414925, 0.78023333 ],
|
[ 0.41796875, 0.82031255 ],
|
||||||
[ 0.72610437, 0.78023333 ]
|
[ 0.58007813, 0.82031255 ]
|
||||||
|
]).astype(numpy.float32),
|
||||||
|
'dfl_whole_face': numpy.array(
|
||||||
|
[
|
||||||
|
[ 0.36816406, 0.40429688 ],
|
||||||
|
[ 0.62565106, 0.40071616 ],
|
||||||
|
[ 0.49023438, 0.54296875 ],
|
||||||
|
[ 0.39843755, 0.68554699 ],
|
||||||
|
[ 0.59375543, 0.68554699 ]
|
||||||
]).astype(numpy.float32),
|
]).astype(numpy.float32),
|
||||||
'ffhq_512': numpy.array(
|
'ffhq_512': numpy.array(
|
||||||
[
|
[
|
||||||
@ -66,28 +74,6 @@ WARP_TEMPLATES : WarpTemplateSet =\
|
|||||||
[ 0.57015325, 0.68306005 ]
|
[ 0.57015325, 0.68306005 ]
|
||||||
]).astype(numpy.float32)
|
]).astype(numpy.float32)
|
||||||
}
|
}
|
||||||
POINTS_TEMPLATES : PointsTemplateSet =\
|
|
||||||
{
|
|
||||||
'square': numpy.array(
|
|
||||||
[
|
|
||||||
[ 0, 0 ],
|
|
||||||
[ 1, 0 ],
|
|
||||||
[ 1, 1 ],
|
|
||||||
[ 0, 1 ]
|
|
||||||
]).astype(numpy.float32),
|
|
||||||
'triangle_orthogonal': numpy.array(
|
|
||||||
[
|
|
||||||
[ 0, 0 ],
|
|
||||||
[ 1, 0 ],
|
|
||||||
[ 0, 1 ]
|
|
||||||
]).astype(numpy.float32),
|
|
||||||
'triangle_skew': numpy.array(
|
|
||||||
[
|
|
||||||
[ 0, 0 ],
|
|
||||||
[ 1, 0 ],
|
|
||||||
[ 1, 1 ]
|
|
||||||
]).astype(numpy.float32)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def estimate_matrix_by_face_landmark_5(face_landmark_5 : FaceLandmark5, warp_template : WarpTemplate, crop_size : Size) -> Matrix:
|
def estimate_matrix_by_face_landmark_5(face_landmark_5 : FaceLandmark5, warp_template : WarpTemplate, crop_size : Size) -> Matrix:
|
||||||
@ -96,37 +82,16 @@ def estimate_matrix_by_face_landmark_5(face_landmark_5 : FaceLandmark5, warp_tem
|
|||||||
return affine_matrix
|
return affine_matrix
|
||||||
|
|
||||||
|
|
||||||
def estimate_matrix_by_points(source_points : Points, polygon_template : PointsTemplate, crop_size : Size) -> Matrix:
|
|
||||||
target_points = POINTS_TEMPLATES.get(polygon_template) * crop_size
|
|
||||||
affine_matrix = cv2.getAffineTransform(source_points, target_points.astype(numpy.float32))
|
|
||||||
return affine_matrix
|
|
||||||
|
|
||||||
|
|
||||||
def warp_face_by_face_landmark_5(temp_vision_frame : VisionFrame, face_landmark_5 : FaceLandmark5, warp_template : WarpTemplate, crop_size : Size) -> Tuple[VisionFrame, Matrix]:
|
def warp_face_by_face_landmark_5(temp_vision_frame : VisionFrame, face_landmark_5 : FaceLandmark5, warp_template : WarpTemplate, crop_size : Size) -> Tuple[VisionFrame, Matrix]:
|
||||||
affine_matrix = estimate_matrix_by_face_landmark_5(face_landmark_5, warp_template, crop_size)
|
affine_matrix = estimate_matrix_by_face_landmark_5(face_landmark_5, warp_template, crop_size)
|
||||||
crop_vision_frame = cv2.warpAffine(temp_vision_frame, affine_matrix, crop_size, borderMode = cv2.BORDER_REPLICATE, flags = cv2.INTER_AREA)
|
crop_vision_frame = cv2.warpAffine(temp_vision_frame, affine_matrix, crop_size, borderMode = cv2.BORDER_REPLICATE, flags = cv2.INTER_AREA)
|
||||||
return crop_vision_frame, affine_matrix
|
return crop_vision_frame, affine_matrix
|
||||||
|
|
||||||
|
|
||||||
def warp_face_for_deepfacelive(temp_vision_frame : VisionFrame, face_landmark_5 : FaceLandmark5, crop_size : Size, shift : Tuple[float, float], coverage : float) -> Tuple[VisionFrame, Matrix]:
|
|
||||||
affine_matrix = estimate_matrix_by_face_landmark_5(face_landmark_5, 'deepfacelive', (1, 1))
|
|
||||||
square_points = POINTS_TEMPLATES.get('square')
|
|
||||||
square_points = transform_points(square_points, cv2.invertAffineTransform(affine_matrix))
|
|
||||||
center_point = square_points.mean(axis = 0)
|
|
||||||
center_point += shift[0] * numpy.subtract(square_points[1], square_points[0])
|
|
||||||
center_point += shift[1] * numpy.subtract(square_points[3], square_points[0])
|
|
||||||
scale = numpy.linalg.norm(center_point - square_points[0]) * coverage
|
|
||||||
top_bottom_direction = calc_points_direction(square_points[0], square_points[2]) * scale
|
|
||||||
bottom_top_direction = calc_points_direction(square_points[3], square_points[1]) * scale
|
|
||||||
source_points = numpy.array([ center_point - top_bottom_direction, center_point + bottom_top_direction, center_point + top_bottom_direction ]).astype(numpy.float32)
|
|
||||||
affine_matrix = estimate_matrix_by_points(source_points, 'triangle_skew', crop_size)
|
|
||||||
crop_vision_frame = cv2.warpAffine(temp_vision_frame, affine_matrix, crop_size, flags = cv2.INTER_CUBIC)
|
|
||||||
return crop_vision_frame, affine_matrix
|
|
||||||
|
|
||||||
|
|
||||||
def warp_face_by_bounding_box(temp_vision_frame : VisionFrame, bounding_box : BoundingBox, crop_size : Size) -> Tuple[VisionFrame, Matrix]:
|
def warp_face_by_bounding_box(temp_vision_frame : VisionFrame, bounding_box : BoundingBox, crop_size : Size) -> Tuple[VisionFrame, Matrix]:
|
||||||
source_points = numpy.array([ [ bounding_box[0], bounding_box[1] ], [bounding_box[2], bounding_box[1] ], [ bounding_box[0], bounding_box[3] ] ]).astype(numpy.float32)
|
source_points = numpy.array([ [ bounding_box[0], bounding_box[1] ], [bounding_box[2], bounding_box[1] ], [ bounding_box[0], bounding_box[3] ] ]).astype(numpy.float32)
|
||||||
affine_matrix = estimate_matrix_by_points(source_points, 'triangle_orthogonal', crop_size)
|
target_points = numpy.array([ [ 0, 0 ], [ 1, 0 ], [ 0, 1 ] ]).astype(numpy.float32) * crop_size
|
||||||
|
affine_matrix = cv2.getAffineTransform(source_points, target_points)
|
||||||
if bounding_box[2] - bounding_box[0] > crop_size[0] or bounding_box[3] - bounding_box[1] > crop_size[1]:
|
if bounding_box[2] - bounding_box[0] > crop_size[0] or bounding_box[3] - bounding_box[1] > crop_size[1]:
|
||||||
interpolation_method = cv2.INTER_AREA
|
interpolation_method = cv2.INTER_AREA
|
||||||
else:
|
else:
|
||||||
@ -153,12 +118,6 @@ def paste_back(temp_vision_frame : VisionFrame, crop_vision_frame : VisionFrame,
|
|||||||
return paste_vision_frame
|
return paste_vision_frame
|
||||||
|
|
||||||
|
|
||||||
def calc_points_direction(start_point : Points, end_point : Points) -> Direction:
|
|
||||||
direction = end_point - start_point
|
|
||||||
direction /= numpy.linalg.norm(direction)
|
|
||||||
return direction
|
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize = None)
|
@lru_cache(maxsize = None)
|
||||||
def create_static_anchors(feature_stride : int, anchor_total : int, stride_height : int, stride_width : int) -> Anchors:
|
def create_static_anchors(feature_stride : int, anchor_total : int, stride_height : int, stride_width : int) -> Anchors:
|
||||||
y, x = numpy.mgrid[:stride_height, :stride_width][::-1]
|
y, x = numpy.mgrid[:stride_height, :stride_width][::-1]
|
||||||
|
@ -10,7 +10,7 @@ import facefusion.processors.core as processors
|
|||||||
from facefusion import config, content_analyser, face_classifier, face_detector, face_landmarker, face_masker, face_recognizer, inference_manager, logger, process_manager, state_manager, wording
|
from facefusion import config, content_analyser, face_classifier, face_detector, face_landmarker, face_masker, face_recognizer, inference_manager, logger, process_manager, state_manager, wording
|
||||||
from facefusion.download import conditional_download_hashes, conditional_download_sources, resolve_download_url_by_provider
|
from facefusion.download import conditional_download_hashes, conditional_download_sources, resolve_download_url_by_provider
|
||||||
from facefusion.face_analyser import get_many_faces, get_one_face
|
from facefusion.face_analyser import get_many_faces, get_one_face
|
||||||
from facefusion.face_helper import paste_back, warp_face_for_deepfacelive
|
from facefusion.face_helper import paste_back, warp_face_by_face_landmark_5
|
||||||
from facefusion.face_masker import create_occlusion_mask, create_static_box_mask
|
from facefusion.face_masker import create_occlusion_mask, create_static_box_mask
|
||||||
from facefusion.face_selector import find_similar_faces, sort_and_filter_faces
|
from facefusion.face_selector import find_similar_faces, sort_and_filter_faces
|
||||||
from facefusion.face_store import get_reference_faces
|
from facefusion.face_store import get_reference_faces
|
||||||
@ -44,9 +44,8 @@ def create_model_set() -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/iperov/emma_watson_224.dfm')
|
'path': resolve_relative_path('../.assets/models/iperov/emma_watson_224.dfm')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'template': 'dfl_whole_face',
|
||||||
'size': (224, 224),
|
'size': (224, 224),
|
||||||
'shift': (0.0, 0.0),
|
|
||||||
'coverage': 2.2
|
|
||||||
},
|
},
|
||||||
'iperov/jackie_chan_224':
|
'iperov/jackie_chan_224':
|
||||||
{
|
{
|
||||||
@ -66,9 +65,8 @@ def create_model_set() -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/iperov/jackie_chan_224.dfm')
|
'path': resolve_relative_path('../.assets/models/iperov/jackie_chan_224.dfm')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'template': 'dfl_whole_face',
|
||||||
'size': (224, 224),
|
'size': (224, 224),
|
||||||
'shift': (0.0, 0.0),
|
|
||||||
'coverage': 2.2
|
|
||||||
},
|
},
|
||||||
'iperov/keanu_reeves_320':
|
'iperov/keanu_reeves_320':
|
||||||
{
|
{
|
||||||
@ -88,9 +86,8 @@ def create_model_set() -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/iperov/keanu_reeves_320.dfm')
|
'path': resolve_relative_path('../.assets/models/iperov/keanu_reeves_320.dfm')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'template': 'dfl_whole_face',
|
||||||
'size': (320, 320),
|
'size': (320, 320),
|
||||||
'shift': (0.0, 0.0),
|
|
||||||
'coverage': 2.2
|
|
||||||
},
|
},
|
||||||
'iperov/sylvester_stallone_224':
|
'iperov/sylvester_stallone_224':
|
||||||
{
|
{
|
||||||
@ -110,9 +107,8 @@ def create_model_set() -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/iperov/sylvester_stallone_224.dfm')
|
'path': resolve_relative_path('../.assets/models/iperov/sylvester_stallone_224.dfm')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'template': 'dfl_whole_face',
|
||||||
'size': (224, 224),
|
'size': (224, 224),
|
||||||
'shift': (0.0, 0.0),
|
|
||||||
'coverage': 2.2
|
|
||||||
},
|
},
|
||||||
'iperov/taylor_swift_224':
|
'iperov/taylor_swift_224':
|
||||||
{
|
{
|
||||||
@ -132,9 +128,8 @@ def create_model_set() -> ModelSet:
|
|||||||
'path': resolve_relative_path('../.assets/models/iperov/taylor_swift_224.dfm')
|
'path': resolve_relative_path('../.assets/models/iperov/taylor_swift_224.dfm')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
'template': 'dfl_whole_face',
|
||||||
'size': (224, 224),
|
'size': (224, 224),
|
||||||
'shift': (0.0, 0.0),
|
|
||||||
'coverage': 2.2
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,10 +195,9 @@ def post_process() -> None:
|
|||||||
|
|
||||||
|
|
||||||
def swap_face(target_face : Face, temp_vision_frame : VisionFrame) -> VisionFrame:
|
def swap_face(target_face : Face, temp_vision_frame : VisionFrame) -> VisionFrame:
|
||||||
|
model_template = get_model_options().get('template')
|
||||||
model_size = get_model_options().get('size')
|
model_size = get_model_options().get('size')
|
||||||
model_shift = get_model_options().get('shift')
|
crop_vision_frame, affine_matrix = warp_face_by_face_landmark_5(temp_vision_frame, target_face.landmark_set.get('5/68'), model_template, model_size)
|
||||||
model_coverage = get_model_options().get('coverage')
|
|
||||||
crop_vision_frame, affine_matrix = warp_face_for_deepfacelive(temp_vision_frame, target_face.landmark_set.get('5/68'), model_size, model_shift, model_coverage)
|
|
||||||
crop_vision_frame_raw = crop_vision_frame.copy()
|
crop_vision_frame_raw = crop_vision_frame.copy()
|
||||||
box_mask = create_static_box_mask(crop_vision_frame.shape[:2][::-1], state_manager.get_item('face_mask_blur'), state_manager.get_item('face_mask_padding'))
|
box_mask = create_static_box_mask(crop_vision_frame.shape[:2][::-1], state_manager.get_item('face_mask_blur'), state_manager.get_item('face_mask_padding'))
|
||||||
crop_masks =\
|
crop_masks =\
|
||||||
|
@ -53,7 +53,6 @@ FaceStore = TypedDict('FaceStore',
|
|||||||
VisionFrame = NDArray[Any]
|
VisionFrame = NDArray[Any]
|
||||||
Mask = NDArray[Any]
|
Mask = NDArray[Any]
|
||||||
Points = NDArray[Any]
|
Points = NDArray[Any]
|
||||||
Direction = NDArray[Any]
|
|
||||||
Distance = NDArray[Any]
|
Distance = NDArray[Any]
|
||||||
Matrix = NDArray[Any]
|
Matrix = NDArray[Any]
|
||||||
Anchors = NDArray[Any]
|
Anchors = NDArray[Any]
|
||||||
@ -86,10 +85,8 @@ ProcessStep = Callable[[str, int, Args], bool]
|
|||||||
|
|
||||||
Content = Dict[str, Any]
|
Content = Dict[str, Any]
|
||||||
|
|
||||||
WarpTemplate = Literal['arcface_112_v1', 'arcface_112_v2', 'arcface_128_v2', 'deepfacelive', 'ffhq_512', 'mtcnn_512', 'styleganex_384']
|
WarpTemplate = Literal['arcface_112_v1', 'arcface_112_v2', 'arcface_128_v2', 'dfl_head', 'dfl_whole_face', 'ffhq_512', 'mtcnn_512', 'styleganex_384']
|
||||||
WarpTemplateSet = Dict[WarpTemplate, NDArray[Any]]
|
WarpTemplateSet = Dict[WarpTemplate, NDArray[Any]]
|
||||||
PointsTemplate = Literal['square', 'triangle_orthogonal', 'triangle_skew']
|
|
||||||
PointsTemplateSet = Dict[PointsTemplate, NDArray[Any]]
|
|
||||||
ProcessMode = Literal['output', 'preview', 'stream']
|
ProcessMode = Literal['output', 'preview', 'stream']
|
||||||
|
|
||||||
ErrorCode = Literal[0, 1, 2, 3, 4]
|
ErrorCode = Literal[0, 1, 2, 3, 4]
|
||||||
|
Loading…
Reference in New Issue
Block a user