这里主要是已经训练好的模型,并不是由我们自己进行训练。
我们在这里使用到了openCV和dlib两个软件包。
实现代码
import cv2
import dlib
# 加载 Dlib 的人脸检测器
detector = dlib.get_frontal_face_detector()
# 打开摄像头(默认摄像头,如果有多个摄像头可以修改参数)
cap = cv2.VideoCapture(0)
while True:
# 读取一帧
ret, frame = cap.read()
# 将帧转换为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 在帧中检测人脸
faces = detector(gray)
# 绘制矩形框标注检测到的人脸
for face in faces:
x, y, w, h = face.left(), face.top(), face.width(), face.height()
cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
# 显示结果帧
cv2.imshow('Detected Faces', frame)
# 按 'q' 键退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 释放摄像头并关闭所有窗口
cap.release()
cv2.destroyAllWindows()
很短哈哈哈哈哈哈,所以其实效果也不是太好,但是很适合新手入门看一看,学一学
代码解释
(1)读取一帧
在OpenCV中,cap.read()
是用于从视频捕获设备(比如摄像头)中读取一帧图像的方法。这个方法返回两个值:
-
ret
(返回值):一个布尔值,表示是否成功读取了一帧图像。如果成功读取,ret
为True
;如果没有读取到帧,ret
为False
。 -
frame
:表示从视频流中读取到的图像帧。如果ret
为True
,frame
就是包含当前图像的 NumPy 数组。
在下面的代码片段中:
ret, frame = cap.read()
cap
是通过 cv2.VideoCapture()
打开的视频捕获对象。这一行代码实际上是尝试从摄像头中读取一帧图像,并将成功与否的结果存储在 ret
中,图像数据存储在 frame
中。接下来,你可以对 frame
进行处理或显示。
通常,在视频捕获的循环中,会使用类似的结构来连续读取视频流中的帧,以便进行实时处理、显示或分析。
(2)转换为灰度图提升性能
这行代码是将彩色图像(BGR格式)转换为灰度图像。在计算机视觉中,灰度图像是只包含亮度信息的图像,每个像素只有一个数值,表示灰度级别。
具体来说,`cv2.cvtColor` 是 OpenCV 中的一个函数,用于进行颜色空间转换。在这里,它将彩色图像 `frame` 从BGR(蓝绿红)颜色空间转换为灰度颜色空间。
```python
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
```
- `frame`:彩色图像的NumPy数组。
- `cv2.COLOR_BGR2GRAY`:表示颜色转换的标志。它指示 `cv2.cvtColor` 将图像从BGR颜色空间转换为灰度颜色空间。
在灰度图像中,每个像素只有一个灰度值,范围通常是0到255,其中0表示黑色,255表示白色。灰度图像通常用于简化图像处理任务,减少计算量,并且在一些任务中仍然保留了足够的信息。在人脸检测等任务中,通常使用灰度图像来提高算法的运行速度。
(3)检测灰度图中的人脸
在这行代码中,`detector(gray)` 使用 Dlib 库中的人脸检测器来检测灰度图像中的人脸。具体来说,`detector` 是通过 `dlib.get_frontal_face_detector()` 获得的 Dlib 人脸检测器对象。
```python
faces = detector(gray)
```
- `gray`:灰度图像,通常是通过 `cv2.cvtColor` 转换得到的。
- `detector`:Dlib 的人脸检测器对象。
`detector(gray)` 返回一个包含检测到的人脸位置信息的 Dlib rectangles 对象。这个对象包含了一个或多个矩形区域,每个矩形表示一个检测到的人脸的位置。
在后续的代码中,通过遍历 `faces` 中的矩形,可以获取每个人脸的位置(左上角和右下角的坐标),然后可以在图像上绘制矩形框来标记检测到的人脸。例如:
```python
for face in faces:
x, y, w, h = face.left(), face.top(), face.width(), face.height()
cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
```
这样就可以在图像中标记出检测到的人脸的位置。
(4)绘制人脸矩形
`cv2.rectangle` 是 OpenCV 中用于在图像上绘制矩形的函数。以下是它的一般形式:
```python
cv2.rectangle(image, start_point, end_point, color, thickness)
```
- `image`:要绘制矩形的图像。
- `start_point`:矩形的左上角坐标。
- `end_point`:矩形的右下角坐标。
- `color`:矩形的颜色,通常是一个三元组 (B, G, R),表示蓝、绿、红通道的颜色值。
- `thickness`:矩形的边框厚度(如果为负值,表示填充矩形内部)。
```python
cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)
```
- `frame`:图像,这通常是摄像头捕获的图像。
- `(x, y)`:矩形左上角的坐标,这是人脸检测器返回的人脸位置矩形的左上角坐标。
- `(x+w, y+h)`:矩形右下角的坐标,这是人脸检测器返回的人脸位置矩形的右下角坐标。
- `(255, 0, 0)`:蓝色,表示绘制的矩形边框的颜色。
- `2`:矩形边框的厚度。
因此,这一行代码的作用是在图像上标记检测到的人脸位置,绘制一个蓝色的矩形框,边框宽度为2个像素。
但是记住了
在 OpenCV 中,颜色通常以 BGR 的顺序(蓝绿红)表示,与 RGB 不同。
(5)显示结果
`cv2.imshow` 是 OpenCV 中用于显示图像的函数。以下是它的一般形式:
```python
cv2.imshow(window_name, image)
```
- `window_name`:显示图像的窗口的名称。
- `image`:要显示的图像。
我们的代码中:
```python
cv2.imshow('Detected Faces', frame)
```
- `'Detected Faces'`:窗口的名称,可以自定义。
- `frame`:要显示的图像,通常是摄像头捕获的图像,经过人脸检测并标记后的结果。
这一行代码的作用是在名为 `'Detected Faces'` 的窗口中显示经过人脸检测并标记后的图像。这样,你就可以可视化地看到摄像头捕获的图像,并且在图像上标记了检测到的人脸的位置。
(6)程序退出
这部分代码是用于等待用户按下键盘上的 'q' 键来退出程序的逻辑。解释如下:
- `cv2.waitKey(1)`:等待键盘输入,参数表示等待时间(单位为毫秒)。如果设为 0,则表示持续等待用户输入。如果设为 1,则表示等待 1 毫秒。
- `& 0xFF`:这是为了兼容不同操作系统上键盘输入的处理。在某些系统上,`cv2.waitKey()` 的返回值包含更多信息,而使用 `& 0xFF` 可以获取最低的8位(一个字节)。
- `== ord('q')`:检查用户输入的键是否是 'q'。`ord()` 函数返回字符的 ASCII 值。
如果用户按下 'q' 键,上述条件就为真,循环就会被中断,程序退出。
这是一种简单的方法来实现通过按 'q' 键来退出图像显示或视频播放等循环的操作。
(7)最后释放资源
在使用 OpenCV 处理摄像头捕获或显示图像时,`cap.release()` 和 `cv2.destroyAllWindows()` 这两行是用于释放资源的重要步骤。如果不执行这些步骤,可能会导致程序在退出时没有正确释放摄像头资源或关闭图像窗口。
具体解释如下:
- `cap.release()`:释放通过 `cv2.VideoCapture` 打开的摄像头。这是为了确保在程序退出时释放摄像头资源,以便其他应用程序可以使用它。
- `cv2.destroyAllWindows()`:关闭所有通过 OpenCV 创建的窗口。如果你使用了 `cv2.imshow` 显示图像,这是确保在程序退出时关闭图像窗口的方法。如果没有调用这个函数,可能会导致程序退出后图像窗口仍然保持打开状态。
虽然在一些简单的程序中,可能会省略这两行而不出现问题,但最好在程序中明确地释放资源,以确保程序运行的健壮性。
结束了但是我还有活
如果你的CPU多线程很厉害的话可以采用多线程运行
import cv2
import dlib
import time
import threading
# 加载 Dlib 的人脸检测器
detector = dlib.get_frontal_face_detector()
# 打开摄像头(默认摄像头,如果有多个摄像头可以修改参数)
cap = cv2.VideoCapture(0)
# 计算帧率的变量
start_time = time.time()
frame_count = 0
update_interval = 0.1 # 更新帧率的时间间隔(秒)
# 帧率的全局变量
fps = 0
# 锁,用于确保线程安全
lock = threading.Lock()
# 函数:人脸检测
def face_detection(frame):
global fps, frame_count, start_time
# 将帧转换为灰度图
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
# 在帧中检测人脸
faces = detector(gray)
# 绘制矩形框标注检测到的人脸
for face in faces:
x, y, w, h = face.left(), face.top(), face.width(), face.height()
cv2.rectangle(frame, (x, y), (x + w, y + h), (238, 238, 0), 1)
# 计算帧率
with lock:
frame_count += 1
elapsed_time = time.time() - start_time
if elapsed_time >= update_interval:
fps = frame_count / elapsed_time
frame_count = 0
start_time = time.time()
# 函数:显示帧率
def display_fps(frame):
with lock:
cv2.putText(frame, "FPS: {:.2f}".format(fps), (10, 20), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
# 线程函数:处理视频帧
def process_frames():
while True:
# 读取一帧
ret, frame = cap.read()
# 调用人脸检测函数
face_detection(frame)
# 调用显示帧率函数
display_fps(frame)
# 显示结果
cv2.imshow('Detected Faces', frame)
# 等待一段时间,确保图像显示
cv2.waitKey(30)
# 按 'q' 键退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 创建线程
processing_thread = threading.Thread(target=process_frames)
# 启动线程
processing_thread.start()
# 等待线程结束
processing_thread.join()
# 释放摄像头并关闭所有窗口
cap.release()
cv2.destroyAllWindows()
结语
这次真结束了
拜拜ヾ( ̄▽ ̄)Bye~Bye~