电子说
我们尝试模块化并分离管道构建块,这种方法将为我们提供易于管理的代码,并使测试更容易编写:
import os
import cv2
from pipeline.libs.face_detector import FaceDetector
import tests.config as config
class TestFaceDetector:
def test_face_detector(self):
prototxt = os.path.join(config.MODELS_FACE_DETECTOR_DIR, "deploy.prototxt.txt")
model = os.path.join(config.MODELS_FACE_DETECTOR_DIR, "res10_300x300_ssd_iter_140000.caffemodel")
detector = FaceDetector(prototxt, model)
test_image = cv2.imread(os.path.join(config.ASSETS_IMAGES_DIR, "friends", "friends_01.jpg"))
faces = detector.detect([test_image])
assert len(faces) == 1
assert len(faces[0]) # Should recognize some faces from friends_01.jpg
使用管道架构,可以很容易地CascadeDetectFaces从上一篇文章换成更准确的深度学习人脸检测器模型。让我们FaceDetector在新的DetectFaces管道步骤中使用:
from pipeline.pipeline import Pipeline
from pipeline.libs.face_detector import FaceDetector
class DetectFaces(Pipeline):
def __init__(self, prototxt, model, batch_size=1, confidence=0.5):
self.detector = FaceDetector(prototxt, model, confidence=confidence)
self.batch_size = batch_size
super(DetectFaces, self).__init__()
def generator(self):
batch = []
stop = False
while self.has_next() and not stop:
try:
# Buffer the pipeline stream
data = next(self.source)
batch.append(data)
except StopIteration:
stop = True
# Check if there is anything in batch.
# Process it if the size match batch_size or there is the end of the input stream.
if len(batch) and (len(batch) == self.batch_size or stop):
# Prepare images batch
images = [data["image"] for data in batch]
# Detect faces on all images at once
faces = self.detector.detect(images)
# Extract the faces and attache them to the proper image
for image_idx, image_faces in faces.items():
batch[image_idx]["faces"] = image_faces
# Yield all the data from buffer
for data in batch:
if self.filter(data):
yield self.map(data)
batch = []
我们对图像流(第15–20行)进行缓冲,直到到达batch_size(第24行)为止,然后在所有缓冲的图像上(第28行)检测面部,收集面部坐标和置信度(第31–32行),然后重新生成图像(第35-37行)。
当我们使用GPU(图形处理单元)时,我们的武器库中同时运行着数千个处理内核,这些内核专门用于矩阵运算。批量执行推理总是更快,一次向深度学习模型展示的图像多于一张一张。
保存面孔和摘要
SaveFaces并SaveSummary产生输出结果。在SaveFaces类,使用map功能,遍历所有检测到的面部,从图像裁剪他们并保存到输出目录。
SaveSummary类的任务是收集有关已识别面部的所有元数据,并将它们保存为结构良好的JSON文件,该map函数用于缓冲元数据。接下来,我们使用额外的write功能扩展我们的类,我们将需要在管道的末尾触发以将JSON文件与摘要一起保存。脸部图像针对每一帧存储在单独的目录中。
视频输出
为了观察流水线的结果,很高兴可以显示带有带注释的面孔的视频。关于AnnotateImage(pipeline/annotate_image.py)/DisplayVideo(pipeline/display_video.py)的全部内容。
运行中的管道
在process_video_pipeline.py文件中我们可以看到,整个管道的定义如下:
pipeline = (capture_video |
detect_faces |
save_faces |
annotate_image |
display_video |
save_video |
save_summary)
上面有很多解释,但是视频和图像胜于雄辩。让我们来看一下触发命令的管道:
python process_video_pipeline.py -i assets/videos/faces.mp4 -p -d -ov faces.avi,M,];
-p将显示进度条,
-d显示带有批注面孔的视频结果,
-ov faces.avi并将视频结果保存到output文件夹。
正如我们在示例视频中看到的那样,并不是所有脸孔都能被识别。我们可以降低设置参数的深度学习模型的置信度confidence 0.2(默认值为0.5)。降低置信度阈值会增加假阳性的发生(在图像中没有脸的位置出现脸)。
DetectFaces类的批量处理大小:
$ python process_video_pipeline.py -i assets/videos/faces.mp4 -p
--batch-size 1
100%|███████████████████████████| 577/577 [00:11<00:00, 52.26it/s]
[INFO] Saving summary to output/summary.json...
$ python process_video_pipeline.py -i assets/videos/faces.mp4 -p
--batch-size 4
100%|███████████████████████████| 577/577 [00:09<00:00, 64.66it/s]
[INFO] Saving summary to output/summary.json...
$ python process_video_pipeline.py -i assets/videos/faces.mp4 -p
--batch-size 8
100%|███████████████████████████| 577/577 [00:10<00:00, 56.04it/s]
[INFO] Saving summary to output/summary.json...
在我们的硬件上(2.20GHz的Core i7–8750H CPU和NVIDIA RTX 2080 Ti),我门每秒获得52.26帧的图像--batch-size 1,但是对于--batch-size 4我们来说,速度却提高到了每秒64.66帧。
全部0条评论
快来发表一下你的评论吧 !