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

bf1o4zei  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(132)

我是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()
ewm0tg9j

ewm0tg9j1#

在线上:

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

相关问题