Skip to content

Commit dac45e6

Browse files
committed
update Chapter 4 Face Mesh
1 parent 0a806e3 commit dac45e6

File tree

14 files changed

+229
-0
lines changed

14 files changed

+229
-0
lines changed

Chapter 4 Face Mesh/Basics.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import cv2
2+
import mediapipe as mp
3+
import time
4+
5+
# Open the video file
6+
cap = cv2.VideoCapture(
7+
"E:\\Advance Computer Vision with Python\\main\\Chapter 3 Face Detection\\Videos\\4.mp4"
8+
)
9+
if not cap.isOpened():
10+
print("Error: Could not open video.")
11+
exit()
12+
13+
pTime = 0
14+
15+
# Initialize MediaPipe drawing tools and face mesh model
16+
mpDraw = mp.solutions.drawing_utils # Import MediaPipe drawing utilities
17+
mpFaceMesh = (
18+
mp.solutions.face_mesh
19+
) # Import MediaPipe face mesh module for detecting and processing facial landmarks
20+
faceMesh = mpFaceMesh.FaceMesh(
21+
max_num_faces=2
22+
) # Initialize face mesh model, set to detect up to two faces
23+
drawSpec = mpDraw.DrawingSpec(
24+
thickness=1, circle_radius=2
25+
) # Create a drawing specification object for landmark and connection styles
26+
# thickness specifies line thickness, circle_radius specifies landmark point radius
27+
28+
while True:
29+
print("Reading video frame...")
30+
success, img = cap.read()
31+
print("Read success:", success)
32+
if not success:
33+
print("Finished processing video or error occurred.")
34+
break
35+
36+
# Convert the image to RGB
37+
imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
38+
# Process the image to detect face mesh
39+
results = faceMesh.process(imgRGB)
40+
41+
if results.multi_face_landmarks:
42+
for faceLms in results.multi_face_landmarks:
43+
# Draw the face mesh
44+
mpDraw.draw_landmarks(
45+
img, faceLms, mpFaceMesh.FACEMESH_TESSELATION, drawSpec, drawSpec
46+
)
47+
# mpDraw.draw_landmarks calls MediaPipe's drawing function to draw landmarks and connections on the image
48+
# img: the image on which to draw the landmarks
49+
# faceLms: the detected face landmarks
50+
# mpFaceMesh.FACEMESH_TESSELATION: specifies the type of connections to draw, here it's face mesh tessellation
51+
# drawSpec: defines the drawing style for landmarks and connections (e.g., thickness and circle radius)
52+
# The last two drawSpec parameters define the drawing style for landmarks (keypoints) and connections
53+
# You can choose to define them separately:
54+
# drawSpecPoints = mpDraw.DrawingSpec(color=(0, 255, 0), thickness=1, circle_radius=2) # Green
55+
# drawSpecLines = mpDraw.DrawingSpec(color=(255, 0, 0), thickness=1) # Blue
56+
# Note that circle_radius in drawSpecLines has no effect; it only affects the drawing of landmarks, not connections
57+
58+
for id, lm in enumerate(faceLms.landmark):
59+
# Get the image dimensions
60+
ih, iw, ic = img.shape
61+
x, y = int(lm.x * iw), int(lm.y * ih)
62+
# Print each landmark's ID and coordinates
63+
print(id, x, y)
64+
65+
# Calculate and display the frame rate
66+
cTime = time.time()
67+
fps = 1 / (cTime - pTime)
68+
pTime = cTime
69+
cv2.putText(
70+
img, f"FPS: {int(fps)}", (20, 70), cv2.FONT_HERSHEY_PLAIN, 3, (255, 0, 0), 3
71+
)
72+
73+
cv2.namedWindow("Image", cv2.WINDOW_NORMAL) # Create a resizable window
74+
75+
# Display the image
76+
cv2.imshow("Image", img)
77+
cv2.waitKey(1)
78+
79+
cap.release()
80+
cv2.destroyAllWindows()
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
import cv2
2+
import mediapipe as mp
3+
import time
4+
5+
6+
class FaceMeshDetector:
7+
def __init__(
8+
self, staticMode=False, maxFaces=2, minDetectionCon=0.5, minTrackCon=0.5
9+
):
10+
# Initialize parameters
11+
self.staticMode = staticMode # Use static mode or not
12+
self.maxFaces = maxFaces # Maximum number of faces to detect
13+
self.minDetectionCon = minDetectionCon # Minimum detection confidence
14+
self.minTrackCon = minTrackCon # Minimum tracking confidence
15+
16+
# Initialize MediaPipe drawing tools and face mesh model
17+
self.mpDraw = mp.solutions.drawing_utils # Drawing utilities
18+
self.mpFaceMesh = mp.solutions.face_mesh # Face mesh module
19+
self.faceMesh = self.mpFaceMesh.FaceMesh(
20+
static_image_mode=self.staticMode,
21+
max_num_faces=self.maxFaces,
22+
min_detection_confidence=self.minDetectionCon,
23+
min_tracking_confidence=self.minTrackCon,
24+
)
25+
26+
self.drawSpec = self.mpDraw.DrawingSpec(
27+
thickness=1, circle_radius=2
28+
) # Drawing specifications
29+
30+
def findFaceMesh(self, img, draw=True):
31+
# Convert the image to RGB
32+
self.imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
33+
# Process the image to detect face mesh
34+
self.results = self.faceMesh.process(self.imgRGB)
35+
faces = [] # Store detected facial landmarks
36+
if self.results.multi_face_landmarks:
37+
for faceLms in self.results.multi_face_landmarks:
38+
if draw:
39+
# Draw the face mesh
40+
self.mpDraw.draw_landmarks(
41+
img,
42+
faceLms,
43+
self.mpFaceMesh.FACEMESH_TESSELATION,
44+
self.drawSpec,
45+
self.drawSpec,
46+
)
47+
face = [] # Store landmarks for a single face
48+
for id, lm in enumerate(faceLms.landmark):
49+
ih, iw, ic = img.shape # Get image dimensions
50+
x, y = int(lm.x * iw), int(
51+
lm.y * ih
52+
) # Convert normalized coordinates to pixel coordinates
53+
face.append([x, y]) # Add landmark coordinates
54+
faces.append(face) # Add to faces list
55+
return img, faces # Return image and facial landmarks
56+
57+
58+
def main():
59+
# Open the video file
60+
cap = cv2.VideoCapture(
61+
"E:\\Advance Computer Vision with Python\\main\\Chapter 3 Face Detection\\Videos\\4.mp4"
62+
)
63+
pTime = 0 # Previous frame time
64+
detector = FaceMeshDetector(maxFaces=2) # Initialize face mesh detector
65+
while True:
66+
success, img = cap.read()
67+
if not success:
68+
break
69+
img, faces = detector.findFaceMesh(img) # Detect face mesh
70+
if len(faces) != 0:
71+
print(faces[0]) # Print landmarks of the first face
72+
cTime = time.time() # Current time
73+
fps = 1 / (cTime - pTime) # Calculate frames per second
74+
pTime = cTime # Update previous frame time
75+
cv2.putText(
76+
img, f"FPS: {int(fps)}", (20, 70), cv2.FONT_HERSHEY_PLAIN, 3, (0, 255, 0), 3
77+
) # Display FPS on the image
78+
cv2.namedWindow("Image", cv2.WINDOW_NORMAL) # Create a resizable window
79+
cv2.imshow("Image", img) # Show image
80+
cv2.waitKey(1) # Wait for keyboard input
81+
82+
83+
if __name__ == "__main__":
84+
main()

Chapter 4 Face Mesh/README.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# mp.solutions.face_mesh
2+
3+
`mpFaceMesh = mp.solutions.face_mesh` imports the MediaPipe face mesh module for detecting and processing facial landmarks.
4+
5+
`faceMesh = mpFaceMesh.FaceMesh(max_num_faces=2)` initializes the face mesh model, set to detect up to two faces.
6+
7+
`results = faceMesh.process(imgRGB)` processes the image to detect face meshes.
8+
9+
Parameters for `the mpFaceMesh.FaceMesh()` class include: `self.staticMode, self.maxFaces, self.minDetectionCon, self.minTrackCon`.
10+
11+
- **staticMode**: Whether to treat each image as a static image. If True, face detection is performed on every frame. If False, it tracks the detected face, which is faster.
12+
- **maxFaces**: Maximum number of faces to detect.
13+
- **minDetectionCon**: Minimum confidence threshold for detection. Faces below this confidence are ignored.
14+
- **minTrackCon**: Minimum confidence threshold for tracking. Tracking below this confidence is ignored.
15+
16+
# mp.solutions.drawing_utils
17+
18+
`mpDraw = mp.solutions.drawing_utils` imports the MediaPipe drawing utilities module.
19+
20+
`drawSpec = mpDraw.DrawingSpec(thickness=1, circle_radius=2)` creates a drawing specification object to define the style for landmarks and connections, where thickness specifies line thickness and circle_radius specifies the radius of landmark points.
21+
22+
`mpDraw.draw_landmarks(img, faceLms, mpFaceMesh.FACEMESH_TESSELATION, drawSpec, drawSpec)` calls MediaPipe's drawing function to draw landmarks and connections on the image.
23+
24+
- **img**: The image on which to draw landmarks.
25+
- **faceLms**: The detected face landmarks collection.
26+
- **mpFaceMesh.FACEMESH_TESSELATION**: Specifies the type of connections to draw; here, it's the face mesh tessellation.
27+
- **drawSpec**: Defines the drawing style for landmarks and connections (e.g., thickness and circle radius). The first drawSpec parameter defines the style for landmarks (keypoints), such as circle radius and color, while the second defines the style for connections, such as line thickness and color.
28+
29+
# Issues in Source Code
30+
31+
These bugs won't cause errors during execution but will appear during debugging.
32+
33+
## 1、Parameter Name Change in New Version
34+
35+
Before:
36+
37+
![原来](./pics/原来.png)
38+
39+
Now:
40+
41+
![现在](./pics/现在.png)
42+
43+
## 2、Positional Argument Needs to Be a Keyword Argument
44+
45+
![关键字传参](./pics/关键字传参.png)

Chapter 4 Face Mesh/Videos/1.mp4

16.4 MB
Binary file not shown.

Chapter 4 Face Mesh/Videos/2.mp4

10 MB
Binary file not shown.

Chapter 4 Face Mesh/Videos/3.mp4

23.5 MB
Binary file not shown.

Chapter 4 Face Mesh/Videos/4.mp4

41.2 MB
Binary file not shown.
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
1,https://www.pexels.com/zh-cn/video/3796263/
2+
2,https://www.pexels.com/zh-cn/video/4340125/
3+
3,https://www.pexels.com/zh-cn/video/5137640/
4+
4,https://www.pexels.com/zh-cn/video/4761954/
73.4 KB
Loading
38.8 KB
Loading

0 commit comments

Comments
 (0)