主页 > 电脑硬件  > 

OpenCV实现人脸关键点检测

OpenCV实现人脸关键点检测

目录

实现过程

1,代码解读

1.1 导入工具包

1.2导入所需图像,以及训练好的人脸预测模型

1.3 将 dlib 的关键点对象转换为 NumPy 数组,以便后续处理

1.4图像上可视化面部关键点

1.5# 读取输入数据,预处理

1.6进行人脸检测

1.7遍历检测到的框

1.8遍历每个面部

2,所有代码

3,结果展示


实现过程

导入工具包:首先导入所需的Python库,包括dlib用于人脸检测和关键点定位,以及OpenCV用于图像处理。

参数解析:使用argparse库解析命令行参数,以指定面部关键点预测器的路径和输入图像的路径。

定义关键点范围:定义了两个字典(FACIAL_LANDMARKS_68_IDXS和FACIAL_LANDMARKS_5_IDXS),它们包含了不同面部部位的关键点索引范围,用于标识人脸的不同部分。

图像预处理:加载输入图像,将其缩放为指定宽度(500像素),并将其转换为灰度图像。这些预处理步骤有助于提高人脸检测的性能和稳定性。

人脸检测:使用dlib库的人脸检测器检测灰度图像中的人脸。检测结果是一个包含人脸边界框的列表。

遍历检测到的人脸:对于每个检测到的人脸,使用面部关键点定位器获取关键点的坐标。然后,对不同的面部部位进行循环处理。

绘制关键点:为了可视化,代码使用OpenCV在图像上绘制关键点。每个关键点以红色圆圈的形式标记在图像上,并标注了各个部位的名称。

提取ROI区域:在每个部位上,代码还提取了一个感兴趣区域(ROI),这是通过计算关键点的包围矩形来实现的。ROI区域随后可以用于进一步的分析或显示。

调整ROI尺寸:最后,代码调整了ROI区域的尺寸,以确保它们具有一致的宽度(250像素),同时保持高宽比例不变。

1,代码解读 1.1 导入工具包

collections.OrderedDict: 用于创建有序的字典。numpy: 用于处理数值计算。argparse: 用于处理命令行参数。dlib: 一个图像处理库,用于人脸检测和关键点定位。cv2 (OpenCV): 用于图像处理。 1.2导入所需图像,以及训练好的人脸预测模型

# 参数 ap = argparse.ArgumentParser() ap.add_argument("-p", "--shape-predictor", required=True, help="path to facial landmark predictor") ap.add_argument("-i", "--image", required=True, help="path to input image")

1.3 将 dlib 的关键点对象转换为 NumPy 数组,以便后续处理

'''这个函数用于将 dlib 的关键点对象转换为 NumPy 数组,以便后续处理。 它遍历关键点对象中的每个点,提取其 x 和 y 坐标,然后将坐标保存在 NumPy 数组中。''' def shape_to_np(shape, dtype="int"): # 创建68*2 coords = np.zeros((shape.num_parts, 2), dtype=dtype) # 遍历每一个关键点 # 得到坐标 for i in range(0, shape.num_parts): coords[i] = (shape.part(i).x, shape.part(i).y) return coords

1.4图像上可视化面部关键点

这个函数用于在图像上可视化面部关键点。 它接受输入图像、关键点坐标、可选颜色和透明度参数。 在输入图像上绘制关键点,可以为不同面部部位指定不同的颜色。 最后,将可视化的图像与原图像混合以得到输出图像。''' def visualize_facial_landmarks(image, shape, colors=None, alpha=0.75): # 创建两个copy # overlay and one for the final output image 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)] # 遍历每一个区域 for (i, name) in enumerate(FACIAL_LANDMARKS_68_IDXS.keys()): # 得到每一个点的坐标 (j, k) = FACIAL_LANDMARKS_68_IDXS[name] pts = shape[j:k] # 检查位置 if name == "jaw": # 用线条连起来 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

1.5# 读取输入数据,预处理

image = cv2.imread(args["image"]) (h, w) = image.shape[:2] width=500#这一行定义了一个新的宽度,即将图像调整为的目标宽度。 r = width / float(w) '''这一行创建一个新的图像维度 dim,它是一个元组,包含了目标宽度 width 和一个计算出的新高度。 新高度是原始高度 h 乘以比例 r 并取整数部分''' dim = (width, int(h * r)) '''最后一行使用OpenCV的 cv2.resize 函数, 将原始图像 image 调整为新的维度 dim,以实现目标宽度为500像素,同时保持高宽比例不变。 interpolation 参数指定了插值方法,这里使用了 cv2.INTER_AREA,它适合缩小图像。''' image = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

1.6进行人脸检测

'''1 是一个可选参数,它控制人脸检测的程度。 通常,值为 1 表示对图像进行一次粗略的检测。 你也可以尝试使用不同的值,以获得更灵敏或更宽松的人脸检测结果''' rects = detector(gray, 1)

1.7遍历检测到的框

for (i, rect) in enumerate(rects): # 对人脸框进行关键点定位 # 转换成ndarray shape = predictor(gray, rect) shape = shape_to_np(shape)

1.8遍历每个面部

# 遍历每一个部分 #这段代码针对每个面部部位执行一系列操作 for (name, (i, j)) in FACIAL_LANDMARKS_68_IDXS.items(): clone = image.copy() #这一行创建了图像的一个副本 clone,以便在副本上绘制标记,以保持原始图像不受影响。 cv2.putText(clone, name, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) ''' 这一行在图像上标记面部部位的名称,使用 OpenCV 的 cv2.putText 函数。 name 是部位的名称。 (10, 30) 是文本的起始坐标。 cv2.FONT_HERSHEY_SIMPLEX 是用于文本的字体。 0.7 是字体的比例因子。 (0, 0, 255) 是文本的颜色(蓝色)。 2 是文本的线宽。''' # 根据位置画点 for (x, y) in shape[i:j]: cv2.circle(clone, (x, y), 3, (0, 0, 255), -1) ''' 这个循环遍历给定部位的关键点坐标 (x, y),并在 clone 图像上绘制红色的小圆圈,以标记关键点的位置。 (x, y) 是关键点的坐标。 3 是圆圈的半径。 (0, 0, 255) 是红色的颜色。''' # 提取ROI区域 (x, y, w, h) = cv2.boundingRect(np.array([shape[i:j]]))

2,所有代码 #导入工具包 from collections import OrderedDict import numpy as np import argparse import dlib import cv2 # ibug.doc.ic.ac.uk/resources/facial-point-annotations/ #http://dlib.net/files/ # 参数 ap = argparse.ArgumentParser() ap.add_argument("-p", "--shape-predictor", required=True, help="path to facial landmark predictor") ap.add_argument("-i", "--image", required=True, help="path to input image") args = vars(ap.parse_args()) '''这两个字典包含了不同面部部位的关键点索引范围,用于标识人脸的不同部分,例如嘴巴、眼睛、鼻子等。''' FACIAL_LANDMARKS_68_IDXS = OrderedDict([ ("mouth", (48, 68)), ("right_eyebrow", (17, 22)), ("left_eyebrow", (22, 27)), ("right_eye", (36, 42)), ("left_eye", (42, 48)), ("nose", (27, 36)), ("jaw", (0, 17)) ]) FACIAL_LANDMARKS_5_IDXS = OrderedDict([ ("right_eye", (2, 3)), ("left_eye", (0, 1)), ("nose", (4)) ]) '''这个函数用于将 dlib 的关键点对象转换为 NumPy 数组,以便后续处理。 它遍历关键点对象中的每个点,提取其 x 和 y 坐标,然后将坐标保存在 NumPy 数组中。''' def shape_to_np(shape, dtype="int"): # 创建68*2 coords = np.zeros((shape.num_parts, 2), dtype=dtype) # 遍历每一个关键点 # 得到坐标 for i in range(0, shape.num_parts): coords[i] = (shape.part(i).x, shape.part(i).y) return coords ''' 这个函数用于在图像上可视化面部关键点。 它接受输入图像、关键点坐标、可选颜色和透明度参数。 在输入图像上绘制关键点,可以为不同面部部位指定不同的颜色。 最后,将可视化的图像与原图像混合以得到输出图像。''' def visualize_facial_landmarks(image, shape, colors=None, alpha=0.75): # 创建两个copy # overlay and one for the final output image 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)] # 遍历每一个区域 for (i, name) in enumerate(FACIAL_LANDMARKS_68_IDXS.keys()): # 得到每一个点的坐标 (j, k) = FACIAL_LANDMARKS_68_IDXS[name] pts = shape[j:k] # 检查位置 if name == "jaw": # 用线条连起来 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 # 加载人脸检测与关键点定位 detector = dlib.get_frontal_face_detector() predictor = dlib.shape_predictor(args["shape_predictor"]) # 读取输入数据,预处理 image = cv2.imread(args["image"]) (h, w) = image.shape[:2] width=500#这一行定义了一个新的宽度,即将图像调整为的目标宽度。 r = width / float(w) '''这一行创建一个新的图像维度 dim,它是一个元组,包含了目标宽度 width 和一个计算出的新高度。 新高度是原始高度 h 乘以比例 r 并取整数部分''' dim = (width, int(h * r)) '''最后一行使用OpenCV的 cv2.resize 函数, 将原始图像 image 调整为新的维度 dim,以实现目标宽度为500像素,同时保持高宽比例不变。 interpolation 参数指定了插值方法,这里使用了 cv2.INTER_AREA,它适合缩小图像。''' image = cv2.resize(image, dim, interpolation=cv2.INTER_AREA) gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) # 人脸检测 '''1 是一个可选参数,它控制人脸检测的程度。 通常,值为 1 表示对图像进行一次粗略的检测。 你也可以尝试使用不同的值,以获得更灵敏或更宽松的人脸检测结果''' rects = detector(gray, 1) # 遍历检测到的框 for (i, rect) in enumerate(rects): # 对人脸框进行关键点定位 # 转换成ndarray shape = predictor(gray, rect) shape = shape_to_np(shape) # 遍历每一个部分 #这段代码针对每个面部部位执行一系列操作 for (name, (i, j)) in FACIAL_LANDMARKS_68_IDXS.items(): clone = image.copy() #这一行创建了图像的一个副本 clone,以便在副本上绘制标记,以保持原始图像不受影响。 cv2.putText(clone, name, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) ''' 这一行在图像上标记面部部位的名称,使用 OpenCV 的 cv2.putText 函数。 name 是部位的名称。 (10, 30) 是文本的起始坐标。 cv2.FONT_HERSHEY_SIMPLEX 是用于文本的字体。 0.7 是字体的比例因子。 (0, 0, 255) 是文本的颜色(蓝色)。 2 是文本的线宽。''' # 根据位置画点 for (x, y) in shape[i:j]: cv2.circle(clone, (x, y), 3, (0, 0, 255), -1) ''' 这个循环遍历给定部位的关键点坐标 (x, y),并在 clone 图像上绘制红色的小圆圈,以标记关键点的位置。 (x, y) 是关键点的坐标。 3 是圆圈的半径。 (0, 0, 255) 是红色的颜色。''' # 提取ROI区域 (x, y, w, h) = cv2.boundingRect(np.array([shape[i:j]])) roi = image[y:y + h, x:x + w] (h, w) = roi.shape[:2] width=250 r = width / float(w) dim = (width, int(h * r)) roi = cv2.resize(roi, dim, interpolation=cv2.INTER_AREA) # 显示每一部分 cv2.imshow("ROI", roi) cv2.imshow("Image", clone) cv2.waitKey(0) # 展示所有区域 output = visualize_facial_landmarks(image, shape) cv2.imshow("Image", output) cv2.waitKey(0) 3,结果展示

标签:

OpenCV实现人脸关键点检测由讯客互联电脑硬件栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“OpenCV实现人脸关键点检测