如何基于MediaPipe与OpenCV计算人脸指定关键点的平均RGB值
解决方案
你当前代码中color_array存储的是关键点的像素坐标,计算得到的是坐标的平均值,并非所需的平均RGB值,只需从图像中提取每个关键点对应位置的像素值再做均值计算即可。
修正后完整代码
import cv2 import mediapipe as mp import numpy as np # 初始化存储关键点RGB值的数组 color_array = [] mpFaceMesh = mp.solutions.face_mesh face_mesh = mpFaceMesh.FaceMesh() # 读取图像并转RGB格式 image = cv2.imread("E:\BeautBeta\IP_application/test2.jpg") rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) height, width, _ = image.shape result = face_mesh.process(rgb_image) if result.multi_face_landmarks: for facialLandmarks in result.multi_face_landmarks: landmarks_array = [3, 6, 8, 9, 32, 36, 69, 67, 109, 108, 101, 116, 117, 135, 16, 148, 151, 172, 169, 171, 152, 165, 170, 175, 199, 194, 192, 187, 200, 211, 204, 202, 207, 206, 210, 216, 228, 229, 266, 262, 277, 275, 273, 280, 281, 297, 299, 298, 330, 323, 343, 338, 337, 333, 343, 349, 348, 347, 350, 371, 357, 351, 396, 377, 391, 393, 423, 411, 420, 419, 421, 418, 422, 424, 429, 437, 425, 426, 432, 427, 436, 434, 430, 431, 428, 449, 448, 450, 451, 452] for i in landmarks_array: pt = facialLandmarks.landmark[i] # 限制坐标范围避免越界 x = max(0, min(width - 1, int(pt.x * width))) y = max(0, min(height - 1, int(pt.y * height))) # 标注关键点 cv2.circle(image, (x,y), 3, (255,255,255), -1) # 提取当前点的RGB值存入数组 color_array.append(rgb_image[y, x]) # 计算所有关键点的平均RGB值 if color_array: mean_rgb = np.mean(color_array, axis=0).astype(int) print(f"平均RGB值:R={mean_rgb[0]}, G={mean_rgb[1]}, B={mean_rgb[2]}") cv2.imshow("Image", image) cv2.waitKey(0) cv2.destroyAllWindows()
核心改动说明
- 修正了原代码的缩进错误,新增空检测逻辑避免未检测到人脸时报错
- 图像像素索引顺序为
[y, x]:OpenCV图像数组维度为(高度, 宽度, 通道数),不要搞反x和y的索引顺序 - 替换
color_array的存储内容:不再存储坐标,直接存储每个关键点对应的RGB三通道值 - 新增坐标越界限制:避免关键点计算后落在图像范围外导致索引报错
- 最终对颜色数组按通道求均值,得到的就是所有关键点的平均RGB值,若需要BGR格式的结果,从原始
image变量提取像素即可
内容的提问来源于stack exchange,提问作者Kethmie Perera
相关产品推荐
相关产品推荐

