tensorflow图形检测_社交距离检测器——Tensorflow检测模型设计
在隔離期間,我花時(shí)間在github上探索Tensorflow的大量預(yù)訓(xùn)練模型。這樣做時(shí),我偶然發(fā)現(xiàn)了一個(gè)包含25 個(gè)帶有性能和速度指標(biāo)的預(yù)訓(xùn)練對(duì)象檢測模型的存儲(chǔ)庫。擁有一些計(jì)算機(jī)視覺知識(shí)并給出了實(shí)際的背景知識(shí),我認(rèn)為使用其中之一來構(gòu)建社交隔離應(yīng)用程序可能會(huì)很有趣。
更重要的是,上學(xué)期在計(jì)算機(jī)視覺課程中向我介紹了OpenCV,并意識(shí)到在執(zhí)行許多小型項(xiàng)目時(shí)它的功能多么強(qiáng)大。其中之一包括執(zhí)行圖片的鳥瞰轉(zhuǎn)換。一個(gè)鳥瞰圖是一個(gè)基本場景的自上而下的表示。這是在構(gòu)建自動(dòng)駕駛汽車應(yīng)用程序時(shí)經(jīng)常執(zhí)行的任務(wù)。
車載攝像頭鳥瞰系統(tǒng)的實(shí)現(xiàn)
這使我意識(shí)到,將這種技術(shù)應(yīng)用于我們想要監(jiān)視社會(huì)距離的場景可以提高其質(zhì)量。本文介紹了我如何使用深度學(xué)習(xí)模型以及計(jì)算機(jī)視覺方面的一些知識(shí)來構(gòu)建強(qiáng)大的社交距離探測器。
本文的結(jié)構(gòu)如下:
- 選型
- 人物檢測
- 鳥瞰圖轉(zhuǎn)換
- 社會(huì)距離測量
- 結(jié)果與改進(jìn)
以下所有代碼以及安裝說明都可以在我的github存儲(chǔ)庫中找到。
1.選型
Tensorflow對(duì)象檢測模型Zoo中可用的所有模型均已在COCO數(shù)據(jù)集(COntext中的通用對(duì)象)上進(jìn)行了訓(xùn)練。該數(shù)據(jù)集包含120,000張圖像,這些圖像中總共有880,000個(gè)帶標(biāo)簽的對(duì)象。這些模型經(jīng)過訓(xùn)練可以檢測此數(shù)據(jù)集中標(biāo)記的90種不同類型的對(duì)象。所有這些不同對(duì)象的完整列表可在github repo的data部分訪問的存儲(chǔ)庫的data部分中找到。這些對(duì)象包括汽車,牙刷,香蕉和人。
可用型號(hào)的非詳盡清單
根據(jù)模型的速度,它們具有不同的性能。為了確定如何根據(jù)預(yù)測速度來利用模型的質(zhì)量,我進(jìn)行了一些測試。由于此應(yīng)用程序的目標(biāo)不是能夠執(zhí)行實(shí)時(shí)分析,因此我最終選擇了fast_rcnn_inception_v2_coco ,它的mAP(驗(yàn)證集上的檢測器性能)為28,非常強(qiáng)大,執(zhí)行速度為58 ms 。
2.人員檢測
要使用這種模型,為了檢測人員,必須完成一些步驟:
- 將包含模型的文件加載到張量流圖中。并定義您要從模型獲得的輸出。
- 對(duì)于每一幀,將圖像通過圖形以獲取所需的輸出。
- 過濾掉不需要檢測的弱預(yù)測和對(duì)象。
加載并啟動(dòng)模型
設(shè)計(jì)張量流模型的工作方式是使用圖形。第一步意味著將模型加載到張量流圖中。該圖將包含為了獲得所需檢測而將要執(zhí)行的不同操作。下一步是創(chuàng)建一個(gè)會(huì)話,該會(huì)話是負(fù)責(zé)執(zhí)行上圖中定義的操作的實(shí)體。有關(guān)圖形和會(huì)話的更多說明,請參見此處。我決定實(shí)現(xiàn)一個(gè)類,以將與張量流圖有關(guān)的所有數(shù)據(jù)保持在一起。
class Model: """ Class that contains the model and all its functions """ def __init__(self, model_path): """ Initialization function @ model_path : path to the model """ # Declare detection graph self.detection_graph = tf.Graph() # Load the model into the tensorflow graph with self.detection_graph.as_default(): od_graph_def = tf.compat.v1.GraphDef() with tf.io.gfile.GFile(model_path, 'rb') as file: serialized_graph = file.read() od_graph_def.ParseFromString(serialized_graph) tf.import_graph_def(od_graph_def, name='') # Create a session from the detection graph self.sess = tf.compat.v1.Session(graph=self.detection_graph) def predict(self,img): """ Get the predicition results on 1 frame @ img : our img vector """ # Expand dimensions since the model expects images to have shape: [1, None, None, 3] img_exp = np.expand_dims(img, axis=0) # Pass the inputs and outputs to the session to get the results (boxes, scores, classes) = self.sess.run([self.detection_graph.get_tensor_by_name('detection_boxes:0'), self.detection_graph.get_tensor_by_name('detection_scores:0'), self.detection_graph.get_tensor_by_name('detection_classes:0')],feed_dict={self.detection_graph.get_tensor_by_name('image_tensor:0'): img_exp}) return (boxes, scores, classes)通過模型傳遞每一幀
對(duì)于需要處理的每個(gè)幀,都會(huì)啟動(dòng)一個(gè)新會(huì)話。這是通過調(diào)用run()函數(shù)來完成的。這樣做時(shí)必須指定一些參數(shù)。其中包括模型所需的輸入類型以及我們要從中獲取的輸出。在我們的情況下,所需的輸出如下:
- 每個(gè)對(duì)象的邊界框坐標(biāo)
- 每個(gè)預(yù)測的置信度(0到1)
- 預(yù)測等級(jí)(0到90)
過濾掉弱預(yù)測和不相關(guān)的對(duì)象
人物檢測結(jié)果
模型檢測到的許多類之一是人。與一個(gè)人關(guān)聯(lián)的類別為1。
為了排除弱預(yù)測(閾值:0.75)和除人以外的所有其他類別的對(duì)象,我使用了if語句,將這兩個(gè)條件組合在一起以排除任何其他對(duì)象以進(jìn)行進(jìn)一步計(jì)算。
if int(classes[i]) == 1 and scores[i] > 0.75但是,由于這些模型已經(jīng)過于訓(xùn)練,因此不可能僅檢測此類。因此,這些模型要花很長時(shí)間才能運(yùn)行,因?yàn)樗鼈冊噲D識(shí)別場景中所有90種不同類型的對(duì)象。
3.鳥瞰圖轉(zhuǎn)換
如引言中所述,執(zhí)行鳥瞰圖轉(zhuǎn)換可為我們提供場景的俯視圖。值得慶幸的是,OpenCV具有強(qiáng)大的內(nèi)置功能,可以將該方法應(yīng)用于圖像,以便將所拍攝的圖像從透視圖角度轉(zhuǎn)換為頂視圖。我使用了偉大的Adrian Rosebrock 的教程來了解如何做到這一點(diǎn)。
第一步涉及在原始圖像上選擇4個(gè)點(diǎn),這些點(diǎn)將成為要轉(zhuǎn)換的計(jì)劃的拐角點(diǎn)。這一點(diǎn)必須形成一個(gè)矩形,其中至少兩個(gè)相對(duì)的側(cè)面平行。如果不這樣做,則轉(zhuǎn)換發(fā)生時(shí)的比例將不同。我已經(jīng)在我的存儲(chǔ)庫中實(shí)現(xiàn)了一個(gè)腳本,該腳本使用OpenCV 的setMouseCallback()函數(shù)來獲取這些坐標(biāo)。計(jì)算變換矩陣的函數(shù)還需要使用圖像的image.shape屬性來計(jì)算圖像的尺寸。
width, height, _ = image.shape這將返回寬度,高度和其他不相關(guān)的彩色像素值。讓我們看看它們?nèi)绾斡糜谟?jì)算轉(zhuǎn)換矩陣:
def compute_perspective_transform(corner_points,width,height,image):""" Compute the transformation matrix@ corner_points : 4 corner points selected from the image@ height, width : size of the imagereturn : transformation matrix and the transformed image"""# Create an array out of the 4 corner pointscorner_points_array = np.float32(corner_points)# Create an array with the parameters (the dimensions) required to build the matriximg_params = np.float32([[0,0],[width,0],[0,height],[width,height]])# Compute and return the transformation matrixmatrix = cv2.getPerspectiveTransform(corner_points_array,img_params) img_transformed = cv2.warpPerspective(image,matrix,(width,height))return matrix,img_transformed請注意,我選擇還返回矩陣,因?yàn)橄乱徊綄⑹褂迷摼仃噥碛?jì)算每個(gè)檢測到的人的新坐標(biāo)。其結(jié)果是幀中每個(gè)人的“ GPS”坐標(biāo)。這是更為準(zhǔn)確使用這些不是使用原來的地面點(diǎn),因?yàn)樵谕敢晥D中,距離是不一樣的,當(dāng)人們都在不同的計(jì)劃,而不是在從相機(jī)相同的距離。與使用原始框架中的點(diǎn)相比,這可以大大改善社會(huì)距離度量。
對(duì)于檢測到的每個(gè)人,將返回構(gòu)建邊界框所需的2個(gè)點(diǎn)。這些點(diǎn)是框的左上角和右下角。從這些中,我通過獲取它們之間的中間點(diǎn)來計(jì)算盒子的質(zhì)心。使用此結(jié)果,我計(jì)算了位于框底部中心的點(diǎn)的坐標(biāo)。我認(rèn)為,這一點(diǎn)(我稱為基點(diǎn))是圖像中人的坐標(biāo)的最佳表示。
然后,我使用變換矩陣為每個(gè)檢測到的地面點(diǎn)計(jì)算變換后的坐標(biāo)。在檢測到人之后,使用cv2.perspectiveTransform()在每一幀上完成此操作。這就是我實(shí)現(xiàn)此任務(wù)的方式:
def compute_point_perspective_transformation(matrix,list_downoids):""" Apply the perspective transformation to every ground point which have been detected on the main frame.@ matrix : the 3x3 matrix @ list_downoids : list that contains the points to transformreturn : list containing all the new points"""# Compute the new coordinates of our pointslist_points_to_detect = np.float32(list_downoids).reshape(-1, 1, 2)transformed_points = cv2.perspectiveTransform(list_points_to_detect, matrix)# Loop over the points and add them to the list that will be returnedtransformed_points_list = list()for i in range(0,transformed_points.shape[0]):transformed_points_list.append([transformed_points[i][0][0],transformed_points[i][0][1]])return transformed_points_list4.衡量社會(huì)距離
在每幀上調(diào)用此函數(shù)后,將返回一個(gè)包含所有新轉(zhuǎn)換點(diǎn)的列表。從這個(gè)列表中,我不得不計(jì)算每對(duì)點(diǎn)之間的距離。我使用了來自itertools庫的function Combines ()函數(shù),該函數(shù)允許在列表中獲取所有可能的組合而無需保留雙精度。在此堆棧溢出問題上對(duì)此進(jìn)行了很好的解釋。剩余部分是簡單的數(shù)學(xué)運(yùn)算:使用python中的math.sqrt()函數(shù)很容易實(shí)現(xiàn)兩點(diǎn)之間的距離。選擇的閾值為120像素,因?yàn)樗谖覀兊膱鼍爸写蠹s等于2英尺。
# Check if 2 or more people have been detected (otherwise no need to detect) if len(transformed_downoids) >= 2: # Iterate over every possible 2 by 2 between the points combinations list_indexes = list(itertools.combinations(range(len(transformed_downoids)), 2)) for i,pair in enumerate(itertools.combinations(transformed_downoids, r=2)): # Check if the distance between each combination of points is less than the minimum distance chosen if math.sqrt( (pair[0][0] - pair[1][0])**2 + (pair[0][1] - pair[1][1])**2 ) < int(distance_minimum): # Change the colors of the points that are too close from each other to red change_color_topview(pair) # Get the equivalent indexes of these points in the original frame and change the color to red index_pt1 = list_indexes[i][0] index_pt2 = list_indexes[i][1] change_color_originalframe(index_pt1,index_pt2)一旦確定兩個(gè)點(diǎn)之間的距離太近,標(biāo)記該點(diǎn)的圓圈的顏色將從綠色更改為紅色,并且與原始幀上的邊界框的顏色相同。
5.結(jié)果
讓我回復(fù)一下該項(xiàng)目的工作方式:
- 首先獲取計(jì)劃的4個(gè)角點(diǎn),然后應(yīng)用透視變換獲得該計(jì)劃的鳥瞰圖并保存變換矩陣。
- 獲取原始幀中檢測到的每個(gè)人的邊界框。
- 計(jì)算此框的最低點(diǎn)。這是位于雙腳之間的點(diǎn)。
- 使用轉(zhuǎn)換矩陣對(duì)這些點(diǎn)中的每一個(gè)獲取每個(gè)人的真實(shí)“ GPS”坐標(biāo)。
- 使用itertools.combinations()測量框架中每個(gè)點(diǎn)到所有其他點(diǎn)的距離。
- 如果檢測到社交距離沖突,請將邊界框的顏色更改為紅色。
總結(jié)
以上是生活随笔為你收集整理的tensorflow图形检测_社交距离检测器——Tensorflow检测模型设计的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 悲观的反义词 悲观的反义词有什么
- 下一篇: datagridview绑定数据源不显示