發布日期:2022-07-05 點擊率:24
在計算機視覺領域,實例分割是當今最熱門的話題之一。
它包括圖像中對象的檢測/分割,即特定對象的定位及其所屬像素的關聯。像任何一種機器學習系統一樣,訓練主干結構需要大量圖像。更具體地說,需要大量注釋來訓練神經網絡的定位功能。
注釋是一項耗時的活動,可以決定項目是否會成功。因此,必須謹慎處理,以提高生產率。
在衛星圖像領域,可以利用免費數據集來利用研究人員或注釋人員以前所做的工作。這些數據集通常是由研究人員在從開源圖像構建數據集、進行前后處理并用于訓練和測試自己的人工智能研究系統后發布的。
語義分割和實例分割有點不同,但在建筑物的情況下,一個可以幫助另一個。
事實上,建筑物通常是獨特的,可以在任何圖像上進行分離。利用這種考慮,可以從二值標簽圖像中為每個建筑生成單獨的遮罩,然后用于更快地訓練實例分割算法,如Mask RCNN。注釋不必手動執行,這是該技術的主要優點。下面是一些如何做的提示!
JSON文件格式
Mask RCNN Matterport實現以及FAIR Detectron2平臺使用JSON文件為訓練圖像數據集加載注釋。這種文件格式用于許多計算機科學應用,因為它允許以成對屬性值的格式輕松存儲和共享字母數字信息。
它是為Javascript語言構建的,但如今,它被用于許多其他編程語言,如Python。專門的庫已經建立起來,能夠在Python代碼中以文本文件的形式生成和解析JSON格式的數據。VGG注釋工具格式中Mask RCNN使用的典型JSON文件將具有以下形狀:
{
"image1.png9259408": {
"filename": "image1.png",
"size": 9259408,
"regions": [
{
"shape_attributes": {
"name": "polygon",
"all_points_x": [
314,
55,
71,
303,
318,
538,
],
"all_points_y": [
1097,
1093,
1450,
1450,
1505,
1474,
]
},
"region_attributes": {
"class": "building"
}
},
{
"shape_attributes": {
"name": "rect",
"x": 515,
"y": 1808,
"width": 578,
"height": 185
},
"region_attributes": {
"class": "apple"
}
}
],
"file_attributes": {}
},
"0030fd0e6378.png236322": {
"filename": "0030fd0e6378.png",
"size": 236322,
"regions": [
{
"shape_attributes": {
"name": "polygon",
"all_points_x": [
122,
294,
258,
67,
32
],
"all_points_y": [
92,
113,
231,
221,
132
]
},
"region_attributes": {
"class": "apple"
}
},
{
"shape_attributes": {
"name": "circle",
"cx": 210,
"cy": 303,
"r": 47
},
"region_attributes": {
"class": "swan"
}
}
],
"file_attributes": {}
}
}
一個JSON注釋文件收集所有注釋數據。每個圖像注釋都堆積在一個大的JSON文件中。
一個圖像由其標識符標識。該標識符由四個屬性描述:圖像的名稱(文件名)、其在磁盤上的大小(大小)、注釋的形狀(區域)和圖像上的一些元數據(文件屬性)。
每個注釋都可以由兩個元素來描述:形狀描述(形狀屬性)和注釋數據(區域屬性)。形狀屬性描述由注釋的形狀(名稱)和兩個整數的有序列表(所有點x和所有點y)組成,它們表示構成遮罩注釋的點的x和y坐標。注釋數據region_attributes可以調整,注釋類可以保存以用于多類分割。
第四個標識符屬性名為file_attributes,可用于存儲注釋圖像上的任何信息。
在語法方面,讓我們注意到大括號{}通常用于分隔相同類型的元素,以及引用描述一個元素的屬性。方括號[]用于表示參數列表。
幸運的是,Python有一個庫供我們讀寫JSON文件。使用帶有通用語法的import json代碼片段可以輕松加載它,以讀取和寫入文本文件。
在下一章中,我們將討論如何將二進制標簽圖像轉換為VGG注釋,尤其是如何使用JSON語法編寫注釋文件。
生成注釋JSON文件
本文提出的主要思想是將二進制標簽圖像轉換為VGG注釋格式的掩碼JSON文件。對二值標簽圖像的每個形狀進行個性化處理,以將其轉化為遮罩元素,例如分割。
轉換主要使用著名的OpenCV圖形庫執行,該庫在Python中易于使用。
def Annot(preprocess_path, res=0.6, surf=100, eps=0.01):
"""
preprocess_path : path to folder with gt and images subfolder containing ground truth binary label image and visual imagery
res : spatial resolution of images in meter
surf : the minimum surface of roof considered in the study in square meter
eps : the index for Ramer–Douglas–Peucker (RDP) algorithm for contours approx to decrease nb of points describing a contours
"""
jsonf = {} # only one big annotation file
with open(os.path.join(preprocess_path,'via_region_data.json'), 'w') as js_file:
gt_path = os.path.join(preprocess_path, 'gt')
images_path = os.path.join(preprocess_path, 'images')
# All the elements in the images folders
lst = os.listdir(images_path)
for elt in tqdm(lst, desc='lst'):
# Read the binary mask, and find the contours associated
gray = cv2.imread(os.path.join(gt_path, elt))
imgray = cv2.cvtColor(gray, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(imgray, 127, 255, 0)
contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# https://www.pyimagesearch.com/2021/10/06/opencv-contour-approximation/
# Contours approximation based on Ramer–Douglas–Peucker (RDP) algorithm
areas = [cv2.contourArea(contours[idx])*res*res for idx in range(len(contours))]
large_contour = []
for i in range(len(areas)):
if areas[i]>surf:
large_contour.append(contours[i])
approx_contour = [cv2.approxPolyDP(c, eps * cv2.arcLength(c, True), True) for c in large_contour]
# -------------------------------------------------------------------------------
# BUILDING VGG ANNTOTATION TOOL ANNOTATIONS LIKE
if len(approx_contour) > 0:
regions = [0 for i in range(len(approx_contour))]
for i in range(len(approx_contour)):
shape_attributes = {}
region_attributes = {}
region_attributes['class'] = 'roof'
regionsi = {}
shape_attributes['name'] = 'polygon'
shape_attributes['all_points_x'] = approx_contour[i][:, 0][:, 0].tolist()
# https://stackoverflow.com/questions/26646362/numpy-array-is-not-json-serializable
shape_attributes['all_points_y'] = approx_contour[i][:, 0][:, 1].tolist()
regionsi['shape_attributes'] = shape_attributes
regionsi['region_attributes'] = region_attributes
regions[i] = regionsi
size = os.path.getsize(os.path.join(images_path, elt))
name = elt + str(size)
json_elt = {}
json_elt['filename'] = elt
json_elt['size'] = str(size)
json_elt['regions'] = regions
json_elt['file_attributes'] = {}
jsonf[name] = json_elt
json.dump(jsonf, js_file)
第一行是為真實標簽和圖像文件夾構建正確的文件夾路徑,并創建JSON文件注釋。
首先,使用cv2.findContours將二進制遮罩切割成輪廓。大多數轉換(閾值、灰度轉換)實際上并不需要,因為數據已經是二值圖像。cv2.findContours函數提供一個等高線列表,作為一個點列表,這些點的坐標在圖像的參考系中表示。
在大型建筑屋頂項目中,可以使用自定義OpenCV函數來導出屋頂表面,然后將其轉換為平方米,并僅選擇具有足夠面積的屋頂。在這種情況下,可以使用Ramer–Douglas–Peucker(RDP)算法來簡化和近似檢測到的輪廓,以便更緊湊地存儲注釋數據。此時,你應該有一個點列表,這些點代表在二值圖像上檢測到的輪廓。
現在,你需要將整個輪廓點列表轉換為一個大的用于掩碼RCNN算法的via_region_data.json文件。對于JSON注釋,數據需要具有第一段中指定的格式。字典主要在將數據推送到JSON文件之前使用。
根據輪廓[]的數量,需要特定數量的 [:,0]才能獲取正確的數據。描述輪廓的整數數組必須轉換為JSON可序列化數據。制作VGG注釋JSON文件與制作俄羅斯玩偶非常相似。你可以創建一個空字典,指定其一個(或多個)屬性的值,然后將其作為更高級別屬性的值傳遞,以將其封裝到更大的字典中。我們注意到,對于多類分割或對象檢測,region_attributes可以包含一個屬性類,該屬性類的掩碼在shape_attributes參數中指定。
最后,在將所有圖像數據放入JSON文件之前,每個圖像數據都存儲在一個大的“json”元素中,其名稱+大小字符串作為標識符。這一點非常重要,因為如果每次運行新圖像時都寫入JSON文件,JSON文件的掩碼RCNN導入將失敗。這是因為json.load只讀取第一組大括號{}的內容,無法解釋下一組大括號。
就這樣!讓我們看看這個過程的結果是什么!
檢查注釋顯示
這一小章將展示上述過程的圖形化使用。使用的主要是美國地質調查局通過國家地圖服務公開發布的美國城市圖像(芝加哥、奧斯汀、舊金山)。
美國地質調查局國家地理空間計劃提供的地圖服務和數據。該服務是開源的,所以你可以對數據做任何你想做的事情!
在這篇文章中,處理了德克薩斯州奧斯汀附近的高分辨率圖像(空間分辨率=0.3米/像素)。
第一個圖像是視覺彩色圖像,通常以GeoTiff格式提供,它也包含嵌入的地理空間數據。它以美國城市環境的城市場景為特色。渲染由三個光譜視覺圖像構建:通常的藍色、綠色和紅色。但在更復雜的圖像中,圖像供應商可以提供近紅外圖像,以便能夠生成CNIR(彩色+近紅外圖像),以分析光譜圖像的不同方面。
第二個圖像顯示二進制標簽圖像。可以看出,標簽包含了與建筑物相關的每一個像素,即使是最小的彎曲形狀的像素。每個建筑都可以單獨識別,因為建筑不能重疊,這就證明了整個過程的合理性。
第三幅圖像由二值標簽1和cv2檢測到的輪廓組成,以紅色突出顯示。顯示的等高線是來自OpenCV函數的原始數據,沒有被過濾掉,因此即使是最小的建筑也會被顯示出來。需要注意的是,cv2.findContours是一種像素級的轉換:由一個像素連接的兩座建筑將被分割在一起,而只有一行暗像素就足以將兩座相鄰的建筑分別分割。
第四幅圖像顯示具有過濾后的近似輪廓的二值標簽圖像。正如第二章所說,就屋頂項目而言,對面積小于100平方米的建筑不感興趣。它還將執行輪廓近似以減小注釋文件的大小。因此,僅在大型建筑周圍繪制輪廓,在某些情況下,輪廓與建筑形狀不完全匹配,無法啟發輪廓近似。
第五張也是最后一張圖像顯示了通常的實例分割可視化,可以使用inspect_roof_data等工具繪制。大型建筑的屋頂被單獨分割。
結論
本文展示的過程展示了如何將語義數據集轉換為實例分割訓練數據集。然后可以使用它來有效地訓練Mask-RCNN算法。該過程也可以重復使用和修改,以適應具有不同輸入標簽形狀的數據集。
原文標題 : 自動生成VGG圖像注釋文件