Ashrafb commited on
Commit
5eb6efc
·
verified ·
1 Parent(s): 84821b7

Update vtoonify_model.py

Browse files
Files changed (1) hide show
  1. vtoonify_model.py +30 -19
vtoonify_model.py CHANGED
@@ -22,8 +22,6 @@ import logging
22
  from PIL import Image
23
 
24
 
25
-
26
-
27
  # Configure logging
28
  logging.basicConfig(level=logging.INFO)
29
 
@@ -98,6 +96,23 @@ class Model():
98
  exstyle = self.vtoonify.zplus2wplus(exstyle)
99
  return exstyle, 'Model of %s loaded.' % (style_type)
100
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  def detect_and_align(self, frame, top, bottom, left, right, return_para=False):
102
  message = 'Error: no face detected! Please retry or change the photo.'
103
  instyle = None
@@ -107,10 +122,11 @@ class Model():
107
  if len(faces) > 0:
108
  logging.info(f"Detected {len(faces)} face(s).")
109
  face = faces[0]
110
- landmarks = face.landmark_2d_106
 
111
 
112
  # Align face based on mapped landmarks
113
- aligned_face = self.align_face(frame, landmarks)
114
  if aligned_face is not None:
115
  logging.info(f"Aligned face shape: {aligned_face.shape}")
116
  with torch.no_grad():
@@ -130,8 +146,7 @@ class Model():
130
  return frame, instyle, message
131
 
132
  def align_face(self, image, landmarks):
133
- # Map InsightFace landmarks to dlib's 68-point model
134
- # Example: use specific indices for eyes and mouth
135
  eye_left = np.mean(landmarks[36:42], axis=0)
136
  eye_right = np.mean(landmarks[42:48], axis=0)
137
  mouth_left = landmarks[48]
@@ -161,22 +176,16 @@ class Model():
161
  img = img.resize((output_size, output_size), Image.ANTIALIAS)
162
 
163
  return np.array(img)
164
- def detect_and_align_image(self, image_data: bytes, top: int, bottom: int, left: int, right: int) -> tuple:
165
- if image_data is None:
 
166
  return np.zeros((256, 256, 3), np.uint8), None, 'Error: fail to load empty file.'
167
-
168
- # Convert bytes to a NumPy array
169
- nparr = np.frombuffer(image_data, np.uint8)
170
-
171
- # Decode the image data
172
- frame = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
173
-
174
  if frame is None:
175
- return np.zeros((256, 256, 3), np.uint8), None, 'Error: fail to decode the image.'
176
-
177
  frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
178
  return self.detect_and_align(frame, top, bottom, left, right)
179
-
180
  def image_toonify(self, aligned_face: np.ndarray, instyle: torch.Tensor, exstyle: torch.Tensor, style_degree: float, style_type: str) -> tuple:
181
  if instyle is None or aligned_face is None:
182
  return np.zeros((256, 256, 3), np.uint8), 'Oops, something wrong with the input. Please go to Step 2 and Rescale Image/First Frame again.'
@@ -207,4 +216,6 @@ class Model():
207
  """Convert a tensor image to OpenCV format."""
208
  tmp = ((img.cpu().numpy().transpose(1, 2, 0) + 1.0) * 127.5).astype(np.uint8).copy()
209
  logging.debug(f"Converted image shape: {tmp.shape}, strides: {tmp.strides}")
210
- return cv2.cvtColor(tmp, cv2.COLOR_RGB2BGR)
 
 
 
22
  from PIL import Image
23
 
24
 
 
 
25
  # Configure logging
26
  logging.basicConfig(level=logging.INFO)
27
 
 
96
  exstyle = self.vtoonify.zplus2wplus(exstyle)
97
  return exstyle, 'Model of %s loaded.' % (style_type)
98
 
99
+ def convert_106_to_68(self, landmarks_106):
100
+ # Mapping from 106 landmarks to 68 landmarks
101
+ landmark106to68 = [
102
+ 1, 10, 12, 14, 16, 3, 5, 7, 0, 23, 21, 19, 32, 30, 28, 26, 17, # Face outline
103
+ 43, 48, 49, 51, 50, # Left eyebrow
104
+ 102, 103, 104, 105, 101, # Right eyebrow
105
+ 72, 73, 74, 86, 78, 79, 80, 85, 84, # Nose
106
+ 35, 41, 42, 39, 37, 36, # Left eye
107
+ 89, 95, 96, 93, 91, 90, # Right eye
108
+ 52, 64, 63, 71, 67, 68, 61, 58, 59, 53, 56, 55, 65, 66, 62, 70, 69, 57, 60, 54 # Mouth
109
+ ]
110
+
111
+ # Convert 106 landmarks to 68 landmarks
112
+ landmarks_68 = [landmarks_106[index] for index in landmark106to68]
113
+
114
+ return landmarks_68
115
+
116
  def detect_and_align(self, frame, top, bottom, left, right, return_para=False):
117
  message = 'Error: no face detected! Please retry or change the photo.'
118
  instyle = None
 
122
  if len(faces) > 0:
123
  logging.info(f"Detected {len(faces)} face(s).")
124
  face = faces[0]
125
+ landmarks_106 = face.landmark_2d_106
126
+ landmarks_68 = self.convert_106_to_68(landmarks_106)
127
 
128
  # Align face based on mapped landmarks
129
+ aligned_face = self.align_face(frame, landmarks_68)
130
  if aligned_face is not None:
131
  logging.info(f"Aligned face shape: {aligned_face.shape}")
132
  with torch.no_grad():
 
146
  return frame, instyle, message
147
 
148
  def align_face(self, image, landmarks):
149
+ # Example alignment logic using 68 landmarks
 
150
  eye_left = np.mean(landmarks[36:42], axis=0)
151
  eye_right = np.mean(landmarks[42:48], axis=0)
152
  mouth_left = landmarks[48]
 
176
  img = img.resize((output_size, output_size), Image.ANTIALIAS)
177
 
178
  return np.array(img)
179
+
180
+ def detect_and_align_image(self, image: str, top: int, bottom: int, left: int, right: int) -> tuple:
181
+ if image is None:
182
  return np.zeros((256, 256, 3), np.uint8), None, 'Error: fail to load empty file.'
183
+ frame = cv2.imread(image)
 
 
 
 
 
 
184
  if frame is None:
185
+ return np.zeros((256, 256, 3), np.uint8), None, 'Error: fail to load the image.'
 
186
  frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
187
  return self.detect_and_align(frame, top, bottom, left, right)
188
+
189
  def image_toonify(self, aligned_face: np.ndarray, instyle: torch.Tensor, exstyle: torch.Tensor, style_degree: float, style_type: str) -> tuple:
190
  if instyle is None or aligned_face is None:
191
  return np.zeros((256, 256, 3), np.uint8), 'Oops, something wrong with the input. Please go to Step 2 and Rescale Image/First Frame again.'
 
216
  """Convert a tensor image to OpenCV format."""
217
  tmp = ((img.cpu().numpy().transpose(1, 2, 0) + 1.0) * 127.5).astype(np.uint8).copy()
218
  logging.debug(f"Converted image shape: {tmp.shape}, strides: {tmp.strides}")
219
+ return cv2.cvtColor(tmp, cv2.COLOR_RGB2BGR)
220
+
221
+