Skip to content

Instantly share code, notes, and snippets.

@vdalv
Created June 23, 2018 21:52
Show Gist options
  • Save vdalv/7aaf8a090a6111184d6b6438a6847669 to your computer and use it in GitHub Desktop.
Save vdalv/7aaf8a090a6111184d6b6438a6847669 to your computer and use it in GitHub Desktop.
This script reads PascalVOC xml files, and crops the class instances into seperate image files.

Export Class Images from PascalVOC Annotations

This script reads PascalVOC xml files, and crops the class instances into seperate image files.

Note: This script relies on ImageMagick for the crop (convert) functionality. It comes pre-installed on most recent versions of Ubuntu.

Disclaimer: This code is a modified version of Dat Tran's xml_to_csv.py

Example:

Let's say we have this image in our train folder:

And we annotate it like so:

Upon running the script, our train folder now looks like this:

And the class folders (head, leg) contain the following:

crop_classes.py:

import os
import glob
import subprocess
import xml.etree.ElementTree as ET

classes_dict = {}

def crop_classes(path):
    xml_list = []
    for xml_file in glob.glob(path + '/*.xml'):
        tree = ET.parse(xml_file)
        root = tree.getroot()
        for member in root.findall('object'):
            value = (root.find('filename').text,
                     member[0].text,
                     int(member[4][0].text),
                     int(member[4][1].text),
                     int(member[4][2].text),
                     int(member[4][3].text)
                     )
            class_name = member[0].text
            save_folder = path + "/" + class_name
            if not os.path.isdir(save_folder):
                os.makedirs(save_folder)
        
            if not class_name in classes_dict.keys():
                classes_dict[class_name] = 1;

            #http://www.imagemagick.org/Usage/crop/
            #convert -crop {x2 - x1}x{y2 - y1}+{x1}+{y1} {folder_name}/{image_name} {folder_name}/{class_name}/{class_name}-{count}-{image_name}
            call = ['convert', '-crop', str(value[4] - value[2]) + 'x' + str(value[5] - value[3]) + "+" + str(value[2]) + "+" + str(value[3]), path + "/" + value[0], save_folder + "/" + value[1] + "-" + str(classes_dict[class_name]) + "-" + value[0]]
            subprocess.call(call)

            classes_dict[class_name] += 1

def main():
    for folder_name in ['train', 'val']:
        image_path = os.path.join(os.getcwd(), folder_name)
        crop_classes(image_path)
        print('Successfully cropped classes in the ' + folder_name + ' folder.')

main()
@vBoykoGit
Copy link

vBoykoGit commented Jun 25, 2018

I got error "wrong parameter", folders has been created but empty.
Here is output:

Недопустимый параметр: 19x17+10+31
Недопустимый параметр: 18x18+39+31
Недопустимый параметр: 16x12+65+33
Недопустимый параметр: 14x17+86+32
Недопустимый параметр: 11x17+129+32
Недопустимый параметр: 28x17+1470+1
Недопустимый параметр: 26x20+1516+1
Недопустимый параметр: 34x21+1559+1
Недопустимый параметр: 20x20+1564+29
Недопустимый параметр: 22x26+1353+25
Недопустимый параметр: 21x24+1339+27
Недопустимый параметр: 75x20+1064+79
Недопустимый параметр: 193x19+508+148
Недопустимый параметр: 284x32+509+166
Недопустимый параметр: 237x18+507+198
Недопустимый параметр: 179x18+509+131
Недопустимый параметр: 128x18+507+226
Недопустимый параметр: 194x18+507+243
Недопустимый параметр: 273x31+508+262
Недопустимый параметр: 162x19+509+303
Недопустимый параметр: 193x18+508+322
Недопустимый параметр: 139x19+507+339
Недопустимый параметр: 93x19+508+371
Недопустимый параметр: 128x18+508+394
Недопустимый параметр: 230x21+858+133
Недопустимый параметр: 236x21+857+195
Недопустимый параметр: 150x20+858+238
Недопустимый параметр: 107x15+859+258
Недопустимый параметр: 149x17+859+274
Недопустимый параметр: 255x15+859+293
Недопустимый параметр: 204x17+858+319
Недопустимый параметр: 208x18+860+337
Недопустимый параметр: 215x16+859+355
Недопустимый параметр: 205x25+1384+27
Недопустимый параметр: 114x18+144+32
Недопустимый параметр: 96x17+28+139
Недопустимый параметр: 125x18+26+162
Недопустимый параметр: 75x18+26+184
Недопустимый параметр: 96x32+26+208
Недопустимый параметр: 98x33+26+241
Недопустимый параметр: 122x20+26+277
Недопустимый параметр: 159x20+28+300
Недопустимый параметр: 167x17+7+116
Недопустимый параметр: 132x33+24+70
Недопустимый параметр: 309x18+260+97
Недопустимый параметр: 302x25+260+109
Недопустимый параметр: 254x19+579+113
Недопустимый параметр: 273x19+259+79
Недопустимый параметр: 243x20+260+141
Недопустимый параметр: 197x18+260+160
Недопустимый параметр: 428x18+259+177
Недопустимый параметр: 65x17+260+206
Недопустимый параметр: 268x16+260+225
Недопустимый параметр: 192x18+541+223
Недопустимый параметр: 182x18+259+241
Недопустимый параметр: 208x18+455+243
Недопустимый параметр: 125x19+257+270
Недопустимый параметр: 210x15+257+290
Недопустимый параметр: 214x16+484+289
Недопустимый параметр: 122x21+261+315
Недопустимый параметр: 323x21+259+597
Недопустимый параметр: 188x19+599+597
Недопустимый параметр: 188x19+261+615
Недопустимый параметр: 22x22+107+29
Недопустимый параметр: 18x17+1476+1
Недопустимый параметр: 34x23+1513+1
Недопустимый параметр: 36x24+1559+1
Successfully cropped classes in the train folder
Successfully cropped classes in the val folder.

@vBoykoGit
Copy link

Under ubuntu it works well! Thank

@vdalv
Copy link
Author

vdalv commented Jun 26, 2018

Yeah, no problem, man.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment