我們嘗試模塊化并分離管道構(gòu)建塊,這種方法將為我們提供易于管理的代碼,并使測試更容易編寫:
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
使用管道架構(gòu),可以很容易地CascadeDetectFaces從上一篇文章?lián)Q成更準(zhǔn)確的深度學(xué)習(xí)人臉檢測器模型。讓我們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行)進(jìn)行緩沖,直到到達(dá)batch_size(第24行)為止,然后在所有緩沖的圖像上(第28行)檢測面部,收集面部坐標(biāo)和置信度(第31–32行),然后重新生成圖像(第35-37行)。
當(dāng)我們使用GPU(圖形處理單元)時,我們的武器庫中同時運(yùn)行著數(shù)千個處理內(nèi)核,這些內(nèi)核專門用于矩陣運(yùn)算。批量執(zhí)行推理總是更快,一次向深度學(xué)習(xí)模型展示的圖像多于一張一張。
保存面孔和摘要
SaveFaces并SaveSummary產(chǎn)生輸出結(jié)果。在SaveFaces類,使用map功能,遍歷所有檢測到的面部,從圖像裁剪他們并保存到輸出目錄。
SaveSummary類的任務(wù)是收集有關(guān)已識別面部的所有元數(shù)據(jù),并將它們保存為結(jié)構(gòu)良好的JSON文件,該map函數(shù)用于緩沖元數(shù)據(jù)。接下來,我們使用額外的write功能擴(kuò)展我們的類,我們將需要在管道的末尾觸發(fā)以將JSON文件與摘要一起保存。臉部圖像針對每一幀存儲在單獨(dú)的目錄中。
視頻輸出
為了觀察流水線的結(jié)果,很高興可以顯示帶有帶注釋的面孔的視頻。關(guān)于AnnotateImage(pipeline/annotate_image.py)/DisplayVideo(pipeline/display_video.py)的全部內(nèi)容。
運(yùn)行中的管道
在process_video_pipeline.py文件中我們可以看到,整個管道的定義如下:
pipeline = (capture_video |
detect_faces |
save_faces |
annotate_image |
display_video |
save_video |
save_summary)
上面有很多解釋,但是視頻和圖像勝于雄辯。讓我們來看一下觸發(fā)命令的管道:
python process_video_pipeline.py -i assets/videos/faces.mp4 -p -d -ov faces.avi,M,];
-p將顯示進(jìn)度條,
-d顯示帶有批注面孔的視頻結(jié)果,
-ov faces.avi并將視頻結(jié)果保存到output文件夾。
正如我們在示例視頻中看到的那樣,并不是所有臉孔都能被識別。我們可以降低設(shè)置參數(shù)的深度學(xué)習(xí)模型的置信度confidence 0.2(默認(rèn)值為0.5)。降低置信度閾值會增加假陽性的發(fā)生(在圖像中沒有臉的位置出現(xiàn)臉)。
DetectFaces類的批量處理大?。?/p>
$ 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幀。
-
攝像頭
+關(guān)注
關(guān)注
59文章
4793瀏覽量
95276 -
OpenCV
+關(guān)注
關(guān)注
29文章
624瀏覽量
41214 -
JSON
+關(guān)注
關(guān)注
0文章
116瀏覽量
6929
發(fā)布評論請先 登錄
相關(guān)推薦
評論