ssd kerasの教師データをyolo用に変換

世の中の流れと逆行していますが,諸般の事情により必要となったので,スクリプトを書きました.

まずは,Pascal VOC形式のxmlファイルをPythonで読むを元に,xmlファイルのデータを取ってきて,変換して出力してみました.

# coding:utf-8

import xml.etree.ElementTree as ET
import sys

# FILE = '00001.xml'
args = sys.argv

for FILE in args:
    # print FILE
    if FILE != args[0]:
        file = open(FILE)
        tree = ET.parse(file)
        root = tree.getroot()

        all_list = []

        img_file = root.find('filename').text  # 画像ファイル名を取得

        for obj in root.iter('object'):
            cls = obj.find('name').text
            xmlbox = obj.find('bndbox')
            b = [int(xmlbox.find('xmin').text), int(xmlbox.find('ymin').text), int(xmlbox.find('xmax').text), int(xmlbox.find('ymax').text)]
            all_list.append([img_file] + b + [cls])
        # print all_list
        # [['00102.jpg', 148, 369, 494, 957, 'WALL'], ['00102.jpg', 470, 16, 1176, 849, 'MPS']]
        if cls == 'MPS':
            print '0',
        else:
            print '1',
        centerx = (int(xmlbox.find('xmin').text) + int(xmlbox.find('xmax').text)) / 2
        centery = (int(xmlbox.find('ymin').text) + int(xmlbox.find('ymax').text)) / 2
        widthx = (int(xmlbox.find('xmax').text) - int(xmlbox.find('xmin').text))
        widthy = (int(xmlbox.find('ymax').text) - int(xmlbox.find('ymin').text))
        print centerx, centery, widthx, widthy

複数ファイルに対応させておきながら,この出力結果を扱う方法が面倒くさかったので,その部分はbashで書いちゃいました.

#!/bin/bash

for FILE in `ls *.xml`; do
        TXT="`echo $FILE|sed 's/\.[^\.]*$//'`.txt"
        echo $TXT
        python convert.py $FILE > $TXT
done

これで,xml ファイルからdarknet のtxt ファイルに一括変換できました.

※2019/11/15追加
学生からの指摘で,変換後は,画像のサイズで正規化する必要があるとのことでした.
つまり,int(サイズ) /2のところが,1920X1080の場合は,

        centerx = (float(xmlbox.find('xmin').text) + float(xmlbox.find('xmax').text)) / 2 / 1920
        centery = (float(xmlbox.find('ymin').text) + float(xmlbox.find('ymax').text)) / 2 /1080
        widthx = (float(xmlbox.find('xmax').text) - float(xmlbox.find('xmin').text)) / 1980
        widthy = (float(xmlbox.find('ymax').text) - float(xmlbox.find('ymin').text)) / 1080

となるとのことでした.

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

*