序文
目前用于**图像分割的**数据集,我目前接触到的用的比较多的有:
1 PASCAL VOC
2 COCO
3 YOLO
4 Halcon自己的格式(其实就是Halcon字典类型)
私がコンピューター ビジョンに携わっている現在のデータ セット形式には、さまざまなターゲット検出および画像セグメンテーション タスク用の PASCAL VOC、COCO、YOLO が含まれます。以下に、これら 3 つのデータセット形式の概要を示します。
1. PASCAL VOC フォーマット:
PASCAL VOC (Visual Object Classes) は、広く使用されているオブジェクト検出および画像セグメンテーション データセットであり、その注釈形式は XML ファイルの形式で提供されます。以下は、PASCAL VOC 形式の例です (単一オブジェクトの場合)。
<annotation>
<folder>images</folder>
<filename>example.jpg</filename>
<source>
<database>PASCAL VOC</database>
</source>
<size>
<width>800</width>
<height>600</height>
<depth>3</depth>
</size>
<object>
<name>cat</name>
<pose>Unspecified</pose>
<truncated>0</truncated>
<difficult>0</difficult>
<bndbox>
<xmin>200</xmin>
<ymin>150</ymin>
<xmax>400</xmax>
<ymax>450</ymax>
</bndbox>
</object>
</annotation>
2.COCO形式:
COCO (Common Objects in Context) は、オブジェクトの検出、セグメンテーション、キーポイント推定のための大規模なデータセットであり、そのアノテーション形式は JSON ファイルの形式で提供されます。以下は COCO 形式の例です (単一オブジェクトの場合)。
{
"info": {
},
"images": [
{
"id": 1,
"file_name": "example.jpg",
"width": 800,
"height": 600,
"depth": 3
}
],
"annotations": [
{
"id": 1,
"image_id": 1,
"category_id": 1,
"bbox": [200, 150, 200, 300],
"area": 60000,
"iscrowd": 0
}
],
"categories": [
{
"id": 1,
"name": "cat"
}
]
}
3.YOLO形式:
YOLO (You Only Look Once) はターゲット検出アルゴリズムであり、特有のデータ セット形式もあります。YOLO 形式には通常、各行が画像内のオブジェクトを説明するテキスト ファイルが必要です。以下に YOLO 形式の例を示します (各行は 1 つのオブジェクトを表します)。
0 0.45 0.35 0.2 0.5
この例では、各行にカテゴリ インデックスとオブジェクトの正規化された座標情報 (中心点の座標、画像サイズに対する幅と高さ) が含まれています。
これらの例はデモンストレーションのみを目的としており、実際のデータセット ファイルにはさらに多くの画像やオブジェクトの注釈情報が含まれている可能性があることに注意してください。さまざまなタスクやアルゴリズムに適したデータセット形式が異なるため、特定のデータセットを使用する場合は、対応するアノテーション形式を理解する必要があります。
これらの形式はすべて、画像内の特定のフレームの位置と、そのフレームに対応するカテゴリを記述します。
背景
現在、PASCAL VOC 形式のデータ セットを持っています。各画像には、対応するラベル付き画像があります。次に、halcon を使用してデータ セット全体を読み取りたいと考えています。ただし、halcon には独自の注釈ツールがあります: MVTec 深層学習ツールには
このソフトウェアによって注釈が付けられた画像があり、エクスポートされたデータ セットの形式は .hdict です。PASCAL
VOC を .hdict 形式に直接変換する方法はありますか?
PASCAL VOC から .hdict へ
PASCAL VOC のフォーマット タイプは XML であることは既に説明しましたが、この XML を解析するのは簡単ですが、.hdict ファイルはバイナリ ファイルであり、内容を確認することはできません。
そこで、インターネットを検索して、PASCAL VOC を .hdict に変換するための halcon スクリプトを見つけ、高いお金を出して購入しました。 :
*read_dict ('C:/Users/12820/Desktop/数据/分割.hdict', [], [], DictHandle)
* Image Acquisition 01: Code generated by Image Acquisition 01
*read_dl_dataset_from_coco
*read_dl
create_dict (NEWDictHandle1)
class_ids:=[0,1,2,3,4,5]
class_names:=['crazing', 'inclusion', 'patches', 'pitted_surface', 'rolled-in_scale', 'scratches']
image_dir:='images/'
set_dict_tuple (NEWDictHandle1, 'class_ids', class_ids)
set_dict_tuple (NEWDictHandle1, 'class_names', class_names)
set_dict_tuple (NEWDictHandle1, 'image_dir', image_dir)
list_files ('images/', ['files','follow_links','recursive'], ImageFiles)
tuple_regexp_select (ImageFiles, ['\\.(tif|tiff|gif|bmp|jpg|jpeg|jp2|png|pcx|pgm|ppm|pbm|xwd|ima|hobj)$','ignore_case'], ImageFiles)
list_files ('labels/', ['files','follow_links','recursive'], xmladdress)
samples:=[]
for Index := 0 to |ImageFiles| - 1 by 1
read_image (Image, ImageFiles[Index])
open_file (xmladdress[Index], 'input', FileHandle)
IsEof := false
bbox_row1:=[]
bbox_col1:=[]
bbox_row2:=[]
bbox_col2:=[]
bbox_label_id:=[]
while (not(IsEof))
fread_line (FileHandle, XmlElement, IsEof)
if (IsEof)
break
endif
tuple_split (XmlElement, '<''>', Substrings)
create_dict (image)
if (Substrings[1]=='folder')
floder:= Substrings[2]
endif
if (Substrings[1]=='filename')
filename:= Substrings[2]
endif
*class_names:=['crazing', 'inclusion', 'patches', 'pitted_surface', 'rolled-in_scale', 'scratches']
if (Substrings[1]=='name')
if (Substrings[2]== class_names[0] )
bbox_label_id:=[bbox_label_id,0]
elseif (Substrings[2]==class_names[1])
bbox_label_id:=[bbox_label_id,1]
elseif (Substrings[2]==class_names[2])
bbox_label_id:=[bbox_label_id,2]
elseif (Substrings[2]==class_names[3])
bbox_label_id:=[bbox_label_id,3]
elseif (Substrings[2]==class_names[4])
bbox_label_id:=[bbox_label_id,4]
elseif (Substrings[2]==class_names[5])
bbox_label_id:=[bbox_label_id,5]
endif
endif
if (Substrings[1]=='xmin')
bbox_col1:= [bbox_col1,Substrings[2]]
tuple_number (bbox_col1, bbox_col1)
endif
if (Substrings[1]=='ymin')
bbox_row1:= [bbox_row1,Substrings[2] ]
tuple_number (bbox_row1, bbox_row1)
endif
if (Substrings[1]=='xmax')
bbox_col2:=[bbox_col2, Substrings[2] ]
tuple_number (bbox_col2, bbox_col2)
endif
if (Substrings[1]=='ymax')
bbox_row2:=[bbox_row2, Substrings[2] ]
tuple_number (bbox_row2, bbox_row2)
endif
endwhile
* gen_rectangle1 (Rectangle,bbox_row1 , bbox_col1,bbox_row2 , bbox_col2)
set_dict_tuple (image, 'image_id', Index+1)
set_dict_tuple (image, 'image_file_name', floder+'/'+filename)
set_dict_tuple (image, 'bbox_label_id', bbox_label_id)
set_dict_tuple (image, 'bbox_row1', bbox_row1)
set_dict_tuple (image, 'bbox_col1', bbox_col1)
set_dict_tuple (image, 'bbox_row2', bbox_row2)
set_dict_tuple (image, 'bbox_col2', bbox_col2)
samples:=[samples,image]
*stop()
endfor
set_dict_tuple (NEWDictHandle1, 'samples', samples)
write_dict (NEWDictHandle1, '数据test.hdict', [], [])
最後の文 write_dict を見て、いわゆる .hdict ファイルが halcon の辞書形式であることに気付きました。
このスクリプトファイルは使えるのですが、1800個のデータを変換するのに30分近くかかりましたが、これは許容できるでしょうか?
PASCAL VOC アノテーション ファイルにも問題があり、画像名にサフィックスがないため、
インポート後に画像をディープ ラーニング ツールに表示できません。したがって、原理を理解した後は、自分でツールを作成するのが簡単になります。
HTuple NEWDict;
HOperatorSet.CreateDict(out NEWDict);
List<int> class_ids = new List<int> {
0, 1, 2, 3, 4, 5 };
List<string> class_names = new List<string> {
"crazing", "inclusion", "patches", "pitted_surface", "rolled-in_scale", "scratches" };
string image_dir = "F:\\temp\\数据集格式转换测试\\images";
//图片字典
HTuple hv_image = new HTuple();
HTuple hv_samples = new HTuple();
HTuple hv_class_ids = new HTuple(class_ids.ToArray());
HTuple hv_class_names = new HTuple(class_names.ToArray());
HTuple hv_image_dir = new HTuple(image_dir);
HOperatorSet.SetDictTuple(NEWDict, "class_ids", hv_class_ids);
HOperatorSet.SetDictTuple(NEWDict, "class_names", hv_class_names);
HOperatorSet.SetDictTuple(NEWDict, "image_dir", hv_image_dir);
string[] imageFiles = Directory.GetFiles(image_dir, "*.*", SearchOption.AllDirectories);
List<Dictionary<string, object>> samples = new List<Dictionary<string, object>>();
int index = 0;
string extension = "";
foreach (string imagePath in imageFiles)
{
HOperatorSet.CreateDict(out hv_image);
string xmlPath = "D:/DATASET/yolo/NEU-DET/ANNOTATIONS/" + Path.GetFileNameWithoutExtension(imagePath) + ".xml";
XDocument xdoc;
using (StreamReader reader = new StreamReader(xmlPath))
{
string xmlContent = reader.ReadToEnd();
xdoc = XDocument.Parse(xmlContent);
// 现在可以使用xdoc进行XML解析操作
}
XElement xroot = xdoc.Root;//根节点
List<int> bbox_label_ids = new List<int>();
List<int> bbox_col1 = new List<int>();
List<int> bbox_row1 = new List<int>();
List<int> bbox_col2 = new List<int>();
List<int> bbox_row2 = new List<int>();
//----folder
var folder = xroot.Element("folder").Value;
//----filename
var filename = xroot.Element("filename").Value;
if(Path.GetExtension(filename) != "")
{
extension = Path.GetExtension(filename);
}
else
{
if (extension != "")
{
filename += extension;
}
}
//----获取object节点(一个xml中可能会有多个)
var objectNodes = xroot.Descendants("object");
foreach (var objectNode in objectNodes)
{
//bndbox节点,包含xmin,ymin,xmax,ymax
XElement bndboxNode = objectNode.Element("bndbox");
XElement xminNode = bndboxNode.Element("xmin");
XElement yminNode = bndboxNode.Element("ymin");
XElement xmaxNode = bndboxNode.Element("xmax");
XElement ymaxNode = bndboxNode.Element("ymax");
// 解析坐标值并添加到相应列表
bbox_col1.Add(int.Parse(xminNode.Value));
bbox_row1.Add(int.Parse(yminNode.Value));
bbox_col2.Add(int.Parse(xmaxNode.Value));
bbox_row2.Add(int.Parse(ymaxNode.Value));
// 获取类别名称对应的编号,并添加到相应列表
string className = objectNode.Element("name").Value;
int id = class_names.IndexOf(className);
bbox_label_ids.Add(id);
}
HOperatorSet.SetDictTuple(hv_image, "image_id", index + 1);
HOperatorSet.SetDictTuple(hv_image, "image_file_name", (folder + "/") + filename);
HOperatorSet.SetDictTuple(hv_image, "bbox_label_id", bbox_label_ids.ToArray());
HOperatorSet.SetDictTuple(hv_image, "bbox_row1", bbox_row1.ToArray());
HOperatorSet.SetDictTuple(hv_image, "bbox_col1", bbox_col1.ToArray());
HOperatorSet.SetDictTuple(hv_image, "bbox_row2", bbox_row2.ToArray());
HOperatorSet.SetDictTuple(hv_image, "bbox_col2", bbox_col2.ToArray());
// hv_image添加到samples
using (HDevDisposeHelper dh = new HDevDisposeHelper())
{
HTuple ExpTmpLocalVar_samples = hv_samples.TupleConcat(hv_image);
hv_samples.Dispose();
hv_samples = ExpTmpLocalVar_samples;
}
index++;
}
HOperatorSet.SetDictTuple(NEWDict, "samples", hv_samples);
HOperatorSet.WriteDict(NEWDict, "数据Csharp.hdict", new HTuple(), new HTuple());
MessageBox.Show("转换完成");
今回は XDocument メソッドを使用して解析しますが、数回クリックするだけで変換が完了します。ディープ ラーニング ツールを再度使用して、変換された Csharp.hdict を開きます。今回は成功しました。
.hdict 形式のデータセットを読み取る
.hdict 形式のデータが設定されているのですが、どのように使用するのですか?
*データセットを読んでください! !!これは、ディープ ラーニング ツールによってマークされた辞書
read_dict ("xxxxx.hdict", [], [], DLDataset)
です。これは辞書である必要があるため、read_dict を使用してデータ セットを直接読み取ることができます。
また、halcon は独自のデータ セットに加えて、実際には coco データ セットを直接読み取ることができます。
read_dl_dataset_from_coco (FileExists, [], [], DLDataset1) は
あまり便利ではありません。
データの学習方法の詳細については、今後も継続的に出力していきます。
付録
PASCAL VOC を YOLO に変換するための Python スクリプトが付属しています。
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
import glob
classes = ["crazing", "inclusion", "patches", "pitted_surface", "rolled-in_scale", "scratches"]
def convert(size, box):
dw = 1./size[0]
dh = 1./size[1]
x = (box[0] + box[1])/2.0
y = (box[2] + box[3])/2.0
w = box[1] - box[0]
h = box[3] - box[2]
x = x*dw
w = w*dw
y = y*dh
h = h*dh
return (x,y,w,h)
def convert_annotation(image_name):
in_file = open('./ANNOTATIONS/'+image_name[:-3]+'xml')
out_file = open('./LABELS/'+image_name[:-3]+'txt','w')
tree=ET.parse(in_file)
root = tree.getroot()
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)
for obj in root.iter('object'):
cls = obj.find('name').text
if cls not in classes:
print(cls)
continue
cls_id = classes.index(cls)
xmlbox = obj.find('bndbox')
b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
bb = convert((w,h), b)
out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
wd = getcwd()
if __name__ == '__main__':
for image_path in glob.glob("./IMAGES/*.jpg"):
image_name = image_path.split('\\')[-1]
#print(image_path)
convert_annotation(image_name)