語義分割:基於openCV和深度學習(二)

語義分割:基於openCV和深度學習(二)

Semantic segmentation in images with OpenCV

開始吧-打開segment.py歸檔並插入以下代碼:

Semantic segmentation with
OpenCV and deep learning

import the necessary packages

import numpy as np

import argparse

import
imutils

import time

import cv2

從輸入必要的依賴包開始。對於這個腳本,推薦OpenCV 3.4.1或更高版本。可以按照一個安裝教程進行操作—只要確保在執行步驟時指定要下載和安裝的OpenCV版本。還需要安裝OpenCV便利功能包imutils-只需使用pip安裝該包:

Semantic segmentation with
OpenCV and deep learning

$ pip install --upgrade imutils

如果使用的是Python虛擬環境,不要忘記在使用pip安裝imutils之前使用work-on命令! 接下來,分析一下命令行參數:

Semantic segmentation with
OpenCV and deep learning

#construct the argument parse and parse the arguments

ap = argparse.ArgumentParser()

ap.add_argument("-m", “–model”, required=True,

help=“path
to deep learning segmentation model”)

ap.add_argument("-c", “–classes”, required=True,

help=“path
to .txt file containing class labels”)

ap.add_argument("-i", “–image”, required=True,

help=“path
to input image”)

ap.add_argument("-l", “–colors”, type=str,

help=“path
to .txt file containing colors for labels”)

ap.add_argument("-w", “–width”, type=int, default=500,

help=“desired
width (in pixels) of input image”)

args = vars(ap.parse_args())

此腳本有五個命令行參數,其中兩個是可選的:

–模型:深入學習語義分割模型的途徑。

–類:包含類標籤的文本文件的路徑。

–圖像:的輸入圖像文件路徑。 -

-顏色:顏色文本文件的可選路徑。如果沒有指定文件,則將爲每個類分配隨機顏色。

–寬度:可選的所需圖像寬度。默認情況下,該值爲500像素。

如果不熟悉argparse和命令行參數的概念,一定要閱讀這篇深入介紹命令行參數的博客文章。 接下來,來分析類標籤文件和顏色:

Semantic segmentation with
OpenCV and deep learning

#load the class label names

CLASSES = open(args[“classes”]).read().strip().split("\n")

if a colors file was supplied, load it from disk

if args[“colors”]:

COLORS = open(args[“colors”]).read().strip().split("\n")

COLORS
= [np.array(c.split(",")).astype(“int”) for c in COLORS]

COLORS = np.array(COLORS, dtype=“uint8”)

otherwise, we need to randomly generate RGB colors for

each class

#label

else:

#initialize a list of colors to represent each class label in

the mask (starting with ‘black’ for the

background/unlabeled

#regions)

np.random.seed(42)

COLORS
= np.random.randint(0, 255, size=(len(CLASSES) - 1, 3),

dtype=“uint8”)

COLORS
= np.vstack([[0, 0, 0], COLORS]).astype(“uint8”)

從提供的文本文件中將類加載到內存中,該文件的路徑包含在命令行args字典(第23行)中。

如果文本文件中爲每個類標籤提供了一組預先指定的顏色(每行一個),將它們加載到內存中(第26-29行)。否則,爲每個標籤隨機生成顏色(第33-40行)。

出於測試目的(並且由於有20個類),使用OpenCV繪圖函數創建一個漂亮的顏色查找圖例:

Semantic segmentation with
OpenCV and deep learning

#initialize the legend visualization

legend = np.zeros(((len(CLASSES) * 25) + 25, 300, 3), dtype=“uint8”)

loop over the class names + colors

for (i, (className, color)) in enumerate(zip(CLASSES,
COLORS)):

draw the class name + color on the legend

color =
[int© for c in color]

cv2.putText(legend, className, (5, (i * 25) + 17),

cv2.FONT_HERSHEY_SIMPLEX,
0.5, (0, 0, 255), 2)

cv2.rectangle(legend, (100, (i * 25)), (300, (i * 25) + 25),

tuple(color), -1)

生成一個圖例可視化,就可以很容易地可視化地將類標籤與顏色關聯起來。圖例由類標籤及其旁邊的彩色矩形組成。這是通過創建畫布(第43行)和使用循環動態構建圖例(第46-52行)快速創建的。本文中介紹了繪畫基礎知識。

結果如下:
在這裏插入圖片描述

Figure 2: Our deep learning semantic segmentation class color legend generated with OpenCV.

下一個區塊將進行深度學習細分:

Semantic segmentation with OpenCV and deep learning

#load our serialized model from disk

print("[INFO] loading model…")

net =
cv2.dnn.readNet(args[“model”])

#load the input image, resize it, and construct a blob from it,

but keeping mind mind that the original input image

dimensions

#ENet was trained on was 1024x512

image = cv2.imread(args[“image”])

image =
imutils.resize(image, width=args[“width”])

blob = cv2.dnn.blobFromImage(image, 1 / 255.0, (1024, 512), 0,

swapRB=True,
crop=False)

#perform a forward pass using the segmentation model

net.setInput(blob)

start =
time.time()

output = net.forward()

end =
time.time()

#show the amount of time inference took

print("[INFO] inference took {:.4f} seconds".format(end - start))

爲了使用Python和OpenCV對圖像進行深入的語義分割:

加載模型(第56行)。構造一個blob(第61-64行),在這篇博客文章中使用的ENet模型是在1024×512分辨率的輸入圖像上訓練的,將在這裏使用相同的方法。可以在這裏瞭解更多關於OpenCV的blob是如何工作的。將blob設置爲網絡的輸入(第67行),並執行神經網絡的前向傳遞(第69行)。用時間戳將forward pass語句括起來。將經過的時間打印到第73行的終端。

在腳本的其餘行中,將生成一個顏色映射,覆蓋在原始圖像上。每個像素都有一個對應的類標籤索引,能夠在屏幕上看到語義分割的結果。

首先,需要從輸出中提取卷維度信息,然後計算類圖和顏色掩碼:

Semantic segmentation with
OpenCV and deep learning

#infer the total number of classes along with the spatial dimensions

of the mask image via the shape of the output array

(numClasses,
height, width) = output.shape[1:4]

our

output class ID map will be num_classes x height x width in

size, so we take the argmax to find the class label

with the

#largest probability for each and every (x, y)-coordinate in the

image

classMap
= np.argmax(output[0], axis=0)

#given the class ID map, we can map each of the class IDs to its

corresponding color

mask = COLORS[classMap]

在第77行確定輸出體積的空間維度。接下來,讓找到輸出卷的每個(x,y)-座標的概率最大的類標籤索引(第83行)。這就是現在所知道的類映射,它包含每個像素的類索引。 給定類ID索引,可以使用NumPy數組索引“神奇地”(更不用說超級高效地)查找每個像素(第87行)對應的可視化顏色。彩色mask版將透明地覆蓋在原始圖像上。 讓完成腳本:

Semantic segmentation with OpenCV and deep learning

resize the mask and class map such that its dimensions match the

original size of the input image (we’re not using the

class map

#here for anything else but this is how you would resize it just in

case you wanted to extract specific pixels/classes)

mask =cv2.resize(mask, (image.shape[1],
image.shape[0]),

interpolation=cv2.INTER_NEAREST)

classMap
= cv2.resize(classMap, (image.shape[1],
image.shape[0]),

interpolation=cv2.INTER_NEAREST)

perform a weighted combination of the input image with

the mask to

#form an output visualization

output = ((0.4 * image) + (0.6 * mask)).astype(“uint8”)

show the input and output images

cv2.imshow(“Legend”, legend)

cv2.imshow(“Input”, image)

cv2.imshow(“Output”, output)

cv2.waitKey(0)

調整掩碼和類映射的大小,使它們與輸入圖像(第93-96行)具有完全相同的維度。爲了保持原始的類id/mask值,使用最近鄰插值而不是三次、二次等插值是非常重要的。 現在大小是正確的,創建了一個“透明的顏色覆蓋”,通過覆蓋的原始圖像(第100行)的遮罩。這使能夠輕鬆地可視化分割的輸出。關於透明覆蓋層以及如何構建它們的更多信息,可以在本文中找到。最後,圖例和原始+輸出圖像顯示在第103-105行的屏幕上。

單圖像分割結果

在使用本節中的命令之前,請確保獲取此博客文章的“下載”。爲了方便起見,在zip文件中提供了模型+相關文件、圖像和Python腳本。在終端中提供的命令行參數對於複製結果很重要。如果不熟悉命令行參數,請在此處瞭解它們。準備好後,打開一個終端並導航到項目,然後執行以下命令:

Semantic segmentation with
OpenCV and deep learning

$python segment.py --model enet-cityscapes/enet-model.net \

–classes enet-cityscapes/enet-classes.txt \

–colors
enet-cityscapes/enet-colors.txt \

–image images/example_01.png

[INFO]
loading model…

[INFO] inference took 0.2100
seconds

在這裏插入圖片描述

圖3:OpenCV的語義分割顯示了道路、人行道、人、自行車、交通標誌等等!

注意分割的精確程度-它清楚地分割類並準確地識別人和自行車(自動駕駛汽車的安全問題)。道路,人行道,汽車,甚至樹葉都被識別出來了。

嘗試另一個示例,只需將–image命令行參數更改爲不同的圖像:

Semantic segmentation with
OpenCV and deep learning

$
python segment.py --model enet-cityscapes/enet-model.net \

–classes enet-cityscapes/enet-classes.txt \

–colors
enet-cityscapes/enet-colors.txt \

–image images/example_02.jpg

[INFO]
loading model…

[INFO] inference took 0.1989
seconds

在這裏插入圖片描述

圖4中的結果展示了這個語義分割模型的準確性和清晰性。汽車、道路、樹木和天空都有清晰的標記。下面是另一個例子:

Semantic segmentation with
OpenCV and deep learning

$
python segment.py --model enet-cityscapes/enet-model.net \

–classes enet-cityscapes/enet-classes.txt \

–colors
enet-cityscapes/enet-colors.txt \

–image images/example_03.png

[INFO]
loading model…

[INFO] inference took 0.1992
seconds

在這裏插入圖片描述

上圖是一個更復雜的場景,但ENet仍然可以分割走在車前的人。不幸的是,該模型錯誤地將道路分類爲人行道,但可能是因爲人們在人行道上行走。最後一個例子:

Semantic segmentation with
OpenCV and deep learning

$
python segment.py --model enet-cityscapes/enet-model.net \

–classes enet-cityscapes/enet-classes.txt \

–colors
enet-cityscapes/enet-colors.txt \

–image images/example_04.png

[INFO]
loading model…

[INFO] inference took 0.1916
seconds

在這裏插入圖片描述

通過ENet發送的最終圖像顯示了模型如何在道路、人行道、樹葉、人物等其他場景類別中清晰地分割卡車與汽車。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章