精、點擊上方“碼農的后花園”,選擇“星標” 公眾號
精選文章,第一時間送達
上期講解了語意分割模型的基本架構和常用資料集,這期就講解一下語意分割資料集的制作,追下去吧~
制作總體步驟:
1. 使用lableme對圖片資料進行標注,生成對應圖片的x.json檔案,
2. 執行lableme下的內置函式labelme_json_to_dataset,依次手動生成圖片對應的x_json檔案(或者使用代碼一次性處理生成),
3. 對第二步生成檔案夾中的檔案進行處理,生成語意圖片label.png,
4. 將語意圖片轉換為類別灰度圖圖片-最終訓練標簽檔案,
一、檔案目錄結構:
二、正式開始制作
第一步:標注軟體的安裝
1.Anaconda Prompt中創建一個環境
conda create --name=labelImg python=3.6
2.激活進入剛建立的新環境,
conda activate labelImg
3.安裝界面支持pyqt5包
pip install pyqt5 -i https://pypi.douban.com/simple/
4.下載安裝labelme
pip install labelme -i https://pypi.douban.com/simple/
5.輸入命令labelme,就可以啟動程式進行資料標注
第二步:進行標注
A.單類別標注 - 即每一張圖片上只有一個目標
【1】在命令列中輸入命令 labelme,打開標注界面,然后打開要標注的圖片所在的檔案夾進行標注
Opendir “”Test_Image“” ->Create polygons ->Save->Next Image
【2】所有圖片標注完之后,標注檔案以x.json形式檔案進行保存,制作完成后放在目錄的before檔案夾下,
用VS2017可查看Json檔案內容,包含資訊為我們標注區域內每一個像素點的資料
【3】利用labelme的自帶函式labelme_json_to_dataset手動依次將每個json檔案格式轉換為語意圖片的資料,
1.cd 到json檔案所在的地方:cmd D:Test_Image
2.查看當前labelme安裝所在的環境label并激活
3.利用labelme_json_to_dataset手動依次對每張圖片的標注檔案x.json格式依次進行處理, 生成得到x_json檔案即每張圖片的對應的語意圖片 - 區域類別標簽(這個程序需要手動對每一張圖片的x.json檔案進行處理,比較麻煩,可以寫代碼直接一次性轉換)
命令:labelme_json_to_data [ x.json ] -> labelme標注生成的json檔案名
得到每張圖片的x.json檔案對應的區域類別標簽保存在每個x_json檔案中,如下所示:
每張圖片區域類別標簽內容 x_json檔案中的內容:
注解:
img.png: 對應的區域的jpg原圖檔案,訓練時要用
label.png: 標注語意影像,訓練時要用
label_names.txt: 在這張影像上目標分類名稱
label_viz.png: 標簽可視化,用于讓我們確認是否標記正確
代碼一次性轉換:json_to_dataset.py
會生成和上述x_json檔案下一模一樣的檔案內容
import argparseimport jsonimport osimport os.path as ospimport warnings
import PIL.Imageimport yaml
from labelme import utilsimport base64
def main(): count = os.listdir("./before/") for i in range(0, len(count)): path = os.path.join("./before", count[i])
# 找到before檔案中以json為結尾的檔案并且打開if os.path.isfile(path) and path.endswith('json'): data = json.load(open(path))
if data['imageData']: imageData = data['imageData']else: imagePath = os.path.join(os.path.dirname(path), data['imagePath'])with open(imagePath, 'rb') as f: imageData = f.read() imageData = base64.b64encode(imageData).decode('utf-8') img = utils.img_b64_to_arr(imageData) label_name_to_value = {'_background_': 0}for shape in data['shapes']: label_name = shape['label']if label_name in label_name_to_value: label_value = label_name_to_value[label_name]else: label_value = len(label_name_to_value) label_name_to_value[label_name] = label_value
# label_values must be dense label_values, label_names = [], []for ln, lv in sorted(label_name_to_value.items(), key=lambda x: x[1]): label_values.append(lv) label_names.append(ln)assert label_values == list(range(len(label_values)))
lbl = utils.shapes_to_label(img.shape, data['shapes'], label_name_to_value)
captions = ['{}: {}'.format(lv, ln)for ln, lv in label_name_to_value.items()] lbl_viz = utils.draw_label(lbl, img, captions) out_dir = osp.basename(count[i]).replace('.', '_') out_dir = osp.join(osp.dirname(count[i]), out_dir) out_dir = osp.join("output",out_dir)
if not osp.exists(out_dir): os.mkdir(out_dir)
PIL.Image.fromarray(img).save(osp.join(out_dir, 'img.png'))
utils.lblsave(osp.join(out_dir, 'label.png'), lbl) PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, 'label_viz.png'))
with open(osp.join(out_dir, 'label_names.txt'), 'w') as f:for lbl_name in label_names: f.write(lbl_name + '\n')
warnings.warn('info.yaml is being replaced by label_names.txt') info = dict(label_names=label_names)with open(osp.join(out_dir, 'info.yaml'), 'w') as f: yaml.safe_dump(info, f, default_flow_style=False)
print('Saved to: %s' % out_dir)
if __name__ == '__main__': main()
我們得到了每張圖片所對應的區域語意類別標簽之后(每一張圖片,灰度類別轉換后,屬于標記目標,如貓,其所屬區域像素點的值均為1,不屬于標記目標的圖片區域(背景)像素點值為0),
如果資料集新增圖片,這張圖片上也只有一個目標狗,為了將目標狗這個類別加入到訓練集中,則需要將狗這個區域類別標簽進行轉換為全域類別標簽,即在訓練時,背景的像素點值為0,貓的像素點值為1,狗的像素點值為2,依次類推)
【4】區域類別標簽—>全域類別標簽(類別灰度轉換)
將得到的每張圖片所對應的區域訓練標簽檔案label.png轉換為全域訓練標簽檔案,放在了png檔案夾下,這個程序中還涉及了類別灰度化操作,
進行get_jpg_and_png.py操作即可得到每張圖片的全域類別標簽檔案和類別灰度轉換,即一張圖片中背景的像素點的值為0,若目標是貓,則其像素點的值為1,若目標是狗,則其像素點的值為2,
這里最終的全域訓練標簽是灰度圖,是單通道的,像素點的取值范圍為0~255,這里全黑是因為,像素點值為1和2,在灰度圖中,值比較小,區別比較小,所以顯示都是黑的,
類別灰度圖圖片:
我們可以看到,貓這張圖片對應的類別灰度圖圖片所在區域的像素點的值均為 1,而背景所對應的像素點的值均為0
1. 這里我們需要首先新建一個包含全域類名稱的class_name.txt
2. 借助class_name.txt檔案,將圖片區域類別標簽檔案轉換成全域類別標簽檔案,轉換代碼:get_jpg_and_png.py
import os
from PIL import Image
import numpy as np
def main():
# 讀取原檔案夾
count = os.listdir("./before/")
for i in range(0, len(count)):
# 如果里的檔案以jpg結尾
# 則尋找它對應的png
if count[i].endswith("jpg"):
path = os.path.join("./before", count[i])
img = Image.open(path)
img.save(os.path.join("./jpg", count[i]))
# 找到對應的png
path = "./output/" + count[i].split(".")[0] + "_json/label.png"
img = Image.open(path)
# 找到全域的類
class_txt = open("./before/class_name.txt","r")
class_name = class_txt.read().splitlines()
# ["bk","cat","dog"] 全域的類
# 打開x_json檔案里面存在的類,稱其為區域類
with open("./output/" + count[i].split(".")[0] + "_json/label_names.txt","r") as f:
names = f.read().splitlines()
# ["bk","dog"] 區域的類
# 新建一張空白圖片
new = Image.new("RGB",[np.shape(img)[1],np.shape(img)[0]])
# 找到區域的類在全域中的類的序號
for name in names:
# index_json是x_json檔案里存在的類label_names.txt,區域類
index_json = names.index(name)
# index_all是全域的類,
index_all = class_name.index(name)
# 將區域類轉換成為全域類
# 將原圖img中像素點的值為index_json的像素點乘以其在全域中的像素點的所對應的類的序號 得到 其實際在資料集中像素點的值
# 比如dog,在區域類(output/x_json/label_names)中它的序號為1,dog在原圖中的像素點的值也為1.
# 但是在全域的類(before/classes.txt)中其對應的序號為2,所以在新的圖片中要將區域類的像素點的值*全域類的序號,從而得到標簽檔案
new = new + np.expand_dims(index_all*(np.array(img) == index_json),-1)
new = Image.fromarray(np.uint8(new))
# 將轉變后的得到的新的最終的標簽圖片保存到make_dataset/png檔案夾下
new.save(os.path.join("./png", count[i].replace("jpg","png")))
# 找到新的標簽檔案中像素點值的最大值和最小值,最大值為像素點對應的類在class_name.txt中的序號,最小值為背景,即0
print(np.max(new),np.min(new))
if __name__ == '__main__':
main()
?
????????3. 最后我們利用get_train_txt.py對上述得到的jpg檔案下和png檔案下的內容進行資料集原圖和標簽的一一對應的關系,將其train_data.txt中
【5】最終訓練模型資料集的樣式:jpg檔案夾(原圖)+png檔案夾(全域灰度類別標簽) + train_data.txt(原圖和標簽的對應關系),放入模型當中即可訓練了,下期講解基于MobileNet的SegNet的語意分割模型,
B.多類別標注- 即一張圖片上有多個目標
標注程序和上述類似,對圖片上的多目標依次進行標注,生成的x_json檔案內容和單目標標注一樣,
新建一個包含全域類名稱的class_name.txt,然后類別灰度轉換, 利用get_jpg_and_png.py進行轉換,我們可以看到貓對應的區域像素點的值為1,對應類別1,同理狗對應區域的像素點的值為2,對應類別2,而背景區域像素點的值為0
進行類別灰度轉換之后,就可以進行模型訓練了,
最終訓練模型資料集的樣式:jpg檔案夾(原圖)+png檔案夾(全域灰度類別標簽) + train_data.txt(原圖和標簽的對應關系),放入模型當中即可訓練了,下期講解基于MobileNet的SegNet的語意分割模型,
好啦,資料標注的部分到這里就結束了,所有處理檔案代碼,回復關鍵字:專案實戰,即可獲取,
精彩推薦:
新教程之影像分割系列
影像分割系列 <-> 語意分割
更多優質內容?等你點在看
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/219004.html
標籤:其他
下一篇:python學習
