Belajar Python dan OpenCV- Crop the image by annotation XML

By | January 15, 2021
Print Friendly, PDF & Email
3,069 Views

Sinopsis

Bicara mengenai algoritma Haar Classifier dan Viola Jones yang membutuhkan dataset image, kalian pasti akrab dengan  aplikasi yang digunakan untuk membuat dataset pada kasus image clasification, pasti akan mengenal Image Labeler seperti di Matlab 2017 keatas https://www.mathworks.com/help/vision/ug/define-ground-truth-for-image-collections.html Tapi koq agak berat buat dijalan di netbook kesayangan saya yang tiap hari menemani buat posting artikel serta mempelajari beberapa paper ilmiah. Nah untuk itu bisa kalian bisa gunakan Image-Net menggunakan python lho!

Image-Net

https://en.wikipedia.org/wiki/ImageNet atau www.image-net.org kalian bisa menggunakan  https://github.com/tzutalin/labelImg yang lebih ringan.

Download Zip dan kita akan menemukan file labelImg.py atau bila ingin install langsung bisa ketikan kode seperti biasa python setup.py install, dengan catatan anda sudah sudah directory aktifnya. Karena penulis ingin mencobanya (dengan anaconda3 sudah terinstall sebelumnya serta PyQt5 nya)

conda install pyqt=5
pyrcc5 -o resources.py resources.qrc
python labelImg.py

Yups ternyata bisa juga di run

Nah, itu sebagai pendahuluan saja sebenarnya. Silahkan anda pelajari video tutorialnya sampai pada simpan data data dalam format *.xml Menjadi masalah ketika penulis dikirimi file *.xml dan sayangnya lokasi path yang ada didalam *.xml  berbeda-beda, sehingga ketika penulis menggunakan https://github.com/tzutalin/ImageNet_Utils yaitu kode bbox_helper.py  menjadi tidak bisa digunakan secara maksimal, kode tersebut digunakan untuk membaca file *.xml serta image didalam path nya kedalam folder khusus.
Jangan lupa sebelum  menggunakan semua kode diatas, anda harus install PIL menggunakan pip
pip install PIL
agar bisa menggunakan library Image nya, ternyata sudah diinstal pun masih ada error ModuleNotFoundError: No module named 'Image' kemudian penulis ubah sedikit kode nya  dari import Image menjadi from PIL import Image 
maka tidak ada error lagi, dan masih terjadi error lagi karena kode tersebut tidak membuat folder otomatis, dan masih banyak lagi yang error. Maka penulis kode ulang dengan perubahan sedikit. Berikut kode yang penulis gunakan untuk membaca file *.xml serta membuat croping otomatis kedalam folder penampung (hasil comotan dari kode bbox_helper.py)
# -*- coding: utf-8 -*-
"""
Created on Sun Sep 23 11:23:08 2018

@author: mulkan.ms@gmail.com
www.softscients.web.id
"""
'''
kode untuk membaca file XML hasil imageLabeler
dikarenakan lokasi setiap path pada file xml berbeda-beda
maka dibutuhkan modifikasi kode bbox_helper agar mudah dalam management nya

'''
import os
import xml.etree.ElementTree as ET
from PIL import Image

def scanAnnotationFolder(annotationFolderPath):
    annotationFiles = []
    for root, dirs, files in os.walk(annotationFolderPath):
        for file in files:
            if file.endswith('.xml'):
                annotationFiles.append(os.path.join(root, file))
    return annotationFiles
def BBoxHelper(lokasi_absolut_gambar,file_xml,lokasi_tujuan_gambar,count=0):
    if os.path.exists(lokasi_tujuan_gambar)==False:
        os.mkdir(lokasi_tujuan_gambar)
    xmltree = ET.parse(file_xml)
    filename = xmltree.find('path').text #baca path nya dulu
    filename = os.path.basename(filename) #cari nama file nya
    objects = xmltree.findall('object') #temukan rectangle nya
    rects = []
    for object_iter in objects:
        bndbox = object_iter.find("bndbox")
        rects.append([int(it.text) for it in bndbox])
    
    bbs = []
    lokasi_absolut_gambar = lokasi_absolut_gambar+filename
    if os.path.isfile(lokasi_absolut_gambar):
        im = Image.open(lokasi_absolut_gambar)
        for box in rects:
             bbs.append(im.crop(box))
        
        
        for box in bbs:
            outPath = str(os.path.join(lokasi_tujuan_gambar, filename.split('.')[0] + 
                            '_box' + str(count) +
                            '.'+ filename.split('.')[1]))
            box.save(outPath)
            print ('save to ' + outPath)
            count = count + 1
    else :
        print(file_xml+': tidak ada')
    return count

def MultiBBoxHelper(lokasi_absolut_gambar,folder_xml,lokasi_tujuan_gambar):
    folder = scanAnnotationFolder(folder_xml)
    count = 0
    for file_xml in folder:
        count=BBoxHelper(lokasi_absolut_gambar,file_xml,lokasi_tujuan_gambar,count)
    pass        
lokasi_absolut_gambar = 'E:/NULISLEZAT/PT MSMB/Survey OPT/Padi/Hawar Daun/Hida/'
lokasi_tujuan_gambar = 'hasil croping/'
file_xml = 'data/IMG_20180714_144148.xml' #lokasi file *.xml
#gunakan function ini untuk handle 1 file *.xml
BBoxHelper(lokasi_absolut_gambar,file_xml,lokasi_tujuan_gambar) 
folder_xml = 'data/'  #lokasi folder berisi file *.xml
#gunakan function ini untuk handle multi *.xml dalam  folder
MultiBBoxHelper(lokasi_absolut_gambar,folder_xml,lokasi_tujuan_gambar)

 

Leave a Reply