Skip to content

Commit 79b6095

Browse files
committed
Add angle correction
1 parent 4d47261 commit 79b6095

1 file changed

Lines changed: 49 additions & 4 deletions

File tree

software/face.py

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import sensor
22
import image
33
import utime
4+
import math
45

56
class face_detection:
67
def __init__(self, config, comms):
@@ -9,6 +10,8 @@ def __init__(self, config, comms):
910
self.has_face = False
1011
self.face_cascade = image.HaarCascade("frontalface", stages=self.config.get('FaceStages'))
1112
self.face_object = [0, 0, 1, 1]
13+
self.face_angle = 0
14+
self.correct_angle = False
1215

1316
self.extra_fb = sensor.alloc_extra_fb(sensor.width(), sensor.height(), sensor.GRAYSCALE)
1417

@@ -19,21 +22,31 @@ def detect(self, img):
1922
return
2023

2124
now = utime.ticks_ms()
25+
self.face_angle = 0
2226
face_objects = img.find_features(self.face_cascade, threshold=self.config.get('FaceThreshold'), scale_factor=self.config.get('FaceScaleFactor'))
2327

2428
if len(face_objects) == 0 and self.config.get('FaceAngles'):
2529
for angle in self.config.get('FaceAngles'):
2630
self.extra_fb.replace(img)
2731
self.extra_fb.rotation_corr(x_rotation=0.0, y_rotation=0.0, z_rotation=angle)
32+
2833
face_objects = self.extra_fb.find_features(self.face_cascade, threshold=self.config.get('FaceThreshold'), scale_factor=self.config.get('FaceScaleFactor'))
2934
if face_objects:
35+
self.face_angle = angle
3036
break
3137

3238
if face_objects:
3339
self.face_object = face_objects[0]
3440
self.has_face = True
3541
if self.config.get('TrackEyes'):
3642
self.face_object = [self.face_object[0], self.face_object[1] + int(self.face_object[3] * 1/5), self.face_object[2], int(self.face_object[3] * 2/5)]
43+
44+
if self.correct_angle:
45+
eyes_x = self.face_object[0] + int(self.face_object[2] * 1/5)
46+
eyes_y = self.face_object[1] + int(self.face_object[3] * 1/5)
47+
eyes_width = self.face_object[2] - int(self.face_object[2] * 1/5)
48+
eyes_height = int(self.face_object[3] * 2/5)
49+
self.face_object = [eyes_x, eyes_y, eyes_width, eyes_height]
3750
else:
3851
self.face_object = [0, 0, img.width(), img.height()]
3952
self.has_face = False
@@ -45,7 +58,39 @@ def draw_region(self, img):
4558
if self.face_object[2] == img.width():
4659
return
4760

48-
if self.config.get('PixelFormat') == 'RGB565':
49-
img.draw_rectangle(self.face_object, color=(70, 130, 180))
50-
else:
51-
img.draw_rectangle(self.face_object)
61+
img.draw_rectangle(self.face_object, color=(70, 130, 180))
62+
63+
if self.correct_angle:
64+
face_x = self.face_object[0]
65+
face_y = self.face_object[1]
66+
face_width = self.face_object[2]
67+
face_height = self.face_object[3]
68+
69+
theta = math.radians(self.face_angle * -1)
70+
offset = (0, 0)
71+
72+
rect = [
73+
(face_x, face_y),
74+
(face_x, face_y + face_height),
75+
(face_x + face_width, face_y + face_height),
76+
(face_x + face_width, face_y)
77+
]
78+
79+
rotated_rect = [translate(rotate(xy, theta), offset) for xy in rect]
80+
81+
img.draw_line((rotated_rect[0][0], rotated_rect[0][1], rotated_rect[1][0], rotated_rect[1][1]), color=(220, 220, 0))
82+
img.draw_line((rotated_rect[1][0], rotated_rect[1][1], rotated_rect[2][0], rotated_rect[2][1]), color=(220, 220, 0))
83+
img.draw_line((rotated_rect[2][0], rotated_rect[2][1], rotated_rect[3][0], rotated_rect[3][1]), color=(220, 220, 0))
84+
img.draw_line((rotated_rect[3][0], rotated_rect[3][1], rotated_rect[0][0], rotated_rect[0][1]), color=(220, 220, 0))
85+
img.draw_string(face_x, face_y + face_height - 10, str(self.face_angle) + "^", color=(70, 130, 180), mono_space=False)
86+
87+
def rotate(xy, theta):
88+
cos_theta, sin_theta = math.cos(theta), math.sin(theta)
89+
90+
return (
91+
int(xy[0] * cos_theta - xy[1] * sin_theta),
92+
int(xy[0] * sin_theta + xy[1] * cos_theta)
93+
)
94+
95+
def translate(xy, offset):
96+
return xy[0] + offset[0], xy[1] + offset[1]

0 commit comments

Comments
 (0)