本文主要是翻譯人數(shù)統(tǒng)計(jì)器?。感謝Adrian Rosebrock分享視頻人數(shù)統(tǒng)計(jì)的技術(shù)。先上圖看效果,再做技術(shù)分享。主要分四個(gè)部分:基礎(chǔ)支持,目標(biāo)檢測(cè)與目標(biāo)追蹤,實(shí)踐人數(shù)統(tǒng)計(jì)器,視頻檢驗(yàn)效果。

一、基礎(chǔ)支持
需要安裝第三方包:NumPy、OpenCV、dlib、imutils。使用anconda命令conda install xxx。
二、目標(biāo)檢測(cè)與目標(biāo)追蹤
當(dāng)我們應(yīng)用對(duì)象檢測(cè)時(shí),我們確定對(duì)象在圖像/幀中的位置。對(duì)象檢測(cè)器通常在計(jì)算上也比對(duì)象跟蹤算法更昂貴,因此更慢。物體檢測(cè)算法的示例包括Haar級(jí)聯(lián),HOG +線(xiàn)性SVM和基于深度學(xué)習(xí)的物體檢測(cè)器,諸如更快的R-CNN,YOLO和單次檢測(cè)器(SSD)
對(duì)象跟蹤器將接受對(duì)象在圖像中的位置的輸入(x,y)坐標(biāo),并將:
1、為該特定對(duì)象分配唯一ID
2、跟蹤對(duì)象在視頻流中移動(dòng)時(shí),根據(jù)幀的各種屬性(漸變,光流等)預(yù)測(cè)下一幀中的新對(duì)象位置對(duì)象跟蹤算法的示例包括MedianFlow,MOSSE,GOTURN,kernalized相關(guān)濾波器和判別相關(guān)濾波器,僅舉幾個(gè)例子。如果您有興趣了解OpenCV中內(nèi)置的對(duì)象跟蹤算法的更多信息,請(qǐng)務(wù)必參考此博客文章。
結(jié)合對(duì)象檢測(cè)和對(duì)象跟蹤
高度精確的對(duì)象跟蹤器將對(duì)象檢測(cè)和對(duì)象跟蹤的概念結(jié)合到一個(gè)算法中,通常分為兩個(gè)階段:
1、檢測(cè):在檢測(cè)階段,我們運(yùn)行計(jì)算上更昂貴的對(duì)象跟蹤器,以(1)檢測(cè)新對(duì)象是否已進(jìn)入我們的視圖,以及(2)查看是否可以找到在跟蹤階段“丟失”的對(duì)象。對(duì)于每個(gè)檢測(cè)到的對(duì)象,我們使用新的邊界框坐標(biāo)創(chuàng)建或更新對(duì)象跟蹤器。由于我們的對(duì)象檢測(cè)器在計(jì)算上更加昂貴,我們每N幀只運(yùn)行一次這個(gè)階段。
2、跟蹤:當(dāng)我們不處于“檢測(cè)”階段時(shí),我們處于“跟蹤”階段。對(duì)于我們檢測(cè)到的每個(gè)對(duì)象,我們創(chuàng)建一個(gè)對(duì)象跟蹤器,以便在對(duì)象圍繞框架移動(dòng)時(shí)跟蹤對(duì)象。我們的對(duì)象跟蹤器應(yīng)該比對(duì)象檢測(cè)器更快,更有效。我們將繼續(xù)跟蹤,直到我們到達(dá)第N幀,然后重新運(yùn)行我們的物體探測(cè)器。然后整個(gè)過(guò)程重復(fù)。
這種混合方法的好處是我們可以應(yīng)用高度精確的物體檢測(cè)方法,而不會(huì)產(chǎn)生很大的計(jì)算負(fù)擔(dān)。我們將實(shí)施這樣的跟蹤系統(tǒng)來(lái)建立我們的人數(shù)統(tǒng)計(jì)器。
三、實(shí)踐人數(shù)統(tǒng)計(jì)器
項(xiàng)目結(jié)構(gòu)
讓我們回顧一下今天博客文章的項(xiàng)目結(jié)構(gòu)。從“下載”部分獲取代碼后,可以使用tree命令檢查目錄結(jié)構(gòu):

歸入最重要的兩個(gè)目錄。就是:
1、pyimagesearch /:該模塊包含質(zhì)心跟蹤算法。質(zhì)心跟蹤算法在“組合對(duì)象跟蹤算法”部分中介紹,但代碼不是。有關(guān)質(zhì)心跟蹤代碼(centroidtracker.py)的評(píng)論,請(qǐng)參閱本系列的第一篇文章質(zhì)心算法。
2、mobilenet_ssd /:包含Caffe深度學(xué)習(xí)模型文件。我們將使用MobileNet單次檢測(cè)器(SSD),該文章在本篇博文的頂部“用于物體檢測(cè)的單次檢測(cè)器”一節(jié)中介紹。
今天項(xiàng)目的核心包含在people_counter.py腳本中 - 這就是我們花費(fèi)大部分時(shí)間的地方。我們今天還將審查trackableobject.py腳本。
結(jié)合對(duì)象跟蹤算法

要實(shí)現(xiàn)我們的人員計(jì)數(shù)器,我們將同時(shí)使用OpenCV和dlib。我們將OpenCV用于標(biāo)準(zhǔn)計(jì)算機(jī)視覺(jué)/圖像處理功能,以及用于人數(shù)統(tǒng)計(jì)的深度學(xué)習(xí)對(duì)象檢測(cè)器。
然后我們將使用dlib來(lái)實(shí)現(xiàn)相關(guān)過(guò)濾器。我們也可以在這里使用OpenCV;但是,dlib對(duì)象跟蹤實(shí)現(xiàn)對(duì)于此項(xiàng)目來(lái)說(shuō)更容易使用。
除了dlib的對(duì)象跟蹤實(shí)現(xiàn),我們還將使用幾周前的質(zhì)心跟蹤實(shí)現(xiàn)。查看整個(gè)質(zhì)心跟蹤算法超出了本博文的范圍,但我在下面簡(jiǎn)要介紹了一下。
1、我們接受一組邊界框并計(jì)算它們對(duì)應(yīng)的質(zhì)心(即邊界框的中心)

在上面的圖像中,您可以看到我們?cè)谒惴ǖ某跏嫉杏袃蓚€(gè)要跟蹤的對(duì)象。
2、我們計(jì)算任何新質(zhì)心(黃色)和現(xiàn)有質(zhì)心(紫色)之間的歐幾里德距離:

質(zhì)心跟蹤算法假設(shè)它們之間具有最小歐幾里德距離的質(zhì)心對(duì)必須是相同的對(duì)象ID。
在上面的示例圖像中,我們有兩個(gè)現(xiàn)有的質(zhì)心(紫色)和三個(gè)新的質(zhì)心(黃色),這意味著已經(jīng)檢測(cè)到一個(gè)新的對(duì)象(因?yàn)檫€有一個(gè)新的質(zhì)心與舊的質(zhì)心)。
然后箭頭表示計(jì)算所有紫色質(zhì)心和所有黃色質(zhì)心之間的歐幾里德距離。
一旦我們得到歐幾里德距離,我們就會(huì)嘗試在步驟3中關(guān)聯(lián)對(duì)象ID:

你可以看到我們的質(zhì)心跟蹤器已選擇關(guān)聯(lián)質(zhì)心,以最大限度地減少各自的歐幾里德距離。
但是左下角的那個(gè)點(diǎn)怎么樣?它沒(méi)有任何關(guān)聯(lián) - 我們?cè)撛趺崔k?
4、要回答這個(gè)問(wèn)題,我們需要執(zhí)行步驟#4,注冊(cè)新對(duì)象

注冊(cè)只是意味著我們將新對(duì)象添加到我們的跟蹤對(duì)象列表中:
1、為其分配新的對(duì)象ID
2、存儲(chǔ)新對(duì)象的邊界框坐標(biāo)的質(zhì)心
如果一個(gè)對(duì)象丟失或離開(kāi)了視野,我們可以簡(jiǎn)單地取消注冊(cè)該對(duì)象(步驟#5)。當(dāng)對(duì)象“丟失”或“不再可見(jiàn)”時(shí),您究竟如何處理實(shí)際上取決于您的確切應(yīng)用程序,但對(duì)于我們的人員計(jì)數(shù)器,當(dāng)他們無(wú)法與任何現(xiàn)有人員對(duì)象匹配40個(gè)連續(xù)幀時(shí),我們將取消注冊(cè)人員ID 。同樣,這只是質(zhì)心跟蹤算法的簡(jiǎn)要概述。有關(guān)更詳細(xì)的評(píng)論,包括用于實(shí)現(xiàn)質(zhì)心跟蹤的源代碼的說(shuō)明,請(qǐng)務(wù)必參考這篇文章。
創(chuàng)建“可跟蹤對(duì)象”
為了跟蹤和計(jì)算視頻流中的對(duì)象,我們需要一種簡(jiǎn)單的方法來(lái)存儲(chǔ)有關(guān)對(duì)象本身的信息,包括:
1、對(duì)象ID
2、以前的質(zhì)心(所以我們可以很容易地計(jì)算物體移動(dòng)的方向)
3、該對(duì)象是否已被計(jì)算
為了實(shí)現(xiàn)所有這些目標(biāo),我們可以定義TrackableObject的實(shí)例 - 打開(kāi)trackableobject.py文件并插入以下代碼:

TrackableObject構(gòu)造函數(shù)接受objectID + centroid并存儲(chǔ)它們。 centroids變量是一個(gè)列表,因?yàn)樗鼘粋€(gè)對(duì)象的質(zhì)心位置歷史記錄。
構(gòu)造函數(shù)還將count初始化為False,表示該對(duì)象尚未計(jì)數(shù)。
使用OpenCV + Python實(shí)現(xiàn)我們的人員計(jì)數(shù)器
有了我們所有支持的Python幫助工具和類(lèi),我們現(xiàn)在可以構(gòu)建我們的OpenCV人員計(jì)數(shù)器了。
打開(kāi)你的people_counter.py文件并插入以下代碼:

我們首先導(dǎo)入必要的包:
從pyimagesearch模塊,我們導(dǎo)入自定義的CentroidTracker和TrackableObject類(lèi)。
1、imutils.video中的VideoStream和FPS模塊將幫助我們使用網(wǎng)絡(luò)攝像頭并計(jì)算估計(jì)的每秒幀數(shù)(FPS)吞吐率。
2、我們需要為其OpenCV便利功能提供imutils。
3、dlib庫(kù)將用于其相關(guān)跟蹤器實(shí)現(xiàn)。
4、OpenCV將用于深度神經(jīng)網(wǎng)絡(luò)推理,打開(kāi)視頻文件,編寫(xiě)視頻文件以及向屏幕顯示輸出幀。
現(xiàn)在所有的工具都在我們手里,讓我們解析命令行參數(shù):

我們有六個(gè)命令行參數(shù),允許我們?cè)谶\(yùn)行時(shí)從終端將信息傳遞給我們的人員計(jì)數(shù)器腳本:
1、--prototxt:Caffe“部署”原型文件的路徑。
2、--model:Caffe預(yù)訓(xùn)練CNN模型的路徑。
3、--input:可選的輸入視頻文件路徑。如果未指定路徑,則將使用您的網(wǎng)絡(luò)攝像頭。
4、--output:可選的輸出視頻路徑。如果未指定路徑,則不會(huì)錄制視頻。
5、--confidence:默認(rèn)值為0.4,這是有助于濾除弱檢測(cè)的最小概率閾值。
6、--skip-frames:在跟蹤對(duì)象上再次運(yùn)行DNN檢測(cè)器之前要跳過(guò)的幀數(shù)。請(qǐng)記住,對(duì)象檢測(cè)在計(jì)算上很昂貴,但它確實(shí)有助于我們的跟蹤器重新評(píng)估幀中的對(duì)象。默認(rèn)情況下,我們使用OpenCV DNN模塊和CNN單發(fā)探測(cè)器模型在檢測(cè)對(duì)象之間跳過(guò)30幀。
現(xiàn)在我們的腳本可以在運(yùn)行時(shí)動(dòng)態(tài)處理命令行參數(shù),讓我們準(zhǔn)備我們的SSD:

首先,我們將初始化CLASSES - 我們的SSD支持的類(lèi)列表。如果您使用的是“下載”中提供的模型,則不應(yīng)更改此列表。我們只對(duì)“人”類(lèi)感興趣,但你也可以計(jì)算其他移動(dòng)物體(但是,如果你的“盆栽植物”,“沙發(fā)”或“電視監(jiān)視器”長(zhǎng)出腿并開(kāi)始移動(dòng),你應(yīng)該跑出你的房子尖叫而不是計(jì)數(shù)它們???)。
在38行上,我們加載了用于檢測(cè)物體的預(yù)訓(xùn)練的MobileNet SSD(但同樣,我們只對(duì)檢測(cè)和跟蹤人員感興趣,而不是任何其他類(lèi)別)。要了解有關(guān)MobileNet和SSD的更多信息,請(qǐng)參閱我之前的博客文章。
從那里我們可以初始化我們的視頻流:

首先,我們處理我們使用網(wǎng)絡(luò)攝像頭視頻流的情況(第41-44行)。否則,我們將從視頻文件中捕獲幀(第47-49行)。
在開(kāi)始循環(huán)幀之前,我們?nèi)匀恍枰獔?zhí)行一些初始化:

其余的初始化包括:
1、寫(xiě):寫(xiě)視頻。如果我們要寫(xiě)視頻,我們稍后會(huì)實(shí)例化這個(gè)對(duì)象。
2、W和H:我們的框架尺寸。我們需要將它們插入到cv2.VideoWriter中。
3、ct:我們的CentroidTracker。有關(guān)CentroidTracker實(shí)施的詳細(xì)信息,請(qǐng)務(wù)必參考幾周前的博客文章。
4、跟蹤器:用于存儲(chǔ)dlib關(guān)聯(lián)跟蹤器的列表。要了解dlib相關(guān)性跟蹤,請(qǐng)繼續(xù)關(guān)注下周的帖子。
5、trackableObjects:將objectID映射到TrackableObject的字典。
6、totalFrames:處理的幀總數(shù)。
7、totalDown和totalUp:向下或向上移動(dòng)的對(duì)象/人的總數(shù)。這些變量衡量腳本的實(shí)際“人數(shù)統(tǒng)計(jì)”結(jié)果。
8、fps:我們的每秒幀數(shù)估算器用于基準(zhǔn)測(cè)試。
注意:如果您在下面的while循環(huán)中迷了,您應(yīng)該參考這個(gè)重要變量的項(xiàng)目符號(hào)列表。
現(xiàn)在我們已經(jīng)完成了所有的初始化,讓我們循環(huán)傳入的幀:

我們開(kāi)始在第76行循環(huán)。在循環(huán)的頂部我們抓住下一幀(第79和80行)。如果我們已經(jīng)到達(dá)視頻的末尾,我們將突破循環(huán)(第84和85行)。預(yù)處理幀發(fā)生在第90和91行。這包括調(diào)整大小和交換顏色通道,因?yàn)閐lib需要rgb圖像。
我們抓取視頻編寫(xiě)器的幀尺寸(第94和95行)。
如果通過(guò)命令行參數(shù)提供輸出路徑(第99-102行),我們將從那里實(shí)例化視頻編寫(xiě)器。要了解有關(guān)將視頻寫(xiě)入磁盤(pán)的更多信息,請(qǐng)務(wù)必參閱此文章。
現(xiàn)在讓我們檢測(cè)人使用SSD:

我們?cè)诘?07行初始化狀態(tài)為“等待”??赡艿臓顟B(tài)狀態(tài)包括:
1、等待:在這種狀態(tài)下,我們正在等待人們被發(fā)現(xiàn)和跟蹤。
2、檢測(cè):我們正在積極地使用MobileNet SSD檢測(cè)人員。
3、跟蹤:在框架中跟蹤人員,我們計(jì)算totalUp和totalDown。
我們的rects列表將通過(guò)檢測(cè)或跟蹤填充。我們繼續(xù)并在第108行初始化rects。
重要的是要理解深度學(xué)習(xí)對(duì)象檢測(cè)器在計(jì)算上非常昂貴,特別是如果您在CPU上運(yùn)行它們。
為了避免在每一幀上運(yùn)行我們的對(duì)象檢測(cè)器,并加快我們的跟蹤管道,我們將跳過(guò)每N幀(由命令行參數(shù)設(shè)置--skip-frames,其中30是默認(rèn)值)。我們只需每N幀就可以使用SSD進(jìn)行物體檢測(cè)。否則,我們將只是跟蹤中間的移動(dòng)物體。
使用第112行的模運(yùn)算符,我們確保每N幀只執(zhí)行if語(yǔ)句中的代碼。
假設(shè)我們已經(jīng)登陸了多個(gè)skip_frames,我們將狀態(tài)更新為“Detecting”(第114行)。
然后我們初始化新的跟蹤器列表(第115行)。
接下來(lái),我們將通過(guò)對(duì)象檢測(cè)進(jìn)行推理。我們首先從圖像中創(chuàng)建一個(gè)blob,然后將blob傳遞到網(wǎng)中以獲得檢測(cè)(第119-121行)。
現(xiàn)在我們將遍歷每個(gè)檢測(cè),希望找到屬于“person”類(lèi)的對(duì)象:

在第124行的檢測(cè)中循環(huán),我們繼續(xù)獲取置信度(第127行)并過(guò)濾掉弱結(jié)果+那些不屬于“人”類(lèi)的行(第131-138行)。
現(xiàn)在我們可以為每個(gè)人計(jì)算一個(gè)邊界框并開(kāi)始相關(guān)性跟蹤:

計(jì)算我們的邊界框發(fā)生在第142和143行。
然后我們?cè)?48行實(shí)例化我們的dlib相關(guān)跟蹤器,然后將對(duì)象的邊界框坐標(biāo)傳遞給dlib.rectangle,將結(jié)果存儲(chǔ)為rect(第149行)。
隨后,我們開(kāi)始在150行跟蹤,并將跟蹤器附加到154行的跟蹤器列表中。
這是我們每N個(gè)跳幀所做的所有操作的包裝!
讓我們來(lái)處理在else塊中進(jìn)行跟蹤的典型操作:

大多數(shù)時(shí)候,我們沒(méi)有重新設(shè)置跳幀skip-frame功能。在此期間,我們將利用我們的跟蹤器來(lái)跟蹤我們的對(duì)象,而不是應(yīng)用檢測(cè)。
我們開(kāi)始在160行的可用跟蹤器上循環(huán)。
我們繼續(xù)將狀態(tài)更新為“跟蹤”(第163行)并抓住對(duì)象位置(第166和167行)。
從那里我們提取位置坐標(biāo)(第170-173行),然后填寫(xiě)我們的rects列表中的信息。
現(xiàn)在讓我們繪制一條水平可視化線(xiàn)(人們必須交叉才能被跟蹤)并使用質(zhì)心跟蹤器來(lái)更新我們的對(duì)象質(zhì)心:

在第181行,我們繪制了水平線(xiàn),我們將用它來(lái)形象化人們“穿越” - 一旦人們?cè)竭^(guò)這條線(xiàn),我們將增加我們各自的柜臺(tái)
然后在第185行,我們利用CentroidTracker實(shí)例來(lái)接受rects列表,無(wú)論它們是通過(guò)對(duì)象檢測(cè)還是對(duì)象跟蹤生成的。我們的質(zhì)心跟蹤器將對(duì)象ID與對(duì)象位置相關(guān)聯(lián)。
在下一個(gè)塊中,我們將檢查一個(gè)人在框架中向上或向下移動(dòng)的邏輯:

我們首先循環(huán)遍歷對(duì)象ID的更新的邊界框坐標(biāo)(第188行)。
在第191行,我們嘗試為當(dāng)前objectID獲取TrackableObject。
如果objectID不存在TrackableObject,我們創(chuàng)建一個(gè)(第194和195行)。
否則,已經(jīng)存在TrackableObject,因此我們需要確定對(duì)象(人)是向上還是向下移動(dòng)。
為此,我們獲取給定對(duì)象的所有先前質(zhì)心位置的y坐標(biāo)值(第204行)。然后我們通過(guò)獲取當(dāng)前質(zhì)心位置和所有先前質(zhì)心位置的平均值之間的差來(lái)計(jì)算方向(線(xiàn)205)。
我們采用均值的原因是為了確保我們的方向跟蹤更加穩(wěn)定。如果我們只為那個(gè)人存儲(chǔ)了前一個(gè)質(zhì)心位置,那么我們就會(huì)對(duì)錯(cuò)誤的方向計(jì)數(shù)進(jìn)行開(kāi)放。請(qǐng)記住,對(duì)象檢測(cè)和對(duì)象跟蹤算法并不“神奇” - 有時(shí)它們會(huì)預(yù)測(cè)可能略微偏離您所期望的邊界框;因此,通過(guò)取平均值,我們可以使我們的人更準(zhǔn)確。
如果TrackableObject尚未計(jì)算(第209行),我們需要確定它是否已準(zhǔn)備好進(jìn)行計(jì)數(shù)(第213-222行),方法是:
檢查方向是否為負(fù)(表示物體向上移動(dòng))并且質(zhì)心位于中心線(xiàn)上方。在這種情況下,我們?cè)黾觮otalUp。
或者檢查方向是否為正(表示物體向下移動(dòng))并且質(zhì)心低于中心線(xiàn)。如果這是真的,我們?cè)黾觮otalDown。
最后,我們將TrackableObject存儲(chǔ)在trackableObjects字典中(第225行),這樣我們就可以在捕獲下一幀時(shí)抓取并更新它。
我們?cè)诨A(chǔ)擴(kuò)展!
接下來(lái)的三個(gè)代碼塊處理:
1、Display :顯示(繪制和書(shū)寫(xiě)文本到框架)
2、將幀寫(xiě)入磁盤(pán)上的視頻文件(如果存在--output命令行參數(shù))
3、捕捉按鍵
4、清理
首先,我們將在框架上繪制一些信息為可視化:

在這里,我們?cè)诳蚣苌细采w以下數(shù)據(jù):
1、ObjectID:每個(gè)對(duì)象的數(shù)字標(biāo)識(shí)符。
2、質(zhì)心:物體的中心將由一個(gè)“點(diǎn)”表示,該點(diǎn)通過(guò)填充圓形而形成。
3、info:包括totalUp,totalDown和status
有關(guān)繪圖操作的評(píng)論,請(qǐng)務(wù)必參閱此博客文章。
然后我們將幀寫(xiě)入視頻文件(如果需要)并處理按鍵:

在這個(gè)塊中我們:
1、Write the?frame,如有必要,將幀寫(xiě)入輸出視頻文件(第249行和第250行)
2、顯示框架和手柄按鍵(第253-258行)。如果按下“q”,我們就會(huì)跳出幀處理循環(huán)。
3、更新我們的fps計(jì)數(shù)器(第263行)
我們沒(méi)有太多的混亂,但現(xiàn)在是時(shí)候清理:

為了完成腳本,我們向終端顯示FPS信息,釋放所有指針,并關(guān)閉所有打開(kāi)的窗口。
之后只有283行代碼,我們現(xiàn)在完成了嗎?
四、視頻檢驗(yàn)效果
要查看我們的OpenCV人員計(jì)數(shù)器,請(qǐng)確保使用此博客文章的“下載”部分下載源代碼和示例視頻。
從那里,打開(kāi)一個(gè)終端并執(zhí)行以下命令:

在這里,您可以看到我們的人員計(jì)數(shù)器正在計(jì)算以下人數(shù):
1、正在進(jìn)入百貨商店(dowm)
2、和離開(kāi)的人數(shù)(up)
在第一個(gè)視頻結(jié)束時(shí),你會(huì)看到有7個(gè)人進(jìn)入,3個(gè)人離開(kāi)。
此外,檢查終端輸出,您將看到我們的人員計(jì)數(shù)器能夠?qū)崟r(shí)運(yùn)行,從而獲得34 FPS。盡管我們正在使用深度學(xué)習(xí)對(duì)象檢測(cè)器來(lái)進(jìn)行更準(zhǔn)確的人物檢測(cè)。
1、通過(guò)我們的兩階段流程,我們可以實(shí)現(xiàn)34 FPS的全部費(fèi)率:
2、每30幀檢測(cè)一次
然后在其間的所有幀中應(yīng)用更快,更有效的對(duì)象跟蹤算法。使用OpenCV計(jì)算人數(shù)的另一個(gè)例子如下:

我在下面添加了一個(gè)簡(jiǎn)短的GIF,讓您了解算法的工作原理:

這次有2人進(jìn)入百貨商店,14人已經(jīng)離開(kāi)。
您可以看到這個(gè)系統(tǒng)對(duì)于對(duì)流量分析感興趣的商店所有者有多大用處。
使用OpenCV計(jì)算人流量的相同類(lèi)型的系統(tǒng)可用于計(jì)算OpenCV的汽車(chē)流量,我希望在未來(lái)的博客文章中涵蓋該主題。