Labelme的改進——海量圖片的自動標注
????深度學習一般需要對大量的圖片進行標注,但是手動標注耗時耗力,所以模仿labelme軟件的功能,使用程序對大批量的圖片進行自動標注,大大減少手動操作。下面介紹如何實現對大批量的圖片進行標注。
自動標注的程序實現:https://github.com/shuyucool/Labelme.git
一:Labelme的安裝參考——https://github.com/wkentaro/labelme.git
???這里簡要介紹windows下如何安裝:
?
1) 打開Anaconda命令行工具
2) conda create --name=labelme python=3.5 #我使用的版本是Python3.5,根據自己的情況修改版本號
3) activate labelme
4) conda install pyyaml
5) pip install labelme
6) labelme
???安裝中可能會出現這樣的錯誤:
?
from PyQt5 import QtCore?
ImportError: DLL load failed: 找不到指定的模塊。
?出現這樣錯誤的原因是:
??????Anaconda 安裝的Python缺少了python3.dll,可以通過去python.org 下載所需版本的python安裝包并安裝,然后從安裝目錄中拷貝python3.dll文件,粘貼到Anaconda安裝目錄下,也就是python36.dll所在的目錄下,一般就是第一層目錄,具體要看自己的安裝情況。
詳細解決方案參照——https://blog.csdn.net/ltime/article/details/71403947
?
二:了解Labelme生成的json文件的內部數據,批量生成標注圖像
{
? "imageData": "xxxxxx", # 原圖像數據通過b64編碼生成的字符串數據,這里不重要,只需要知道是圖像數據的另一種存儲形式
? "shapes": [ # 所有對象的形狀,鼠標點擊的輪廓坐標點,填充顏色等
? ? { # 第一個對象
? ? ? "points": [ # 邊緣是由點構成,實際上就是物體的輪廓坐標
? ? ? ? [
? ? ? ? ? 165.90909090909093, # 第一個點 x 坐標
? ? ? ? ? 36.909090909090935 ?# 第一個點 y 坐標
? ? ? ? ],
? ? ? ? ……
? ? ? ? [
? ? ? ? ? 240.90909090909093,
? ? ? ? ? 15.909090909090935
? ? ? ? ],
? ? ? ? [
? ? ? ? ? 216.90909090909093, # 最后一個點的x坐標
? ? ? ? ? 31.909090909090935 # 最后一個點的y坐標
? ? ? ? ]
? ? ? ],
? ? ? "fill_color": null, #填充顏色
? ? ? "label": "cat_1", ?# 第一個對象的標簽
? ? ? "line_color": null
? ? },
? ? { ?# 第二個對象
? ? ? "points": [
? ? ? ? [
? ? ? ? ? 280.90909090909093,
? ? ? ? ? 31.909090909090935
? ? ? ? ],
? ? ? ? ……
? ? ? ? [
? ? ? ? ? 362.90909090909093,
? ? ? ? ? 20.909090909090935
? ? ? ? ],
? ? ? ? [
? ? ? ? ? 339.90909090909093,
? ? ? ? ? 32.909090909090935
? ? ? ? ]
? ? ? ],
? ? ? "fill_color": null,
? ? ? "label": "cat_2", # 第二個對象的標簽
? ? ? "line_color": null
? ? }
? ],
? "fillColor": [
? ? 255,
? ? 0,
? ? 0,
? ? 128
? ],
? "imagePath": "/home/wu/1.jpg", # 原始圖片的路徑
? "lineColor": [
? ? 0,
? ? 255,
? ? 0,
? ? 128
? ]
}
?
詳細信息可以參考——https://blog.csdn.net/wc781708249/article/details/79595174
?
參考labelme軟件標記后生成的json文件海量圖片的自動標注可以分為以下四個步驟:
【1】提取圖片中物體輪廓的坐標
【2】將圖片編碼保存為json格式
【3】將【1】中的坐標數據與【2】的編碼后的圖片數據“融合”
【4】自動解析生成的json文件,并將16位的label.png轉為8位的圖片格式
?
三:提取物體輪廓坐標
?????圖片中物體輪廓的提取需要將原圖現轉化為二值圖,然后找到各個連通域的坐標,將所有圖片中不同的連通域對應的坐標保存為mat文件。示意圖如下:
?????輪廓坐標提取程序使用MATLAB編寫,為了方便大家閱讀,已經精簡了程序并加了注釋:(不明白輪廓提取得到的數據可以參考補充提供的示例數據,Z.mat數據中只有Z.btnimage類下是需要的數據,就是簡單的背景減除或者二值化處理)
%%MATLAB版本%%
load('D:\Zerbrafish Tracking\107-LXP7-6\107-LXP7-6_Z.mat');%加載指定的數據,因為我把二值化后的圖像都保存在了mat中
for i = 1:size(Z,2)
? ? Process_data= size(Z(i).imageCroped,2);
? ? if Process_data == 6 ?%當魚的數量等于6時,繼續執行
? ? ? ? I = Z(i).btnimage{1,1};%讀入圖像 ?這一步是關鍵,可以在此程序基礎上修改,加載轉換成二值化的圖片
? ? ? ? BW = im2bw(I, graythresh(I));%轉換成2進制圖像
? ? ? ? [B,L] = bwboundaries(BW,'noholes');%尋找邊緣,不包括孔
? ? ? ? mid_arug = cell(length(B),2);
? ? ?for k = 1:length(B)
? ? ? ? ?boundary = B{k}; %boundary表示所有的輪廓坐標,為了節省內存,我們取其1/4
? ? ? ? ?x_coordinate = ?boundary(1:4:end,2);
? ? ? ? ?y_coordinate = ?boundary(1:4:end,1);
? ? ? ? ?mid_arug{k,1} = {boundary(1:4:end,2)};
? ? ? ? ?mid_arug{k,2} = {boundary(1:4:end,1)};
? ? ?end
? ? ?assignin('base',['img_',num2str(i)],mid_arug);
? ? end
end
?
四:將圖片編碼后保存為json文件
?????這是為了最后生成的json文件和Labelme軟件生成的json文件相同的必須工作。同時為了批量能夠對圖像進行處理,編寫了一個轉換程序。批量轉換程序命名為:img2json.py。如果需要請點擊傳送門。(程序中已加入了詳細的中文注釋。)
?????以上面的圖片為例轉換成json文件后,其部分內容如下:(真正的圖片數據很大,為方便演示,只展示部分)
五:坐標數據與圖像數據的融合
?????坐標數據與圖像數據的融合,生成可供Labelme解析的json文件。融合程序命名為imitate_json.py。如果需要請點擊傳送門。(程序中已加入了詳細的中文注釋。)自動生成的json文件其實在內容上和“二”中介紹的json內部數據相同。
六:json文件的批量解析
?????如果一個一個的對“五”中生成的json文件解析,需要首先進入Labelme的安裝路徑,找到Scripts文件夾,進入后運行:
python labelme_json_to_dataset [文件名] #比如 python labelme_json_to_dataset D:\Practice\fusion_json\1.josn
?????但這樣每次只能解析一個文件,為了能夠批量解析,我寫了一個批量解析的程序,命名為release_json.py。如有需要請點擊傳送門。(程序中已加入了詳細的中文注釋。)解析后會在當前json文件路徑下生成一個對應的json文件夾。如下圖:
以“1_json”文件為例,其中包含了五個文件。如下圖:
?????其中的label.png是uint16格式存儲的圖像,需要將其轉成uint8格式存儲的才能讓opencv讀取。16位的label.png批量轉換成8位的程序命名為uint16_to_uint8.py。程序如下:(非常精簡)
#!/usr/bin/env python
# _*_ coding: UTF-8 _*_
# author:"Zhang Shuyu"
"""使用skimage模塊讀取圖片,不改變圖片數據類型uint16,保存為uint8類型"""
import os
import cv2
import natsort
import numpy as np
from skimage import io
from matplotlib import pylab as plt
input_file = "D:\\Practice\\fusion_json\\" ?#文件路徑
img_type = ".png"
?
for root, dirs, files in os.walk(input_file,topdown=True):
? ? for name in natsort.natsorted(dirs): ?#natsort,自然排序
? ? ? ? file_name = os.path.join(input_file + name,"label_1" + img_type)
? ? ? ? img = io.imread(file_name) ?#Todo:使用skimage模塊讀取圖片不會改變圖片的數據格式
? ? ? ? print(img.dtype)
? ? ? ? img = img.astype(np.uint8)
? ? ? ? print(img.dtype)
? ? ? ? cv2.imwrite(os.path.join(input_file + name,"label_1" + img_type),img)
?
?????其中的label.png轉成8位后看起來還是一片黑色,當其實已經對目標價上了標簽。以上圖中的label.png為例,轉換為8位后再對齊進行圖像增強,效果如下:
?
?
????其實就是對uint8類型格式的圖片數據讀取后乘以40。(uint8的取值范圍是0~255,在MATLAB顯示label.png圖片雖然看起來一片黑,但目標位置其實都加上了標簽1,2,3,4,5,6,以上圖為例,乘以40后,目標位置的像素相當于變成了40,80,120,160,200,240,所以顯示出的圖像就是目標顏色的深淺各不相同)
補充:
鑒于很多人詢問關于輪廓提取的數據問題,即加載的數據Z.mat是什么??我將自己的一個示例數據的鏈接提供給大家(Z.mat數據中只有Z.btnimage類下的數據是需要的數據)
https://pan.baidu.com/s/16-PH3zpS4yM_UA5t6iTFrw
?????這樣就能快速制作出大量的訓練數據集,對于幾千張圖片的標注大概只需要幾分鐘就能完成,如果手動標注的話一個人至少需要兩天。程序內容均為原創,使用請用麻煩點贊呀
————————————————
版權聲明:本文為CSDN博主「Kellybook」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/qq_30622831/java/article/details/80100605