使用OpenCV人脸检测获取视频RGB均值遇图表异常求助
问题解决:视频人脸区域RGB均值计算与折线图绘制
问题原因分析
- 未计算区域RGB均值:原代码中
B,G,R = face[150, 150]仅获取了人脸区域内某一个像素的BGR值(OpenCV图像默认是BGR通道顺序,不是RGB),并非整个区域的平均值。 - 图表阻塞程序执行:
plt.show()被放在了视频循环内部,第一次执行时会弹出图表窗口并阻塞程序,直到手动关闭图表才会继续处理后续帧,导致仅能获取前几帧数据。
修改后的代码
import cv2 import matplotlib.pyplot as plt import numpy as np # 加载分类器 face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') cap = cv2.VideoCapture('Video1.MOV') # 获取视频FPS,用于计算时间轴 fps = cap.get(cv2.CAP_PROP_FPS) # 初始化数据列表 b_means = [] g_means = [] r_means = [] timestamps = [] frame_count = 0 while True: ret, img = cap.read() # 视频读取完毕或出错时退出循环 if not ret: break gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) faces = face_cascade.detectMultiScale(gray, scaleFactor=1.3, minNeighbors=5) for x, y, w, h in faces: cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 0), 2) face_region = img[y:y+h, x:x+w] # 计算人脸区域的BGR均值 b_mean, g_mean, r_mean, _ = cv2.mean(face_region) # 或者用numpy计算:b_mean = np.mean(face_region[:, :, 0]),以此类推 # 记录数据和对应时间(基于帧计数和FPS) b_means.append(b_mean) g_means.append(g_mean) r_means.append(r_mean) timestamps.append(frame_count / fps) print(f"帧时间: {timestamps[-1]:.2f}s | B均值: {b_mean:.2f} | G均值: {g_mean:.2f} | R均值: {r_mean:.2f}") # 显示视频画面 cv2.imshow('video image', img) frame_count += 1 # 按ESC退出 if cv2.waitKey(1) & 0xFF == 27: break # 释放资源 cap.release() cv2.destroyAllWindows() # 绘制折线图 plt.figure(figsize=(10, 6)) plt.plot(timestamps, b_means, label='Blue Mean', color='blue') plt.plot(timestamps, g_means, label='Green Mean', color='green') plt.plot(timestamps, r_means, label='Red Mean', color='red') plt.xlabel('Time (s)') plt.ylabel('RGB Mean Value') plt.title('Face Region RGB Mean Over Time') plt.legend() plt.grid(True) plt.show()
关键改动说明
- 计算区域均值:使用
cv2.mean(face_region)直接获取人脸区域的BGR通道均值,也可以用numpy的np.mean()按通道计算,结果一致。 - 调整绘图时机:将
plt.show()和绘图逻辑移到视频循环结束后,避免阻塞帧处理流程,确保收集完整的20秒视频数据。 - 准确时间轴:通过
frame_count / fps计算每帧对应的实际视频时间,替代系统当前时间,避免处理延迟导致的时间误差。 - 视频结束判断:增加
if not ret: break逻辑,当视频读取完毕时自动退出循环,防止报错。
内容的提问来源于stack exchange,提问作者Brandon
相关产品推荐
相关产品推荐

