使用OpenCV人脸检测获取录制视频的RGB像素

问题描述 投票:0回答:1

我是Python新手,目前正在研究它。我目前正在使用OpenCV haarcascade进行面部检测(已经完成),目前正在尝试获取录制视频中每帧的RGB像素并将其输出为图中每帧的每个信号的平均RGB值。但我遇到的问题是,图表只显示前几秒获得的RGB值并停在那里,输出可能不是平均值。

我见过一些使用 .append 来获取 RGB 图像平均值的样本,并尝试过将获得的 RGB 值平均到每个帧,从而在折线图中给出 3 个不同的值,但仅得出的图形给出前几秒的 RGB 值并停在那里(录制的视频大约 20 秒长),输出的结果不是 RGB 值的平均值。

下面的Python代码是我正在使用的代码。我非常感谢所提供的任何帮助和建议。谢谢你。

import cv2
from PIL import Image
import datetime
import matplotlib.pyplot as plt
from statistics import mean

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')

cap = cv2.VideoCapture('Video1.MOV')

b = []
g = []
r = []

while True:
    ret, img = cap.read()
    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 = img[y: y + h, x: x + w]
        face_gray = gray[y: y + h, x: x + w]

        t_now = datetime.datetime.now().time()
        print('The Time is:{}'.format(t_now))

        B,G,R = face[150, 150]

        print('BLUE:{}'.format(B), 'GREEN:{}'.format(G), 'RED:{}'.format(R))
        print('Size of ROI:{}'.format(face.shape))

        b.append(B)
        g.append(G)
        r.append(R)

        plt.xlabel('Time(s)')
        plt.ylabel('RGB Signals')

    plt.plot(b, g, label = "line 1, Blue", color = 'blue')
    plt.plot(g, label = "line 2, Green", color = 'green')
    plt.plot(r, label = "line 3, Red", color = 'red')

    plt.legend()
    plt.show()

    cv2.imshow('video image', img)
    fps = cap.get(cv2.CAP_PROP_FPS)
    print('FPS:{}'.format(fps))
    key = cv2.waitKey(10)
    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()
python opencv average rgb face-detection
1个回答
0
投票

上线:

B, G, R = face[150, 150]

您仅获得检测到的脸部内一个坐标为 150, 150 的单个像素的强度值。我认为这不是您想要的。 在您的问题中,您写道您对整个帧的强度值感兴趣,但我猜您只是指检测到的脸部周围的边界框内的值。

此外,获得的值并不代表任何平均值,因为在您的代码中您没有使用任何计算平均值的方法。你提到的“append”方法实际上是用来在列表末尾插入一个元素。

您可以检查 face 变量的形状:您会注意到前两个值描述了区域的大小(以像素为单位),第三个值表示通道数 - 在我们的例子中,由于图像是 RGB,因此通道数将为 3。因此您需要引用特定通道并将它们分配给变量 B、G、R。您可以计算平均值,例如使用 numpy 包中的mean函数。

    B = np.mean(face[:, :, 0])  
    G = np.mean(face[:, :, 1])  
    R = np.mean(face[:, :, 2])  

    b.append(B)
    g.append(G)
    r.append(R)

我已包含以下完整代码:

import cv2
import datetime
import matplotlib.pyplot as plt
import numpy as np

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
cap = cv2.VideoCapture('Video1.mp4')

b = []
g = []
r = []

while True:
    ret, img = cap.read()
    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 = img[y: y + h, x: x + w]
        face_gray = gray[y: y + h, x: x + w]

        t_now = datetime.datetime.now().time()
        print('The Time is:{}'.format(t_now))

        B = np.mean(face[:, :, 0])  # Blue channel
        G = np.mean(face[:, :, 1])  # Green channel
        R = np.mean(face[:, :, 2])  # Red channel

        b.append(B)
        g.append(G)
        r.append(R)

        print('BLUE:{}'.format(B), 'GREEN:{}'.format(G), 'RED:{}'.format(R))
        print('Size of ROI:{}'.format(face.shape))

        plt.xlabel('Time(s)')
        plt.ylabel('RGB Signals')

    plt.plot(b, label = "line 1, Blue", color = 'blue')
    plt.plot(g, label = "line 2, Green", color = 'green')
    plt.plot(r, label = "line 3, Red", color = 'red')
    plt.legend()
    plt.show()

    cv2.imshow('video image', img)
    key = cv2.waitKey(10)
    if key == 27:
        break

cap.release()
cv2.destroyAllWindows()

但是,如果您想计算整个帧的像素值,而不仅仅是 bbox 内部的像素值,只需在内循环中将 face 替换为 img 即可。

当然,您的代码还有其他可以改进的小问题,例如,您可以将创建图形的行移到循环外部,以便最后只得到一个图形。

© www.soinside.com 2019 - 2024. All rights reserved.