-
-
Save zalo/71fbd5dbfe23cb46406d211b84be9f7e to your computer and use it in GitHub Desktop.
import numpy as np | |
import cv2 | |
import face_alignment | |
# Initialize the face alignment tracker | |
fa = face_alignment.FaceAlignment(face_alignment.LandmarksType._3D, flip_input=True, device="cuda") | |
# Start the webcam capture, exit with 'q' | |
cap = cv2.VideoCapture(0) | |
while(not (cv2.waitKey(1) & 0xFF == ord('q'))): | |
ret, frame = cap.read() | |
if(ret): | |
# Clear the indices frame | |
canonical = np.zeros(frame.shape) | |
# Run the face alignment tracker on the webcam image | |
imagePoints = fa.get_landmarks_from_image(frame) | |
if(imagePoints is not None): | |
imagePoints = imagePoints[0] | |
# Compute the Mean-Centered-Scaled Points | |
mean = np.mean(imagePoints, axis=0) # <- This is the unscaled mean | |
scaled = (imagePoints / np.linalg.norm(imagePoints[42] - imagePoints[39])) * 0.06 # Set the inner eye distance to 60cm (just because) | |
centered = scaled - np.mean(scaled, axis=0) # <- This is the scaled mean | |
# Construct a "rotation" matrix (strong simplification, might have shearing) | |
rotationMatrix = np.empty((3,3)) | |
rotationMatrix[0,:] = (centered[16] - centered[0])/np.linalg.norm(centered[16] - centered[0]) | |
rotationMatrix[1,:] = (centered[8] - centered[27])/np.linalg.norm(centered[8] - centered[27]) | |
rotationMatrix[2,:] = np.cross(rotationMatrix[0, :], rotationMatrix[1, :]) | |
invRot = np.linalg.inv(rotationMatrix) | |
# Object-space points, these are what you'd run OpenCV's solvePnP() with | |
objectPoints = centered.dot(invRot) | |
# Draw the computed data | |
for i, (imagePoint, objectPoint) in enumerate(zip(imagePoints, objectPoints)): | |
# Draw the Point Predictions | |
cv2.circle(frame, (imagePoint[0], imagePoint[1]), 3, (0,255,0)) | |
# Draw the X Axis | |
cv2.line(frame, tuple(mean[:2].astype(int)), | |
tuple((mean+(rotationMatrix[0,:] * 100.0))[:2].astype(int)), (0, 0, 255), 3) | |
# Draw the Y Axis | |
cv2.line(frame, tuple(mean[:2].astype(int)), | |
tuple((mean-(rotationMatrix[1,:] * 100.0))[:2].astype(int)), (0, 255, 0), 3) | |
# Draw the Z Axis | |
cv2.line(frame, tuple(mean[:2].astype(int)), | |
tuple((mean+(rotationMatrix[2,:] * 100.0))[:2].astype(int)), (255, 0, 0), 3) | |
# Draw the indices in Object Space | |
cv2.putText(canonical, str(i), | |
((int)((objectPoint[0] * 1000.0) + 320.0), | |
(int)((objectPoint[1] * 1000.0) + 240.0)), | |
cv2.FONT_HERSHEY_SIMPLEX, 0.3, (255, 255, 255), 1, cv2.LINE_AA) | |
cv2.imshow('Webcam View', frame) | |
cv2.imshow('Canonical View', canonical) | |
# When everything is done, release the capture | |
cap.release() | |
cv2.destroyAllWindows() |
Hi. This process is giving good results for video.
I want to calculate pitch, yaw, roll of a face.
So,
I added these linesdef rotationMatrixToEulerAngles(R) : sy = math.sqrt(R[0,0] * R[0,0] + R[1,0] * R[1,0]) singular = sy < 1e-6 if not singular : x = math.atan2(R[2,1] , R[2,2]) y = math.atan2(-R[2,0], sy) z = math.atan2(R[1,0], R[0,0]) else : x = math.atan2(-R[1,2], R[1,1]) y = math.atan2(-R[2,0], sy) z = 0 return np.array([x, y, z]) eulerAngles=rotationMatrixToEulerAngles(rotationMatrix) pitch, yaw, roll = [math.radians(_) for _ in eulerAngles] pitch = math.degrees(math.asin(math.sin(pitch))) roll = -math.degrees(math.asin(math.sin(roll))) yaw = math.degrees(math.asin(math.sin(yaw))) rotate_degree=[ str(int(pitch)), str(int(yaw)),str(int(roll))]
Your process is giving good results for pitch, roll, yaw.
But, Instead of video, i have taken directory containing different persons in different orientation images and applied above concept. Giving bad results for pitch, roll, yaw values.
Can you tell the process of calculating pitch, roll, yaw anglesThanks
Sandhya
Hi Sandhya,
Have you fixed your results? It seems right results to me.
Hi,
Thanks for your reply.
Sorry for late response.
import numpy as np
import cv2
import face_alignment
import math
def rotationMatrixToEulerAngles(R) :
sy = math.sqrt(R[0,0] * R[0,0] + R[1,0] * R[1,0])
singular = sy < 1e-6
if not singular :
x = math.atan2(R[2,1] , R[2,2])
y = math.atan2(-R[2,0], sy)
z = math.atan2(R[1,0], R[0,0])
else :
x = math.atan2(-R[1,2], R[1,1])
y = math.atan2(-R[2,0], sy)
z = 0
return np.array([x, y, z])
#Initialize the face alignment tracker
fa = face_alignment.FaceAlignment(face_alignment.LandmarksType.3D, flip_input=True, device="cpu")
frame=cv2.imread("model9.jpg") #("model9.jpg")
canonical = np.zeros(frame.shape)
#Run the face alignment tracker on the image
#imagePoints = fa.get_landmarks_from_image(frame)
imagePoints = fa.get_landmarks(frame)
if(imagePoints is not None):
imagePoints = imagePoints[0]
# Compute the Mean-Centered-Scaled Points
mean = np.mean(imagePoints, axis=0) # <- This is the unscaled mean
scaled = (imagePoints / np.linalg.norm(imagePoints[42] - imagePoints[39])) * 0.06 # Set the inner eye distance to 60cm (just because)
centered = scaled - np.mean(scaled, axis=0) # <- This is the scaled mean
# Construct a "rotation" matrix (strong simplification, might have shearing)
rotationMatrix = np.empty((3,3))
rotationMatrix[0,:] = (centered[16] - centered[0])/np.linalg.norm(centered[16] - centered[0])
rotationMatrix[1,:] = (centered[8] - centered[27])/np.linalg.norm(centered[8] - centered[27])
rotationMatrix[2,:] = np.cross(rotationMatrix[0, :], rotationMatrix[1, :])
eulerAngles=rotationMatrixToEulerAngles(rotationMatrix)
pitch, yaw, roll = [math.radians()*100.0 for _ in eulerAngles]
pitch = math.degrees(math.asin(math.sin(pitch)))
roll = -math.degrees(math.asin(math.sin(roll)))
yaw = math.degrees(math.asin(math.sin(yaw)))
# rotate_degree=[ str(int(pitch)), str(int(roll)),str(int(yaw))]
rotate_degree=[math.floor(pitch),math.floor(roll),math.floor(yaw)]
print ("Rotate_Degree:",rotate_degree)
cv2.imshow('Webcam View', frame)
cv2.imshow('Canonical View', canonical)
cv2.waitKey(0)
With the above code, if i print rotate_degree giving result as Rotate_Degree: ['16', '44', '-20'], where as from https://azure.microsoft.com/en-us/services/cognitive-services/face/#demo link getting values for pitch, roll, yaw as like this
"headPose": {
"pitch": 6.0,
"roll": 24.7,
"yaw": 11.1
}
What should i modify to get the results??
Thanks in Advance.
Regards,
Sandhyalaxmi Kanna
Hi,
Thanks for your reply.
Sorry for late response.import numpy as np
import cv2
import face_alignment
import math
def rotationMatrixToEulerAngles(R) :
sy = math.sqrt(R[0,0] * R[0,0] + R[1,0] * R[1,0])
singular = sy < 1e-6
if not singular :
x = math.atan2(R[2,1] , R[2,2])
y = math.atan2(-R[2,0], sy)
z = math.atan2(R[1,0], R[0,0])
else :
x = math.atan2(-R[1,2], R[1,1])
y = math.atan2(-R[2,0], sy)
z = 0
return np.array([x, y, z])
#Initialize the face alignment tracker
fa = face_alignment.FaceAlignment(face_alignment.LandmarksType.3D, flip_input=True, device="cpu") frame=cv2.imread("model9.jpg") #("model9.jpg") canonical = np.zeros(frame.shape) #Run the face alignment tracker on the image #imagePoints = fa.get_landmarks_from_image(frame) imagePoints = fa.get_landmarks(frame) if(imagePoints is not None): imagePoints = imagePoints[0] # Compute the Mean-Centered-Scaled Points mean = np.mean(imagePoints, axis=0) # <- This is the unscaled mean scaled = (imagePoints / np.linalg.norm(imagePoints[42] - imagePoints[39])) * 0.06 # Set the inner eye distance to 60cm (just because) centered = scaled - np.mean(scaled, axis=0) # <- This is the scaled mean # Construct a "rotation" matrix (strong simplification, might have shearing) rotationMatrix = np.empty((3,3)) rotationMatrix[0,:] = (centered[16] - centered[0])/np.linalg.norm(centered[16] - centered[0]) rotationMatrix[1,:] = (centered[8] - centered[27])/np.linalg.norm(centered[8] - centered[27]) rotationMatrix[2,:] = np.cross(rotationMatrix[0, :], rotationMatrix[1, :]) eulerAngles=rotationMatrixToEulerAngles(rotationMatrix) pitch, yaw, roll = [math.radians()*100.0 for _ in eulerAngles]
pitch = math.degrees(math.asin(math.sin(pitch)))
roll = -math.degrees(math.asin(math.sin(roll)))
yaw = math.degrees(math.asin(math.sin(yaw)))rotate_degree=[ str(int(pitch)), str(int(roll)),str(int(yaw))]
rotate_degree=[math.floor(pitch),math.floor(roll),math.floor(yaw)]
print ("Rotate_Degree:",rotate_degree)
cv2.imshow('Webcam View', frame)
cv2.imshow('Canonical View', canonical)
cv2.waitKey(0)With the above code, if i print rotate_degree giving result as Rotate_Degree: ['16', '44', '-20'], where as from https://azure.microsoft.com/en-us/services/cognitive-services/face/#demo link getting values for pitch, roll, yaw as like this "headPose": { "pitch": 6.0, "roll": 24.7, "yaw": 11.1 }
What should i modify to get the results??Thanks in Advance.
Regards,
Sandhyalaxmi Kanna
rotationMatrix = np.empty((3, 3))
rotationMatrix[0, :] = (centered[16] - centered[0]) / np.linalg.norm(centered[16] - centered[0])
rotationMatrix[1, :] = (centered[8] - centered[27]) / np.linalg.norm(centered[8] - centered[27])
rotationMatrix[2, :] = np.cross(rotationMatrix[0, :], rotationMatrix[1, :])
eulerAngles = rotationMatrixToEulerAngles(rotationMatrix)
pitch, yaw, roll = eulerAngles
pitch = np.degrees(np.arcsin(np.sin(pitch)))
roll = -np.degrees(np.arcsin(np.sin(roll)))
yaw = -np.degrees(np.arcsin(np.sin(yaw)))
Thanks @patrickwangqy. It is working very well.
np.arcsin(np.sin(pitch))
why?
np.arcsin(np.sin(pitch))
why?
angle range
you clip it with -90+90 deg? but what if actual YAW > 90 deg ?
it is impossible
Hi. This process is giving good results for video.
I want to calculate pitch, yaw, roll of a face.
So,
I added these lines
Your process is giving good results for pitch, roll, yaw.
But, Instead of video, i have taken directory containing different persons in different orientation images and applied above concept. Giving bad results for pitch, roll, yaw values.
Can you tell the process of calculating pitch, roll, yaw angles
Thanks
Sandhya