網(wǎng)站發(fā)布初期的推廣seo每天一貼
文章目錄
- 一、目標(biāo)檢測
- 1.1 labelImg
- 1.2 介紹
- 1.3 安裝
- 1.4 使用
- 1.5 轉(zhuǎn)換
- 1.6 驗證
- 二、圖像分割
- 2.1 labelme
- 2.2 介紹
- 2.3 安裝
- 2.4 使用
- 2.5 轉(zhuǎn)換
- 2.6 驗證
一、目標(biāo)檢測
1.1 labelImg
1.2 介紹
labelImg是一個開源的圖像標(biāo)注工具,用于創(chuàng)建圖像標(biāo)注數(shù)據(jù)集。它提供了一個簡單易用的界面,允許用戶通過繪制邊界框或者創(chuàng)建多邊形來標(biāo)注圖像中的對象。它支持多種常見的標(biāo)注格式,如Pascal VOC、YOLO和COCO等。
使用labelImg,用戶可以加載圖像文件夾,逐個標(biāo)注圖像中的對象,并保存標(biāo)注結(jié)果。該工具還提供了一些快捷鍵和功能,如縮放、移動和刪除標(biāo)注框,以及快速切換到下一張圖像等。此外,labelImg還支持標(biāo)注圖像的困難程度、部分可見性和關(guān)鍵點等。
labelImg是一個跨平臺的工具,可以在Windows、Linux和macOS等操作系統(tǒng)上運(yùn)行。它基于Python和Qt開發(fā),可以通過pip安裝或從GitHub上獲取源代碼。這使得用戶可以根據(jù)自己的需求進(jìn)行定制和擴(kuò)展。
總而言之,labelImg是一個功能強(qiáng)大、易于使用的圖像標(biāo)注工具,適用于創(chuàng)建各種類型的標(biāo)注數(shù)據(jù)集,從而用于訓(xùn)練和評估計算機(jī)視覺模型。
1.3 安裝
pip install labelImg
1.4 使用
- 在cmd中輸入labelImg,打開目標(biāo)標(biāo)注界面
- open dir選擇圖片的文件夾、Change Save Dir選擇label保存的位置、在View下選擇auto save mode可以不用每次都要點擊保存、在File里面選擇YOLO數(shù)據(jù)集的格式(點擊pascalVOC切換)。
- 通過w來選擇標(biāo)注區(qū)域,然后寫上類別名
- 鍵盤輸入a是上一張,d是下一張
- 然后按照這種格式將圖片和label進(jìn)行分開(train和valid同理)
1.5 轉(zhuǎn)換
如果通過labelImg直接得到txt標(biāo)簽文本是不用進(jìn)行轉(zhuǎn)換就可以提供給YOLO進(jìn)行訓(xùn)練的。
如果是保存的XML文本,則需要通過下面代碼進(jìn)行轉(zhuǎn)換。
修改兩個路徑:xml文件地址和創(chuàng)建保存txt文件的地址
import os
import xml.etree.ElementTree as ET# xml文件存放目錄(修改成自己的文件名)
input_dir = r'E:\auto_label\annotation'# 輸出txt文件目錄(自己創(chuàng)建的文件夾)
out_dir = r'E:\auto_label\labels'class_list = []# 獲取目錄所有xml文件
def file_name(input_dir):F = []for root, dirs, files in os.walk(input_dir):for file in files:# print file.decode('gbk') #文件名中有中文字符時轉(zhuǎn)碼if os.path.splitext(file)[1] == '.xml':t = os.path.splitext(file)[0]F.append(t) # 將所有的文件名添加到L列表中return F # 返回L列表# 獲取所有分類
def get_class(filelist):for i in filelist:f_dir = input_dir + "\\" + i + ".xml"in_file = open(f_dir, encoding='UTF-8')filetree = ET.parse(in_file)in_file.close()root = filetree.getroot()for obj in root.iter('object'):cls = obj.find('name').textif cls not in class_list:class_list.append(cls)def ConverCoordinate(imgshape, bbox):# 將xml像素坐標(biāo)轉(zhuǎn)換為txt歸一化后的坐標(biāo)xmin, xmax, ymin, ymax = bboxwidth = imgshape[0]height = imgshape[1]dw = 1. / widthdh = 1. / heightx = (xmin + xmax) / 2.0y = (ymin + ymax) / 2.0w = xmax - xminh = ymax - ymin# 歸一化x = x * dwy = y * dhw = w * dwh = h * dhreturn x, y, w, hdef readxml(i):f_dir = input_dir + "\\" + i + ".xml"txtresult = ''outfile = open(f_dir, encoding='UTF-8')filetree = ET.parse(outfile)outfile.close()root = filetree.getroot()# 獲取圖片大小size = root.find('size')width = int(size.find('width').text)height = int(size.find('height').text)imgshape = (width, height)# 轉(zhuǎn)化為yolov5的格式for obj in root.findall('object'):# 獲取類別名obj_name = obj.find('name').textobj_id = class_list.index(obj_name)# 獲取每個obj的bbox框的左上和右下坐標(biāo)bbox = obj.find('bndbox')xmin = float(bbox.find('xmin').text)xmax = float(bbox.find('xmax').text)ymin = float(bbox.find('ymin').text)ymax = float(bbox.find('ymax').text)bbox_coor = (xmin, xmax, ymin, ymax)x, y, w, h = ConverCoordinate(imgshape, bbox_coor)txt = '{} {} {} {} {}\n'.format(obj_id, x, y, w, h)txtresult = txtresult + txt# print(txtresult)f = open(out_dir + "\\" + i + ".txt", 'a')f.write(txtresult)f.close()# 獲取文件夾下的所有文件
filelist = file_name(input_dir)# 獲取所有分類
get_class(filelist)# 打印class
print(class_list)# xml轉(zhuǎn)txt
for i in filelist:readxml(i)# 在out_dir下生成一個class文件
f = open(out_dir + "\\classes.txt", 'a')
classresult = ''
for i in class_list:classresult = classresult + i + "\n"
f.write(classresult)
f.close()
1.6 驗證
import cv2
import os# 讀取txt文件信息
def read_list(txt_path):pos = []with open(txt_path, 'r') as file_to_read:while True:lines = file_to_read.readline() # 整行讀取數(shù)據(jù)if not lines:break# 將整行數(shù)據(jù)分割處理,如果分割符是空格,括號里就不用傳入?yún)?shù),如果是逗號, 則傳入‘,'字符。p_tmp = [float(i) for i in lines.split(' ')]pos.append(p_tmp) # 添加新讀取的數(shù)據(jù)# Efield.append(E_tmp)passreturn pos# txt轉(zhuǎn)換為box
def convert(size, box):xmin = (box[1] - box[3] / 2.) * size[1]xmax = (box[1] + box[3] / 2.) * size[1]ymin = (box[2] - box[4] / 2.) * size[0]ymax = (box[2] + box[4] / 2.) * size[0]box = (int(xmin), int(ymin), int(xmax), int(ymax))return boxdef draw_box_in_single_image(image_path, txt_path):# 讀取圖像image = cv2.imread(image_path)pos = read_list(txt_path)for i in range(len(pos)):label = classes[int(str(int(pos[i][0])))]print('label is '+label)box = convert(image.shape, pos[i])image = cv2.rectangle(image,(box[0], box[1]),(box[2],box[3]),colores[int(str(int(pos[i][0])))],2)cv2.putText(image, label,(box[0],box[1]-2), 0, 1, colores[int(str(int(pos[i][0])))], thickness=2, lineType=cv2.LINE_AA)cv2.imshow("images", image)cv2.waitKey(0)if __name__ == '__main__':img_folder = "D:\datasets\YOLO/images"img_list = os.listdir(img_folder)img_list.sort()label_folder = "D:\datasets\YOLO/labels"label_list = os.listdir(label_folder)label_list.sort()classes = {0: "cat", 1: "dog"}colores = [(0,0,255),(255,0,255)]for i in range(len(img_list)):image_path = img_folder + "\\" + img_list[i]txt_path = label_folder + "\\" + label_list[i]draw_box_in_single_image(image_path, txt_path)
二、圖像分割
2.1 labelme
2.2 介紹
LabelMe是一個在線圖像標(biāo)注工具,旨在幫助用戶對圖像進(jìn)行標(biāo)注和注釋。它提供了一個簡單易用的界面,讓用戶可以方便地在圖像上繪制邊界框、標(biāo)記點、線條等,并為每個標(biāo)注對象添加文字描述。
LabelMe的主要特點包括:
-
靈活多樣的標(biāo)注工具:LabelMe提供了多種標(biāo)注工具,包括矩形框、多邊形、線條、點等,可以滿足不同類型圖像的標(biāo)注需求。
-
支持多種標(biāo)注任務(wù):LabelMe適用于各種標(biāo)注任務(wù),包括對象檢測、語義分割、關(guān)鍵點標(biāo)注等。
-
數(shù)據(jù)的可視化和管理:LabelMe支持將標(biāo)注結(jié)果可視化展示,用戶可以在網(wǎng)頁上查看和編輯標(biāo)注結(jié)果。此外,LabelMe還提供了數(shù)據(jù)管理功能,可以方便地組織和管理大量的標(biāo)注數(shù)據(jù)。
-
數(shù)據(jù)的導(dǎo)入和導(dǎo)出:LabelMe支持將標(biāo)注數(shù)據(jù)導(dǎo)入和導(dǎo)出為常見的數(shù)據(jù)格式,如XML、JSON等,方便與其他機(jī)器學(xué)習(xí)和計算機(jī)視覺工具集成。
總的來說,LabelMe是一個功能強(qiáng)大且易于使用的在線圖像標(biāo)注工具,適用于各種圖像標(biāo)注任務(wù),并提供了方便的數(shù)據(jù)管理和導(dǎo)入導(dǎo)出功能。
2.3 安裝
pip install labelme -i https://pypi.tuna.tsinghua.edu.cn/simple/
2.4 使用
參考鏈接:點擊
打完標(biāo)簽后,會在我們圖片的目錄下相應(yīng)的生成JSON標(biāo)簽文件,首先我們先驗證一下我們打的標(biāo)簽和圖片是否對應(yīng),如果沒問題那么我們才轉(zhuǎn)換成YOLO可訓(xùn)練的標(biāo)簽文件。參考代碼如下:
import os, cv2, json
import numpy as npbase_path = '../dataset/labelme_dataset'
path_list = [i.split('.')[0] for i in os.listdir(base_path) if 'json' in i]
print(path_list)
for path in path_list:image = cv2.imread(f'{base_path}/{path}.jpg')h, w, c = image.shapelabel = np.zeros((h, w), dtype=np.uint8)with open(f'{base_path}/{path}.json') as f:mask = json.load(f)['shapes']for i in mask:i = np.array([np.array(j) for j in i['points']])label = cv2.fillPoly(label, [np.array(i, dtype=np.int32)], color=255)image = cv2.bitwise_and(image, image, mask=label)cv2.imshow('Pic', image)cv2.waitKey(0)cv2.destroyAllWindows()
2.5 轉(zhuǎn)換
既然打的標(biāo)簽文件是沒問題的,那么我們開始轉(zhuǎn)換成YOLO可用的TXT文件,轉(zhuǎn)換代碼如下:
import os, cv2, json
import numpy as npclasses = ['square', 'triangle'] # 修改成對應(yīng)的類別base_path = '../dataset/labelme_dataset' # 指定json和圖片的位置
path_list = [i.split('.')[0] for i in os.listdir(base_path)]
for path in path_list:image = cv2.imread(f'{base_path}/{path}.jpg')h, w, c = image.shapewith open(f'{base_path}/{path}.json') as f:masks = json.load(f)['shapes']with open(f'{base_path}/{path}.txt', 'w+') as f:for idx, mask_data in enumerate(masks):mask_label = mask_data['label']if '_' in mask_label:mask_label = mask_label.split('_')[0]mask = np.array([np.array(i) for i in mask_data['points']], dtype=np.float)mask[:, 0] /= wmask[:, 1] /= hmask = mask.reshape((-1))if idx != 0:f.write('\n')f.write(f'{classes.index(mask_label)} {" ".join(list(map(lambda x:f"{x:.6f}", mask)))}')
通過這個代碼可以在當(dāng)前目錄生成對應(yīng)文件名的TXT標(biāo)簽文件,然后我們需要將其劃分為訓(xùn)練集、驗證集和測試集,可通過下面的代碼:
import os, shutil, random
import numpy as nppostfix = 'jpg' # 里面都是jpg圖片
base_path = '../dataset/labelme_dataset' # 原圖片和TXT文件
dataset_path = '../dataset/custom_dataset' # 保存的目標(biāo)位置
val_size, test_size = 0.1, 0.2os.makedirs(dataset_path, exist_ok=True)
os.makedirs(f'{dataset_path}/images', exist_ok=True)
os.makedirs(f'{dataset_path}/images/train', exist_ok=True)
os.makedirs(f'{dataset_path}/images/val', exist_ok=True)
os.makedirs(f'{dataset_path}/images/test', exist_ok=True)
os.makedirs(f'{dataset_path}/labels/train', exist_ok=True)
os.makedirs(f'{dataset_path}/labels/val', exist_ok=True)
os.makedirs(f'{dataset_path}/labels/test', exist_ok=True)path_list = np.array([i.split('.')[0] for i in os.listdir(base_path) if 'txt' in i])
random.shuffle(path_list)
train_id = path_list[:int(len(path_list) * (1 - val_size - test_size))]
val_id = path_list[int(len(path_list) * (1 - val_size - test_size)):int(len(path_list) * (1 - test_size))]
test_id = path_list[int(len(path_list) * (1 - test_size)):]for i in train_id:shutil.copy(f'{base_path}/{i}.{postfix}', f'{dataset_path}/images/train/{i}.{postfix}')shutil.copy(f'{base_path}/{i}.txt', f'{dataset_path}/labels/train/{i}.txt')for i in val_id:shutil.copy(f'{base_path}/{i}.{postfix}', f'{dataset_path}/images/val/{i}.{postfix}')shutil.copy(f'{base_path}/{i}.txt', f'{dataset_path}/labels/val/{i}.txt')for i in test_id:shutil.copy(f'{base_path}/{i}.{postfix}', f'{dataset_path}/images/test/{i}.{postfix}')shutil.copy(f'{base_path}/{i}.txt', f'{dataset_path}/labels/test/{i}.txt')
2.6 驗證
通過結(jié)合TXT標(biāo)簽文件以及圖片來進(jìn)行可視化,以驗證其是否正確。
import os, cv2
import numpy as npimg_base_path = '../dataset/custom_dataset/images/train'
lab_base_path = '../dataset/custom_dataset/labels/train'label_path_list = [i.split('.')[0] for i in os.listdir(img_base_path)]
for path in label_path_list:image = cv2.imread(f'{img_base_path}/{path}.jpg')h, w, c = image.shapelabel = np.zeros((h, w), dtype=np.uint8)with open(f'{lab_base_path}/{path}.txt') as f:mask = np.array(list(map(lambda x:np.array(x.strip().split()), f.readlines())))for i in mask:i = np.array(i, dtype=np.float32)[1:].reshape((-1, 2))i[:, 0] *= wi[:, 1] *= hlabel = cv2.fillPoly(label, [np.array(i, dtype=np.int32)], color=255)image = cv2.bitwise_and(image, image, mask=label)cv2.imshow('Pic', image)cv2.waitKey(0)cv2.destroyAllWindows()