深度学习图像标注工具labelme
來源:極客Merry
前言
在深度學(xué)習(xí)中若是沒有帶標(biāo)注的數(shù)據(jù),這可能會阻礙研究的進(jìn)展,所以深度學(xué)習(xí)第一步就是制作數(shù)據(jù)集,手動去標(biāo)注一些數(shù)據(jù)。LabelMe就是這樣一個在線的圖像數(shù)據(jù)標(biāo)注工具:
LabelMe工具地址
http://labelme.csail.mit.edu/Release3.0/
今天要介紹的圖像標(biāo)注工具是受到LabelMe啟發(fā)的,使用Python和PyQT進(jìn)行重寫的一個離線工具labelme:
labelme的GitHub地址
https://github.com/wkentaro/labelme
labelme可以通過多邊形,矩形,圓形,直線和點(diǎn)的方式對圖像進(jìn)行標(biāo)注,能夠滿足語義分割和目標(biāo)檢測等任務(wù)的標(biāo)注要求。同時,labelme通過json文件存儲標(biāo)注的信息。
01
labelme安裝
各個平臺的安裝方法在GitHub上已有說明,我使用的是Win10,在Win10,Python3環(huán)境下的安裝也很簡單:
pip?install?pyqt5
pip?install?labelme
如果安裝速度過慢,可以考慮換源:
pip?install?labelme??-i?https://pypi.tuna.tsinghua.edu.cn/simple
安裝完成后,在命令行執(zhí)行以下命令,就會出現(xiàn)labelme的界面
labelme
然后就可以對圖像進(jìn)行標(biāo)注了。Open選項(xiàng)是打開一張圖像,對單張圖像進(jìn)行標(biāo)注,OpenDir選項(xiàng)是選中要標(biāo)記的圖像文件夾,對文件夾內(nèi)的所有圖像進(jìn)行標(biāo)注。
02
語義分割標(biāo)注
點(diǎn)擊"open",打開需要標(biāo)注的圖像,選擇"CreatePolygons",然后對目標(biāo)區(qū)域進(jìn)行標(biāo)注。
"CreatePolygons"是采用多邊形方式標(biāo)注,同樣有矩形(Rectangle),圓形(Circle),線段(Line)和點(diǎn)(Point)的方式進(jìn)行標(biāo)注,可根據(jù)需要自由選擇。
標(biāo)注完成后,點(diǎn)擊"save"會生成一個json文件,這個文件就保存了圖像標(biāo)注的信息。打開json文件看看里面都是什么東東。限于篇幅原因,只展示關(guān)鍵的數(shù)據(jù)信息。
下面的json文件只展示了桌子的標(biāo)注信息(上圖中兩個人的標(biāo)注信息由于太長,故刪去)。可以看到,"shapes"字段包含了整幅圖像所有區(qū)域的標(biāo)注點(diǎn)信息,具體的各個區(qū)域標(biāo)注的點(diǎn)的信息都存在"points"里,它表示的是圖像上構(gòu)成多邊形標(biāo)注的各點(diǎn)坐標(biāo),"label"指明該目標(biāo)區(qū)域的類別,"imageData"參數(shù)保存了原始圖像的信息。
{"version":?"4.5.7","flags":?{},"shapes":?[{"label":?"tabel","points":?[[304.34715025906735,274.3523316062176],[330.7720207253886,268.13471502590676],[367.0414507772021,268.9119170984456],[393.98445595854923,279.01554404145077],[422.74093264248705,295.0777202072539],[432.0673575129534,316.0621761658031],[426.6269430051814,331.0880829015544],[422,337],[292,337],[277.4041450777202,336.7875647668394],[273.25906735751295,303.8860103626943],[283.10362694300517,290.1554404145078]],"group_id":?null,"shape_type":?"polygon","flags":?{}}],"imagePath":?"2011_000003.jpg","imageData":?"巨長巨長的圖像數(shù)據(jù)","imageHeight":?338,"imageWidth":?500
}
然后將json文件轉(zhuǎn)換為對應(yīng)的標(biāo)簽圖像。進(jìn)入json文件所在目錄下,在命令行執(zhí)行以下命令
labelme_json_to_dataset?2011_000003.json
在同一級目錄下會生成一個與json同名的文件夾,里面有四個文件:
"label.png"就是語義分割需要的標(biāo)簽數(shù)據(jù)了。這張圖像標(biāo)注了兩類區(qū)域(加上背景總共三類),一類是"person",另一類是"tabel",同一類別的區(qū)域用同一種顏色填充。
讀取"label.png"看看里面底層數(shù)據(jù)都是什么妖魔鬼怪:寫一個腳本將圖像數(shù)據(jù)轉(zhuǎn)換為ASCII碼,并且保存到txt文件中,這個過程有點(diǎn)像是圖像轉(zhuǎn)字符畫。
import?numpy?as?np
from?PIL?import?Imagepng_file?=?"label.png路徑"
img?=?Image.open(png_file)
img?=?img.resize((int(img.size[0]*0.25),int(img.size[1]*0.25)))
print(img.size)img_arr?=?np.asarray(img)
#?統(tǒng)計(jì)圖像中的像素點(diǎn)數(shù)值
label?=?np.unique(img_arr)
print(label)height,?width?=?img_arr.shape
print(height,?width)img2code?=?''
for?i?in?range(height):for?j?in?range(width):#pixel?=?img.getpixel((j,?i))#img2code?+=?ascii(pixel)img2code?+=?ascii(img_arr[i][j])img2code?+=?'\n'fo?=?open('txt存儲路徑',?'w')
fo.write(img2code)
fo.close()
打開剛剛保存的txt文件,因?yàn)樘笕溜@示不了,將字體大小設(shè)置為七號,可以看到效果如下。字符畫的寬高比例和原圖不一樣,這是因?yàn)樨Q直方向上顯示字符占用的空間大小和水平方向上不一樣。
從上圖可以看出,最終得到的標(biāo)簽圖像,底層存儲的數(shù)值按不同類別區(qū)域設(shè)置為不同數(shù)值,背景的每個像素?cái)?shù)值設(shè)置為0,person的每個像素?cái)?shù)值設(shè)為1,tabel的每個像素?cái)?shù)值設(shè)為2。
03
批量轉(zhuǎn)換json為標(biāo)簽圖像
"labelme_json_to_dataset"這個命令能將json文件轉(zhuǎn)為標(biāo)簽數(shù)據(jù),但是它一次只能轉(zhuǎn)換一個,若是有成千上萬張圖像簡直難以想象,本來標(biāo)注完圖像已經(jīng)頭昏腦脹,難道還要我一個一個轉(zhuǎn)換?不可能的!這時需要自己寫個腳本來幫我們完成這個任務(wù)。
第一種方式借助于labelme提供的"labelme_json_to_dataset"這個命令。利用os.system()函數(shù)批量轉(zhuǎn)換json文件,每個json生成的同名文件夾與json在同一級目錄下。
import?osjson_path?=?"json文件保存路徑"for?filename?in?os.listdir(json_path):os.system("labelme_json_to_dataset?"+os.path.join(json_path,filename))
第二種方式使用labelme提供的API。使用img_b64_to_arr()函數(shù),將json文件中"iamgeData"字段的字符轉(zhuǎn)換為原始圖像;然后根據(jù)json文件中"shapes"字段的標(biāo)注信息,使用labelme_shapes_to_label()函數(shù)獲取到標(biāo)簽圖像lbl。
有童鞋可能會發(fā)現(xiàn),此時的lbl標(biāo)簽圖像一片漆黑,什么也沒有。這是因?yàn)閳D像中各點(diǎn)的像素值是標(biāo)簽對應(yīng)的數(shù)字(如同上面畫的字符畫),而這些數(shù)字都很小:0,1,2,3....,而黑色對應(yīng)的像素值為0,所以lbl圖像的顏色和黑色非常接近,看起來就是一片漆黑。
這時我們只需要給圖像上色就可以了:使用putpalette()函數(shù),而且我們可以自定義各個類別區(qū)域的顏色。
import?json
import?os
import?numpy?as?np
from?PIL?import?Image
from?labelme?import?utilsdef?json2mask_multi(json_path,?save_path):if?not?os.path.exists(save_path):os.makedirs(save_path)for?json_name?in?os.listdir(json_path):data?=?json.load(open(os.path.join(json_path,?json_name)))json_name?=?json_name.split('.')[0]#?根據(jù)imageData字段的字符可以得到原圖像img?=?utils.img_b64_to_arr(data['imageData'])#?lbl為label圖像(用類別名對應(yīng)的數(shù)字來標(biāo),背景為0)#?lbl_names為label名和數(shù)字的對應(yīng)關(guān)系字典lbl,?lbl_names?=?utils.labelme_shapes_to_label(img.shape,?data['shapes'])mask?=?Image.fromarray(lbl).convert('L')# putpalette給對象加上調(diào)色板,相當(dāng)于上色:R,G,B#?三個數(shù)一組,對應(yīng)于RGB通道,可以自己定義標(biāo)簽顏色mask.putpalette([0,?0,?0,??255,?0,?255,255,?255,?0,128,?128,?128])mask.save(os.path.join(save_path,?json_name?+?".png"))json_path?=?"json文件存儲路徑"
save_path?=?"標(biāo)簽圖像的保存路徑"
json2mask_multi(json_path,save_path)
本文只是對labelme簡單介紹了一番,因?yàn)樽约涸谧稣Z義分割時需要做一些標(biāo)注,所以只介紹了語義分割上的應(yīng)用,而labelme還可以滿足目標(biāo)檢測和圖像分類任務(wù)的標(biāo)注要求,這些功能就留給各位童鞋去探索研究,這里就不一一展開來說明。
-------?End -------
點(diǎn)右下角「在看」與轉(zhuǎn)發(fā)
是對我們最大的支持
特別推薦下公眾號「價(jià)值前瞻」,分享讀書、成長和投資思考,歡迎來串門。
回復(fù)「書單」?可獲取精選書單一份,包括《如何閱讀 一本書》、《巴菲特之道》、《金字塔原理》、高瓴張磊的《價(jià)值》、《投資最重要的事》、《戴維斯王朝》等書籍的筆記內(nèi)容或思維導(dǎo)圖
價(jià) 值 前 瞻
做一個有遠(yuǎn)見的人
掃碼關(guān)注,查看更多內(nèi)容
總結(jié)
以上是生活随笔為你收集整理的深度学习图像标注工具labelme的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 中获取文件名不要扩展名_如何批量修改文件
- 下一篇: 反向传播是什么?通俗易懂的解释!!!