naicoi's picture
update
0d4381f
Raw
History Blame Contribute Delete
2.2 kB
"""Face Parsing module for MuseTalk - Simplified implementation"""
import torch
import cv2
import numpy as np
from PIL import Image
import torchvision.transforms as transforms
class FaceParsing:
def __init__(self, left_cheek_width=80, right_cheek_width=80):
self.left_cheek_width = left_cheek_width
self.right_cheek_width = right_cheek_width
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
def __call__(self, image, size=(512, 512), mode="jaw"):
if isinstance(image, str):
image = Image.open(image)
width, height = image.size
with torch.no_grad():
image = image.resize(size, Image.BILINEAR)
face_mask = self._get_face_mask(image, mode=mode)
return face_mask
def _get_face_mask(self, image, mode="jaw"):
width, height = image.size
if mode == "jaw":
mask = np.zeros((height, width), dtype=np.uint8)
mask[:, int(height * 0.5) :] = 255
kernel = np.ones((21, 21), dtype=np.uint8)
kernel = cv2.erode(kernel, np.ones((3, 3), dtype=np.uint8), iterations=2)
cheek_kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (35, 3))
mask = cv2.erode(mask, cheek_kernel, iterations=2)
cheek_mask = np.zeros((height, width), dtype=np.uint8)
center = width // 2
cv2.rectangle(
cheek_mask, (0, 0), (center - self.left_cheek_width, height), 255, -1
)
cv2.rectangle(
cheek_mask,
(center + self.right_cheek_width, 0),
(width, height),
255,
-1,
)
mask = cv2.bitwise_and(mask, cheek_mask)
return Image.fromarray(mask)
else:
mask = np.zeros((height, width), dtype=np.uint8)
mask[:, int(height * 0.5) :] = 255
return Image.fromarray(mask)
if __name__ == "__main__":
fp = FaceParsing()
test_img = Image.new("RGB", (512, 512), (100, 150, 200))
mask = fp(test_img, mode="jaw")
mask.save("test_mask.png")
print("Face parsing test complete")