每個目標邊界框的坐標(x, y)
每個邊界框關聯的類別標籤
左下角是一個語義分割的例子。語義分割算法要求我們將輸入圖像中的每個像素與一個類別標籤(包括一個用於背景的類標籤)關聯起來。注意關注我們語義分割的可視化——注意每個目標是如何分割的,但每個「cube」目標都有相同的顏色。 雖然語義分割算法能夠對圖像中的所有目標進行標記,但它們無法區分同一類的兩個對象。 特別是同一個類別的兩個目標是相互遮擋時,問題更加明顯,我們不知道一個對象的邊界在哪裡結束以及哪裡開始,如圖上兩個紫色立方體所示,我們無法說清楚一個立方體邊界的開始和結束。另一方面,實例分割算法為圖像中的每個對象計算像素級mask,即使對象具有相同的類別標籤(右下角)。在這裡,您可以看到每個立方體都有自己獨特的顏色,這意味著我們的實例分割算法不僅定位了每個獨立的立方體,而且還預測了它們的邊界。 而在本教程,我們將要討論的Mask R-CNN架構就是一個實例分割算法的示例。Mask R-CNN算法是何凱明等人在2017年發表的論文中提出的,Mask R-CNN(https://arxiv.org/abs/1703.06870)。 Mask R-CNN是基於之前的目標檢測工作R-CNN(2013)、Fast R-CNN(2015)、Faster R-CNN(2015),均由Girshick等人完成。我們輸入一個圖像和對應的實際的邊界框
提取圖像的特徵map
應用ROI池化,得到ROI特徵向量
最後, 使用兩組全連接層來獲得(1)類別標籤預測(2)每個proposal的邊框位置。
雖然網絡現在是可以端到端訓練的,但是由於依賴於選擇性搜索算法,在推斷時性能仍受到了極大的影響。為了使R-CNN的架構更快,我們需要直接利用R-CNN獲得區域proposal:圖4:Faster R-CNN架構(來源:Girshick et al., 2015) Girshick等人的Faster R-CNN論文將 區域proposals網絡(RPN)引入到神經網絡架構中,減少了對選擇性搜索算法的需求。總的來說,Faster R-CNN架構能夠以大約7-10幀每秒的速度運行,這是通過深度學習實現實時目標檢測的一大進步。 Mask R-CNN算法建立在Faster R-CNN架構的基礎之上,主要有兩個貢獻:用更精確的ROI align模塊替換ROI Pooling模塊
從ROI align模塊中插入一個額外的分支
這個額外的分支的輸入為ROI align模塊的輸出,然後將其輸入到兩個CONV層。我們可以將Mask R-CNN架構可視化如下圖所示:圖5:He等人的Mask R-CNN工作用一個更精確的ROI align模塊替換ROI Polling模塊。然後將ROI模塊的輸出送入兩個CONV層。CONV層的輸出即是掩摸(mask)本身。 注意兩個CONV層的分支來自ROI Align模塊——我們實際生成掩摸由該模塊生成。 我們知道,Faster R-CNN/Mask R-CNN架構利用區域proposal網絡(RPN)生成可能包含對象的圖像區域。這些區域都是根據它們的「可能是目標的評分」(即,給定區域可能包含目標的可能性),然後保留最可能的前N個目標區域。 在原來Faster R-CNN論文中,Girshick等人設置N= 2000,但在實踐中,我們可以用一個小得多的N,比如N={10,100, 200,300},仍然可以得到很好的結果。He等人在他們的論文(https://arxiv.org/abs/1703.06870)中設置N=300,這也是我們這裡使用的值。 所選的300個ROIs中的每一個都要經過網絡的三個並行分支:類別標籤預測
邊界框預測
掩摸預測
在預測時,300個ROIs都會經過非極大值抑制算法(https://www.pyimagesearch.com/2014/11/17/non-maximum-suppression-object-detection-python/),然後僅保存可能性前100的檢測框,使得最終得到一個四維的100 x L x 15 x 15張量,L為數據幾種類別標籤的數量,15 x 15是每個類別L的掩摸(mask)的大小。 我們今天使用的掩模R-CNN是在COCO數據集上訓練的(http://cocodataset.org/#home),它有L=90個類,因此掩模R CNN掩模模塊的最終體積大小是100 x 90 x 15 x 15。 圖6:Mask R-CNN過程的可視化,先生成一個15 x 15的掩摸,遮罩改變到圖像的原始尺寸,最後將掩摸覆蓋到原始圖像上。(來源:Python深度學習計算機視覺,ImageNet Bundle) 這裡你可以看到,我們從我們的輸入圖像開始,並通過我們的Mask R-CNN網絡,最終獲得我們的掩摸預測。預測的掩模只有15 x 15的像素,因此我們將掩模的大小調整回原始輸入圖像的尺寸。 最後,調整大小後的掩模可以覆蓋在原始輸入圖像上。要了解更多關於Mask R-CNN工作原理的詳細討論,請參考:由何等人發表的Mask R-CNN論文(https://arxiv.org/abs/1703.06870)
我的書, Deep Learning for Computer Vision with Python(https://www.pyimagesearch.com/deep-learning-computer-vision-python-book/),在這本書裡,我將更詳細地討論Mask R-CNNs,包括如何根據自己的數據從零開始訓練自己的Mask R-CNNs。
我們今天的項目主要由兩個腳本組成,還有其他幾個重要的文件。 我已經按照如下方式構建了這個項目(直接在終端上的tree命令輸出): 基於OpenCV的Mask R-CNN----Shell$ tree.├── mask-rcnn-coco│ ├── colors.txt│ ├── frozen_inference_graph.pb│ ├── mask_rcnn_inception_v2_coco_2018_01_28.pbtxt│ └── object_detection_classes_coco.txt├── images│ ├── example_01.jpg│ ├── example_02.jpg│ └── example_03.jpg├── videos│ ├──├── output│ ├──├── mask_rcnn.py└── mask_rcnn_video.py 4 directories, 9 filesmask-rcnn-coco/ : Mask R-CNN的模型文件。有四個文件:
frozen_inference_graph.pb : Mask R-CNN模型的權重文件,是基於COCO數據集上預訓練的權重。
mask_rcnn_inception_v2_coco_2018_01_28.pbtxt : Mask R-CNN模型的配置文件。如果你想在你自己的標註的數據上建立並訓練你自己的模型, 參考 Deep Learning for Computer Vision with Python(https://www.pyimagesearch.com/deep-learning-computer-vision-python-book/).
object_detection_classes_coco.txt : 所有90個類別都列在這個文本文件中,每行一個。在文本編輯器中打開它,查看模型可以識別哪些對象。
colors.txt : 這個文本文件包含六種顏色,可以隨機分配給圖像中檢測到的目標。
images/ : 我在「Downloads」中提供了三個測試圖像。請隨意添加您自己的圖像進行測試
videos/ : 這是一個空目錄。實際上,我用從YouTube上搜集的大型視頻進行了測試(Credits下面,就在「Summary」部分的上面)。我更傾向於建議您可以在YouTube上找到一些視頻下載並測試,而不是提供一個真正大的zip文件。或者用你的手機拍一些視頻,然後回到你的電腦前使用它們!
output/ :另一個空目錄,將保存處理過的視頻(假設您將命令行參數設置為輸出到此目錄)。
現在,我們已經回顧了Mask R-CNNs的工作原理,讓我們動手寫一些Python代碼。 在開始之前,請確保您的Python環境已經安裝了OpenCV 3.4.2/3.4.3或更高版本。您可以按照我的OpenCV安裝教程(https://www.pyimagesearch.com/opencv-tutorials-resources-guides/)來升級/安裝OpenCV。如果您想在5分鐘或更短的時間內啟動和運行,可以考慮使用pip安裝OpenCV(https://www.pyimagesearch.com/2018/09/19/pip-install-opencv/)。如果您有其他一些需求,您可能希望從原始碼編譯OpenCV。 請確保您已經從本博客文章的「Downloads」部分下載了原始碼、訓練過的Mask R-CNN以及示例圖像。然後,打開mask_rcnn.py文件並插入以下代碼: Mask R-CNN with OpenCV---Python# import the necessary packagesimport numpy as npimport argparseimport randomimport timeimport cv2import os首先,我們將在第2-7行導入所需的包。值得注意的是,我們正在導入NumPy和OpenCV包。大多數Python安裝都默認安裝了上所需的其他的包。 現在我們開始解析我們的命令行參數(https://www.pyimagesearch.com/2018/03/12/python-argparse-command-line-arguments/):Mask R-CNN with OpenCV# construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--image", required=True,help="path to input image")ap.add_argument("-m", "--mask-rcnn", required=True,help="base path to mask-rcnn directory")ap.add_argument("-v", "--visualize", type=int, default=0,help="whether or not we are going to visualize each instance")ap.add_argument("-c", "--confidence", type=float, default=0.5,help="minimum probability to filter weak detections")ap.add_argument("-t", "--threshold", type=float, default=0.3,help="minimum threshold for pixel-wise mask segmentation")args = vars(ap.parse_args())我們的腳本在終端中運行需要傳遞命令行參數標誌以及參數。我們的參數在第10-21行進行解析,其中前兩行是必需的,其餘的是可選的:--image : 輸入圖像的路徑。
--mask-rnn : Mask R-CNN文件的根路徑 .
--visualize (可選): 正值表示想要可視化如何在屏幕上提取屏蔽區域。無論哪種方式,我們都將在屏幕上顯示最終的輸出。
--confidence (optional): 您可以選擇0-0.5的概率值,該值用於過濾概率較低的檢測區域。
--threshold (可選): 我們將為圖像中的每個對象創建一個二進位掩碼,這個閾值將幫助我們過濾掉概率較低的掩碼。我發現默認值0.3時效果較好。
現在我們的命令行參數存儲在args字典中,讓我們加載標籤和顏色:Mask R-CNN with OpenCV---Python# load the COCO class labels our Mask R-CNN was trained onlabelsPath = os.path.sep.join([args["mask_rcnn"],"object_detection_classes_coco.txt"])LABELS = open(labelsPath).read().strip().split("")
# load the set of colors that will be used when visualizing a given# instance segmentationcolorsPath = os.path.sep.join([args["mask_rcnn"], "colors.txt"])COLORS = open(colorsPath).read().strip().split("")COLORS = [np.array(c.split(",")).astype("int") for c in COLORS]COLORS = np.array(COLORS, dtype="uint8")第24-26行加載COCO對象類別標籤。現在的Mask R-CNN能夠識別90個類,包括人,車輛,標誌,動物,日常用品,體育用品,廚房用品,食物等等!我建議您查看object_detection_classes_cocoa .txt,以查看可用的類別。 這裡我們從路徑加載顏色文件,並執行一些數組轉換操作(第30-33行)。Mask R-CNN with OpenCV---Python# derive the paths to the Mask R-CNN weights and model configurationweightsPath = os.path.sep.join([args["mask_rcnn"],"frozen_inference_graph.pb"])configPath = os.path.sep.join([args["mask_rcnn"],"mask_rcnn_inception_v2_coco_2018_01_28.pbtxt"])# load our Mask R-CNN trained on the COCO dataset (90 classes)# from diskprint("[INFO] loading Mask R-CNN from disk...")net = cv2.dnn.readNetFromTensorflow(weightsPath, configPath)首先,我們構建權重和配置路徑(第36-39行),然後通過這些路徑加載模型(第44行)。 在下一個代碼塊中,我們將加載Mask R-CNN神經網絡,輸入一張圖像:Mask R-CNN with OpenCV---Python# load our input image and grab its spatial dimensionsimage = cv2.imread(args["image"])(H, W) = image.shape[:2]
# construct a blob from the input image and then perform a forward# pass of the Mask R-CNN, giving us (1) the bounding box coordinates# of the objects in the image along with (2) the pixel-wise segmentation# for each specific objectblob = cv2.dnn.blobFromImage(image, swapRB=True, crop=False)net.setInput(blob)start = time.time()(boxes, masks) = net.forward(["detection_out_final", "detection_masks"])end = time.time()
# show timing information and volume information on Mask R-CNNprint("[INFO] Mask R-CNN took {:.6f} seconds".format(end - start))print("[INFO] boxes shape: {}".format(boxes.shape))print("[INFO] masks shape: {}".Load the input image and extract dimensions for scaling purposes later (Lines 47 and 48).
Construct a blob via cv2.dnn.blobFromImage (Line 54). You can learn why and how to use this function in my previous tutorial(https://www.pyimagesearch.com/2017/11/06/deep-learning-opencvs-blobfromimage-works/).
Perform a forward pass of the blob through the net while collecting timestamps (Lines 55-58). The results are contained in two important variables: boxes and masks .
現在我們已經在圖像上執行了口罩R-CNN的正向傳遞,我們想要過濾+可視化我們的結果。這正是下一個for循環要完成的。它很長,所以我把它分成五個代碼塊,從這裡開始:# loop over the number of detected objectsfor i in range(0, boxes.shape[2]):# extract the class ID of the detection along with the confidence# (i.e., probability) associated with the predictionclassID = int(boxes[0, 0, i, 1])confidence = boxes[0, 0, i, 2]
# filter out weak predictions by ensuring the detected probability# is greater than the minimum probabilityif confidence > args["confidence"]:# clone our original image so we can draw on itclone = image.copy()
# scale the bounding box coordinates back relative to the# size of the image and then compute the width and the height# of the bounding boxbox = boxes[0, 0, i, 3:7] * np.array([W, H, W, H])(startX, startY, endX, endY) = box.astype("int")boxW = endX - startXboxH = endY - startY在這個代碼塊中,我們開啟了一個訓練,不斷根據置信度過濾/並進行可視化(第66行)。 我們繼續提取特定檢測對象的分類和置信度(第69行和第70行)。在此基礎之上,我們通過將置信度與命令行參數置信度值進行比較,從而過濾掉置信度較低的預測結果,確保超過該值(第74行)。然後我們縮放對象的邊界框,並計算框的大小(第81-84行)。圖像分割要求我們找到目標所在的所有像素。因此,我們將在對象的頂部放置一個透明的層,以查看我們的算法執行的效果。為了做到這一點,我們將計算一個掩模:Mask R-CNN with OpenCV---Python# extract the pixel-wise segmentation for the object, resize# the mask such that it s the same dimensions of the bounding# box, and then finally threshold to create a *binary* maskmask = masks[i, classID]mask = cv2.resize(mask, (boxW, boxH),interpolation=cv2.INTER_NEAREST)mask = (mask > args["threshold"])
# extract the ROI of the imageroi = clone[startY:endY, startX:endX]在第89-91行,我們提取了對象的像素級分割,並將其調整為原始圖像的尺寸。最後,我們設置掩碼的閾值,使其成為二進位數組/圖像(第92行)。在本文後面的圖8中可以看到遮罩和roi的可視化結果。為了方便起見,下一個代碼塊實現了掩碼、roi和分割實例的可視化,如果通過命令行設置了參數 --visualize的話。Mask R-CNN with OpenCV---Python# check to see if are going to visualize how to extract the# masked region itselfif args["visualize"] > 0:# convert the mask from a boolean to an integer mask with# to values: 0 or 255, then apply the maskvisMask = (mask * 255).astype("uint8")instance = cv2.bitwise_and(roi, roi, mask=visMask)
# show the extracted ROI, the mask, along with the# segmented instancecv2.imshow("ROI", roi)cv2.imshow("Mask", visMask)cv2.imshow("Segmented", instance)檢查是否應該可視化ROI、掩模和分割實例(第99行)。
將掩模從布爾值轉換為整數,其中值「0」表示背景,「255」表示前景(第102行)。
執行按位掩模以僅僅可視化分割實例本身(第103行)。
顯示三個結果圖像(第107-109行)。
同樣,只有通過可選的命令行設置參數 --visualize 標誌時,才會顯示這些可視化圖像(默認情況下不會顯示這些圖像)。 Mask R-CNN with OpenCV---Python# now, extract *only* the masked region of the ROI by passing# in the boolean mask array as our slice conditionroi = roi[mask]
# randomly select a color that will be used to visualize this# particular instance segmentation then create a transparent# overlay by blending the randomly selected color with the ROIcolor = random.choice(COLORS)blended = ((0.4 * color) + (0.6 * roi)).astype("uint8")
# store the blended ROI in the original imageclone[startY:endY, startX:endX][mask] = blended第113行通過將布爾掩模數組作為切片條件傳遞,只提取ROI的掩模區域。 然後我們將隨機選擇六種顏色中的一種,將透明的覆蓋層應用到對象上(第118行)。 隨後,我們將用roi混合掩模區域(第119行),然後將該混合區域放入圖像clone中(第122行)。 最後,我們將在圖像上繪製矩形和文本類別標籤+ 置信度的值,並顯示結果! Mask R-CNN with OpenCV---Python# draw the bounding box of the instance on the imagecolor = [int(c) for c in color]cv2.rectangle(clone, (startX, startY), (endX, endY), color, 2)
# draw the predicted label and associated probability of the# instance segmentation on the imagetext = "{}: {:.4f}".format(LABELS[classID], confidence)cv2.putText(clone, text, (startX, startY - 5),cv2.FONT_HERSHEY_SIMPLEX, 0.5, color, 2)
# show the output imagecv2.imshow("Output", clone)cv2.waitKey(0)在對象周圍繪製一個彩色邊框(第125行和第126行)。 構建我們的類別標籤+置信度文本,並在邊界框上面繪製文本(第130-132行)。 顯示圖像,直到按下任意鍵(第135行和第136行)。 確保您已經從本教程的「Downloads」部分下載了原始碼、訓練過的Mask R-CNN和示例圖像。然後,打開您的終端並執行以下操作:Mask R-CNN with OpenCV---Shell$ python mask_rcnn.py --mask-rcnn mask-rcnn-coco --image images/example_01.jpg[INFO] loading Mask R-CNN from disk...[INFO] Mask R-CNN took 0.761193 seconds[INFO] boxes shape: (1, 1, 3, 7)[INFO] masks shape: (100, 90, 15, 15)圖7:一個用於汽車場景的口罩R-CNN。Python和OpenCV用於生成掩碼。 在上面的圖片中,你可以看到我們的Mask R-CNN不僅定位了圖片中的每一輛車,還構建了一個像素級掩模,允許我們從圖片中分割每一輛車。 如果我們運行相同的命令,這次提供--visualize參數標誌,我們還可以可視化ROI、掩模和實例:圖8:使用--visuatize標誌參數,我們可以查看用Python和OpenCV構建的mask R-CNN流程的ROI、掩模、分割的中間步驟。 Mask R-CNN with OpenCV---Shell$ python mask_rcnn.py --mask-rcnn mask-rcnn-coco --image images/example_02.jpg --confidence 0.6[INFO] loading Mask R-CNN from disk...[INFO] Mask R-CNN took 0.676008 seconds[INFO] boxes shape: (1, 1, 8, 7)[INFO] masks shape: (100, 90, 15, 15)圖9:使用Python和OpenCV,我們可以使用Mask R-CNN執行實例分割。 我們的Mask R-CNN從圖像中正確地檢測並分割了人、狗、馬和卡車。在我們開始在視頻中使用Mask R-CNNs之前,還有最後一個例子:Mask R-CNN with OpenCV---Shell$ python mask_rcnn.py --mask-rcnn mask-rcnn-coco --image images/example_03.jpg[INFO] loading Mask R-CNN from disk...[INFO] Mask R-CNN took 0.680739 seconds[INFO] boxes shape: (1, 1, 3, 7)[INFO] masks shape: (100, 90, 15, 15)圖10:在這裡,您可以看到我正在餵比格爾家的小獵犬傑瑪。每個被標識對象的像素級映射都被屏蔽,並透明地覆蓋在對象上。這幅圖像是使用OpenCV和Python使用一個預訓練的Mask R-CNN模型生成的。 在這張圖片中,你可以看到我和傑瑪的照片,這是我家的小獵犬。 我們的面具R-CNN能夠以比較高的置信度檢測和定位我,傑瑪和椅子。 我們已經學會了怎麼將Mask RCNN應用於圖像上,現在我們進一步學習如何在視頻上應用Mask RCNN.打開文件 mask_rcnn_video.py,插入下列代碼:# import the necessary packagesimport numpy as npimport argparseimport imutilsimport timeimport cv2import os # construct the argument parse and parse the argumentsap = argparse.ArgumentParser()ap.add_argument("-i", "--input", required=True,help="path to input video file")ap.add_argument("-o", "--output", required=True,help="path to output video file")ap.add_argument("-m", "--mask-rcnn", required=True,help="base path to mask-rcnn directory")ap.add_argument("-c", "--confidence", type=float, default=0.5,help="minimum probability to filter weak detections")ap.add_argument("-t", "--threshold", type=float, default=0.3,help="minimum threshold for pixel-wise mask segmentation")args = vars(ap.parse_args())首先,我們插導入必要的包,設置聲明的參數,緊接著的兩行代碼是放置需要檢測的圖像。# load the COCO class labels our Mask R-CNN was trained onlabelsPath = os.path.sep.join([args["mask_rcnn"],"object_detection_classes_coco.txt"])LABELS = open(labelsPath).read().strip().split("") # initialize a list of colors to represent each possible class labelnp.random.seed(42)COLORS = np.random.randint(0, 255, size=(len(LABELS), 3),dtype="uint8") # derive the paths to the Mask R-CNN weights and model configurationweightsPath = os.path.sep.join([args["mask_rcnn"],"frozen_inference_graph.pb"])configPath = os.path.sep.join([args["mask_rcnn"],"mask_rcnn_inception_v2_coco_2018_01_28.pbtxt"]) # load our Mask R-CNN trained on the COCO dataset (90 classes)# from diskprint("[INFO] loading Mask R-CNN from disk...")net = cv2.dnn.readNetFromTensorflow(weightsPath, configPath)在加載MaskRCNN網絡之前,需要先加載權重模型和配置文件(第34-42行)。# initialize the video stream and pointer to output video filevs = cv2.VideoCapture(args["input"])writer = None # try to determine the total number of frames in the video filetry:prop = cv2.cv.CV_CAP_PROP_FRAME_COUNT if imutils.is_cv2() else cv2.CAP_PROP_FRAME_COUNTtotal = int(vs.get(prop))print("[INFO] {} total frames in video".format(total)) # an error occurred while trying to determine the total# number of frames in the video fileexcept:print("[INFO] could not determine # of frames in video")total = -1我們嘗試確定視頻文件的幀數,並將總的幀數顯示出來。如果不成功的話,程序就會終止,但列印狀態信息,或者我們將這個幀數設置成-1,忽略這一個步驟,不做任何處理。# loop over frames from the video file streamwhile True:# read the next frame from the file(grabbed, frame) = vs.read() # if the frame was not grabbed, then we have reached the end# of the streamif not grabbed:break # construct a blob from the input frame and then perform a# forward pass of the Mask R-CNN, giving us (1) the bounding box# coordinates of the objects in the image along with (2) the# pixel-wise segmentation for each specific objectblob = cv2.dnn.blobFromImage(frame, swapRB=True, crop=False)net.setInput(blob)start = time.time()(boxes, masks) = net.forward(["detection_out_final","detection_masks"])end = time.time()我們開始通過定義無限循環來循環所有的幀,並且捕獲第一幀(第 62-64行)。循環地處理視頻,直到滿足退出條件(第68和69行)。然後,我們從幀中構造一個 blob,並在計算通過神經網絡的時間,以便我們可以計算完成所需時間(第 75-80 行)。檢測的結果同時包含了檢測框和蒙版。# loop over the number of detected objectsfor i in range(0, boxes.shape[2]):# extract the class ID of the detection along with the# confidence (i.e., probability) associated with the# predictionclassID = int(boxes[0, 0, i, 1])confidence = boxes[0, 0, i, 2] # filter out weak predictions by ensuring the detected# probability is greater than the minimum probabilityif confidence > args["confidence"]:# scale the bounding box coordinates back relative to the# size of the frame and then compute the width and the# height of the bounding box(H, W) = frame.shape[:2]box = boxes[0, 0, i, 3:7] * np.array([W, H, W, H])(startX, startY, endX, endY) = box.astype("int")boxW = endX - startXboxH = endY - startY # extract the pixel-wise segmentation for the object,# resize the mask such that it s the same dimensions of# the bounding box, and then finally threshold to create# a *binary* maskmask = masks[i, classID]mask = cv2.resize(mask, (boxW, boxH),interpolation=cv2.INTER_NEAREST)mask = (mask > args["threshold"]) # extract the ROI of the image but *only* extracted the# masked region of the ROIroi = frame[startY:endY, sta首先我們過濾掉低置信度的檢測結果,然後確定檢測框的坐標和蒙版。# grab the color used to visualize this particular class,# then create a transparent overlay by blending the color# with the ROIcolor = COLORS[classID]blended = ((0.4 * color) + (0.6 * roi)).astype("uint8") # store the blended ROI in the original frameframe[startY:endY, startX:endX][mask] = blended # draw the bounding box of the instance on the framecolor = [int(c) for c in color]cv2.rectangle(frame, (startX, startY), (endX, endY),color, 2) # draw the predicted label and associated probability of# the instance segmentation on the frametext = "{}: {:.4f}".format(LABELS[classID], confidence)cv2.putText(frame, text, (startX, startY - 5),cv2.FONT_HERSHEY_SIMPLEX, 0.5, col這裡,我們將興趣區域用顏色表示出來,儲存在原始的框架中。# check if the video writer is Noneif writer is None:# initialize our video writerfourcc = cv2.VideoWriter_fourcc(*"MJPG")writer = cv2.VideoWriter(args["output"], fourcc, 30,(frame.shape[1], frame.shape[0]), True) # some information on processing single frameif total > 0:elap = (end - start)print("[INFO] single frame took {:.4f} seconds".format(elap))print("[INFO] estimated total time to finish: {:.4f}".format(elap * total)) # write the output frame to diskwriter.write(frame) # release the file pointersprint("[INFO] cleaning up...")writer.release()vs.release()你會注意到,我沒有在屏幕上顯示每個幀。顯示操作非常耗時,當腳本完成處理時,你仍可以使用任何媒體播放器查看輸出視頻。注意: 此外,OpenCV 不支持 NVIDIA GPU 的 dnn 模塊。目前僅支持數量有限的 GPU,主要是英特爾 GPU。NVIDIA GPU 支持即將推出,但目前我們無法輕鬆地使用具有 OpenCV dnn 的 GPU.現在,我們已經編碼了我們的Mask R-CNN和OpenCV腳本的視頻流,你可以自己嘗試下!然後,你需要使用智慧型手機或其他錄製設備收集你自己的視頻。或者,你也可以像我一樣從 YouTube 下載視頻。$ python mask_rcnn_video.py --input videos/cats_and_dogs.mp4 --output output/cats_and_dogs_output.avi --mask-rcnn mask-rcnn-coco[INFO] loading Mask R-CNN from disk...[INFO] 19312 total frames in video[INFO] single frame took 0.8585 seconds[INFO] estimated total time to finish: 16579.2047圖11:在上面的視頻中,你可以找到包含狗和貓的有趣視頻剪輯,並Mask R-CNN應用在上面!(觀看這個視頻:https://youtu.be/T_GXkW0BUyA)下面是第二個例子,這裡應用OpenCV和Mask R-CNN檢測寒冷天氣下滑動的汽車。$ python mask_rcnn_video.py --input videos/slip_and_slide.mp4 --output output/slip_and_slide_output.avi --mask-rcnn mask-rcnn-coco[INFO] loading Mask R-CNN from disk...[INFO] 17421 total frames in video[INFO] single frame took 0.9341 seconds[INFO] estimated total time to finish: 16272.9920圖12 利用Python和Opencv將Mask RCNN應用於視頻中的車輛檢測你可以想像一下,將Mask RCNN應用於擁擠道路上,檢查道路擁擠、車禍和需要幫助的車輛。(觀看視頻:https://www.youtube.com/watch?v=8nbzVARfosE)貓狗:
「Try Not To Laugh Challenge – Funny Cat & Dog Vines compilation 2017」on YouTube(https://www.youtube.com/watch?v=EtH9Yllzjcc)
「Happy rock」 on BenSound(https://www.bensound.com/royalty-free-music/track/happy-rock)
Slip and Slide:
「Compilation of Ridiculous Car Crash and Slip & Slide Winter Weather – Part 1」 on YouTube(https://www.youtube.com/watch?v=i59v0p-gAtk)
「Epic」 on BenSound(https://www.bensound.com/royalty-free-music/track/epic)
圖13:在我的書 Deep Learning for Computer Vision with Python中
Mask RCNN模型的預訓練權重模型是在COCO數據集上訓練得到的。但是,如果你想在自定義數據集上訓練 Mask R-CNN呢?在我的書Deep Learning for Computer Vision with Python中有詳細介紹。所有 Mask R-CNN 章節都包含算法和代碼的詳細說明,確保您能夠成功訓練自己的 Mask R-CNN。要了解有關我的書的更多信息(並獲取免費的示例章節和目錄集),請查看:https://www.pyimagesearch.com/deep-learning-computer-vision-python-book/ 我教你如何訓練一個Mask R-CNN自動檢測和分割癌性皮膚病變影像-第一步,建立一個自動癌症危險因素分類系統。
為您提供我最喜歡的圖像標註工具,使您能夠為輸入圖像創建蒙版。
向您展示如何在自定義數據集上訓練 Mask R-CNN。
在訓練自己的 Mask R-CNN 時,為您提供我的最佳實踐、提示和建議。
總結在這個教程中,你學到了在OpenCV和Python下用Mask R-CNN進行圖像和視頻流中的目標分割。
像YOLO,SSD和Faster R-CNN這樣的目標檢測方法僅能夠生成圖像中目標的邊界框 — 我們並不能從它們的方法得知目標的實際形狀。而用 Mask R-CNN 我們能得到有相對形狀的顏色塊,從而幫助我們把物體從背景中分離。
進一步說,Mask R-CNN可以幫助我們從傳統計算機視覺算法無法實現的圖像中分割出複雜的物體和形狀。 希望今天的教程能幫到你更好地了解OpenCV 和 Mask R-CNN!via https://www.pyimagesearch.com/2018/11/19/mask-r-cnn-with-opencv/