表情识别(二)——使用Dlib、opencv和Python标记和提取脸部的特定区域

使用Dlib、OpenCV和Python检测眼睛,鼻子,嘴唇和下巴引用函数
特征点和不同人脸部位的关系
  • Dlib库使用68个特征点标注出人脸特征,通过对应序列的特征点,我们就可以获得对应的脸部特征。68个特征点分布如下

在这里插入图片描述

  • 比如说通过第48到68个点,我们就可以获得嘴部的形状。
  • 我们可以在代码中增加类似的映射,直接通过调用对应部位就可以实现
FACIAL_LANDMARKS_IDXS = OrderedDict([
	("mouth", (48, 68)),
	("right_eyebrow", (17, 22)),
	("left_eyebrow", (22, 27)),
	("right_eye", (36, 42)),
	("left_eye", (42, 48)),
	("nose", (27, 35)),
	("jaw", (0, 17))
])
可视化每一个人脸的部位特征
  • 描述:可视化每一个人脸部位并将最终的结果覆盖在输出的图片上
  • 参数:
    •    image是输入的图片
      
    •    shape是包含68个特征点的坐标
      
    •    color是对应的颜色numpy
      
    •    alpha是对应的图片覆盖层的不透明度
      
def visualize_facial_landmarks(image, shape, colors=None, alpha=0.75):
	# 创建输入图片的两个副本
	# 一个是覆盖层
	# 一个是最终的输出层
	overlay = image.copy()
	output = image.copy()
	
	# 设定每一个脸部的颜色,可以自己设定
	if colors is None:
		colors = [(19, 199, 109), (79, 76, 240), (230, 159, 23),
			(168, 100, 168), (158, 163, 32),
			(163, 38, 32), (180, 42, 220)]

	# 遍历之前设定的脸部器官的字典,i是对应序列号,name是脸部器官的名称
	for (i, name) in enumerate(FACIAL_LANDMARKS_IDXS.keys()):
		# 获取的对应器官的开始点的标号范围
		(j, k) = FACIAL_LANDMARKS_IDXS[name]
		# 获取特定器官的点的坐标
		pts = shape[j:k]
	
		# 检查是否需要画下巴
		if name == "jaw":
			# 因为下巴线是非闭合的脸部区域,需要画出在(x,y)点之间的所有的线
			for l in range(1, len(pts)):
				ptA = tuple(pts[l - 1])
				ptB = tuple(pts[l])
				cv2.line(overlay, ptA, ptB, colors[i], 2)
	
		# 否则计算脸部特征的凸几何体的点的坐标并画出啦
		else:
			hull = cv2.convexHull(pts)
			cv2.drawContours(overlay, [hull], -1, colors[i], -1)

		# 创建一个透明的覆盖层
		cv2.addWeighted(overlay, alpha, output, 1 - alpha, 0, output)
		# 返回最终的输出函数
		return output
使用Dlib、OpenCV和Python提取脸的局部主函数
# 这个包是作者自己写的,下载不到可以看上一篇博文,具体的调用的函数我都已经重写了的,可以自己调用,也可以直接去github上搜索
# 导入相关的包
from imutils import face_utils
import numpy as np
import imutils
import dlib
import cv2

  • 初始化68个特征点的面部检测器,加载预先下载的模型
# intialize dlib face detector adn then create the facial landmark predictor
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")
  • 载入图片,并修改图片的大小到统一的格式,同时还注意,将他转成灰度图片
# 加载图片,修改为统一大小,,转为灰度
image = cv2.imread("1.jpg")
image = imutils.resize(image,width = 500)
# change the BGR into RGB
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

# 对修改过的图片进行检测,返回脸部的矩形框
rects = detector(gray,1)
  • 遍历所有检测出来的人脸,并对其进行特征点预测
# 遍历检测出来的人脸选区
for (i,rect) in enumerate(rects):
    # 使用预先加载好的预测器,对提取出来的人脸进行特征点预测
    shape = predictor(gray,rect)
    # 将所有提取出来的特征点,转为二维numpy数组
    shape = face_utils.shape_to_np(shape)
  • 遍历脸部特征区域字典,选出对应的所有的特征点,进行可视化
# 一次分开遍历所有脸部特征
for (name,(i,j)) in face_utils.FACIAL_LANDMARKS_IDXS.items():
    # 复制一份原图,在原图上进行标注
    clone = image.copy()
    cv2.putText(clone,name,(10,30),
                cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)

    # 遍历每一个部位对应的所有的特征点,并在原图上使用圈进行标注
    for (x,y) in shape[i:j]:
    	cv2.circle(image,(x,y),1,(0,0,255),-1)	
  • 提取出单独的脸部特征区,作为一个单独的一张子图进行展示
# 从原图中提取出特定脸部特征的局部,并作为单独的图片显示
(x,y,w,h) = cv2.boundingRect(np.array([shape[i:j]]))
roi = image[y:y+h,x:x+w]
roi = imutils.resize(roi,width=250,inter=cv2.INTER_CUBIC)

# 展示脸部的单独的局部特征
cv2.imshow("ROI",roi)
# 展示单独标注嘴部的图片
cv2.imshow("Image",clone)
cv2.waitKey(0)
  • 使用一个透明覆盖层去显示整张脸
# 通过一个透明层去显示所有的脸部特征
output = face_utils.visualize_facial_landmarks(image,shape)
cv2.imshow("image",output)
cv2.waitkey(0)
最终代码
from imutils import face_utils
import numpy as np
import imutils
import dlib
import cv2

# intialize dlib face detector adn then create the facial landmark predictor
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("shape_predictor_68_face_landmarks.dat")

# load the image,resize it and convert it into grayscale
# resice the size of the image into 500 width
# image = cv2.imread(args["image"])
image = cv2.imread("1.jpg")
image = imutils.resize(image,width = 500)
# change the BGR into RGB
gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)

# detect face in the grayscale face
# detecting the bounding box of faces in our image
# the second parameter is the number of image pyramid layer
# prior applying the detector we must upscaling the image
rects = detector(gray,1)

# Given the coordinates of the face in the image
# loop over the face detections
for (i,rect) in enumerate(rects):
    # determine the facial landmarks for the face region
    # convert the coordiantes of the facial landmark to numpy array
    # predictor is to detect the facila landmark
    shape = predictor(gray,rect)
    # convert the dlib objects to a numpy array
    shape = face_utils.shape_to_np(shape)

    # loop over the face parts individually
    for (name,(i,j)) in face_utils.FACIAL_LANDMARKS_IDXS.items():
        # clone the original image to draw on it
        # display the name of the face part on the image
        clone = image.copy()
        cv2.putText(clone,name,(10,30),
                    cv2.FONT_HERSHEY_SIMPLEX,0.7,(0,0,255),2)

        # loop over the subset of facila landmarks
        # drawing the specific face part
        for (x,y) in shape[i:j]:
            cv2.circle(image,(x,y),1,(0,0,255),-1)

            # exract the ROI of the face region as separate image
        (x,y,w,h) = cv2.boundingRect(np.array([shape[i:j]]))
        roi = image[y:y+h,x:x+w]
        roi = imutils.resize(roi,width=250,inter=cv2.INTER_CUBIC)

            # show the particular face part
        cv2.imshow("ROI",roi)
        cv2.imshow("Image",clone)
        cv2.waitKey(0)

    # visualize all facial landmarks with a transparent overlay
    output = face_utils.visualize_facial_landmarks(image,shape)
    cv2.imshow("image",output)
    cv2.waitkey(0)
最终运行效果

在这里插入图片描述

分析与总结
  • opencv和dlib是真的好用,现在已经能提取出脸部的特征了
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值