通过不停地旋转图片,直到dlib能够识别到人脸;通过dlib找到眼角、嘴角、鼻子、下巴特征点,假设鼻子到下巴的直线与双眼直线、嘴角直线垂直,找到脸部角度,结合已旋转角度,计算出最终图像旋转角度。
import dlib
import cv2
import numpy as np
import math
import osdetector = _frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
POINTS_NUM_LANDMARK = 68def rotate_img(image, angle):# grab the dimensions of the image and then determine the# center(h, w) = image.shape[:2](cX, cY) = (w // 2, h // 2)# grab the rotation matrix (applying the negative of the# angle to rotate clockwise), then grab the sine and cosine# (i.e., the rotation components of the matrix)M = RotationMatrix2D((cX, cY), -angle, 1.0)cos = np.abs(M[0, 0])sin = np.abs(M[0, 1])# compute the new bounding dimensions of the imagenW = int((h * sin) + (w * cos))nH = int((h * cos) + (w * sin))# adjust the rotation matrix to take into account translationM[0, 2] += (nW / 2) - cXM[1, 2] += (nH / 2) - cY# perform the actual rotation and return the imagereturn cv2.warpAffine(image, M, (nW, nH))def show(img, ms=0):""" 显示 """cv2.imshow('show', img)h, w = img.shape[:sizeWindow("show", w, h)cv2.waitKey(ms)def _largest_face(dets):if len(dets) == 1:return 0face_areas = [(det.right() - det.left()) * (det.bottom() - p()) for det in dets]largest_area = face_areas[0]largest_index = 0for index in range(1, len(dets)):if face_areas[index] > largest_area:largest_index = indexlargest_area = face_areas[index]print("largest_face index is {} in {} faces".format(largest_index, len(dets)))return largest_index# 从dlib的检测结果抽取姿态估计需要的点坐标
def get_image_points_from_landmark_shape(landmark_shape):if landmark_shape.num_parts != POINTS_NUM_LANDMARK:print("ERROR:landmark_shape.num_parts-{}".format(landmark_shape.num_parts))return -1, None# 2D image points. If you change the image, you need to change vectorimage_points = np.array([(landmark_shape.part(30).x, landmark_shape.part(30).y), # Nose tip(landmark_shape.part(8).x, landmark_shape.part(8).y), # Chin(landmark_shape.part(36).x, landmark_shape.part(36).y), # Left eye left corner(landmark_shape.part(45).x, landmark_shape.part(45).y), # Right eye right corne(landmark_shape.part(48).x, landmark_shape.part(48).y), # Left Mouth corner(landmark_shape.part(54).x, landmark_shape.part(54).y) # Right mouth corner], dtype="double")return 0, image_points# 计算两个点形成的直线角度,注意opencv的Y轴是朝下生长的,采用 y1-y2/x2-x1
# 最终结果在(-180 ~ 180 )
def computerAngle2(x1,y1,x2,y2):angle = math.atan2((y1 - y2), (x2 - x1))angle = angle * 180 / math.pi #(-180 ~ 180 )return angle# 用dlib检测关键点,返回姿态估计需要的几个点坐标
def detectImage(img,dets,angle):largest_index = _largest_face(dets)face_rectangle = dets[largest_index]landmark_shape = predictor(img, face_rectangle)return get_image_points_from_landmark_shape(landmark_shape)def findRotete(image_path):img = cv2.imread(image_path)finallyImg = NonefinallyAngle = 0for angle in range(0, 360, 60): # 不停旋转,注意如果每次旋转角度过大,存在所有角度无法识别到人脸的可能rotateImg = rotate_img(img, angle)dets = detector(rotateImg, 0)if (len(dets) > 0):finallyImg = rotateImgret, image_points = detectImage(rotateImg, dets, angle)if ret != 0:print('get_image_points failed')breakfor p in image_points:cv2.circle(rotateImg, (int(p[0]), int(p[1])), 3, (0, 0, 255), -1)Nose_x = image_points[0][0]Nose_y = image_points[0][1]Chin_x = image_points[1][0]Chin_y = image_points[1][1]Left_Eye_x = image_points[2][0]Left_Eye_y = image_points[2][1]Right_Eye_x = image_points[3][0]Right_Eye_y = image_points[3][1]Left_Mouth_x = image_points[4][0]Left_Mouth_y = image_points[4][1]Right_Mouth_x = image_points[5][0]Right_Mouth_y = image_points[5][1]eyeAngle = computerAngle2(Left_Eye_x, Left_Eye_y, Right_Eye_x, Right_Eye_y)mouthAngle = computerAngle2(Left_Mouth_x, Left_Mouth_y, Right_Mouth_x, Right_Mouth_y)nose2chinAngle = computerAngle2(Nose_x, Nose_y, Chin_x, Chin_y)# 120.8157057517292 120.25643716352927 32.9052429229879nose2chinAngle += 90 # 假设鼻子到下巴的直线与双眼直线垂直print(angle, eyeAngle, mouthAngle, nose2chinAngle)avgAngle = (eyeAngle + mouthAngle + nose2chinAngle) / 3 # 即双眼直线、嘴角直线与鼻子到下巴直线(垂直后)这三条直线的平均角度,后续要将此角度归0,即直线平行于图片print(avgAngle)finallyAngle = angle + avgAngle # (angle - (- avgAngle)) avgAngle需要归零,即-avgAngle, 又因为angle 是顺时针旋转角度,avgAngle是逆时针旋转角度,即需要减去(-avgAngle)if (finallyAngle > 360):finallyAngle -= 360if (finallyAngle < - 360):finallyAngle += 360print(finallyAngle)breakshow(rotate_img(img, angle), 200)if (rotateImg is not None):show(rotateImg, 1000)finallyImg = rotate_img(img, finallyAngle)filenames = image_path.split('.')filename = filenames[0] + "Modify." + filenames[1]print(filename)cv2.imwrite(filename, finallyImg)show(finallyImg, 2000)dir = "rotateCard"
for s in os.listdir(dir):image_path = os.path.join(dir, s)if 'Modify' not in image_path:findRotete(image_path)
opencv人脸检测,旋转处理 - 姜小豆 - 博客园 (cnblogs)
dlib【正面人脸检测】【特征点检测】【旋转】_dlib检测正脸_ya鸡给给的博客-CSDN博客
使用opencv和dlib进行人脸姿态估计(python)_dlib 人脸角度_yuanlulu的博客-CSDN博客
本文发布于:2024-01-28 12:31:40,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17064163057436.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |