Edmond Yoo
2018-10-13 23d94e4846bf4ec13069703a28b1d776f4bbe44f
Cleaning & commenting #3 - refactoring constants to Config class
7 files modified
2 files added
3 files deleted
26035 ■■■■■ changed files
config.py 27 ●●●●● patch | view | raw | blame | history
fetch_data.py 36 ●●●● patch | view | raw | blame | history
generate_data.py 24 ●●●● patch | view | raw | blame | history
opencv_dnn.py 14 ●●●● patch | view | raw | blame | history
resize_images.py 7 ●●●●● patch | view | raw | blame | history
setup_train.py 11 ●●●● patch | view | raw | blame | history
test_10.txt 2587 ●●●●● patch | view | raw | blame | history
test_file/frilly_0007.jpg patch | view | raw | blame | history
test_file/hand_of_card_easy.jpg patch | view | raw | blame | history
test_file/test2.mp4 patch | view | raw | blame | history
train_10.txt 23286 ●●●●● patch | view | raw | blame | history
transform_data.py 43 ●●●● patch | view | raw | blame | history
config.py
New file
@@ -0,0 +1,27 @@
import os
class Config:
    # List of all black-bordered cards printed from 8th edition and onwards (8ed and 9ed are white-bordered)
    # Core & expansion sets with 2003 frame
    set_2003_list = ['mrd', 'dst', '5dn', 'chk', 'bok', 'sok', 'rav', 'gpt', 'dis', 'csp', 'tsp', 'plc', 'fut', '10e',
                     'lrw', 'mor', 'shm', 'eve', 'ala', 'con', 'arb', 'm10', 'zen', 'wwk', 'roe', 'm11', 'som', 'mbs',
                     'nph', 'm12', 'isd', 'dka', 'avr', 'm13', 'rtr', 'gtc', 'dgm', 'm14', 'ths', 'bng', 'jou']
    # Core & expansion sets with 2015 frame
    set_2015_list = ['m15', 'ktk', 'frf', 'dtk', 'bfz', 'ogw', 'soi', 'emn', 'kld', 'aer', 'akh', 'hou', 'xln', 'rix',
                     'dom']
    # Box sets
    set_box_list = ['evg', 'drb', 'dd2', 'ddc', 'td0', 'v09', 'ddd', 'h09', 'dde', 'dpa', 'v10', 'ddf', 'td0', 'pd2',
                    'ddg',
                    'cmd', 'v11', 'ddh', 'pd3', 'ddi', 'v12', 'ddj', 'cm1', 'td2', 'ddk', 'v13', 'ddl', 'c13', 'ddm',
                    'md1',
                    'v14', 'ddn', 'c14', 'ddo', 'v15', 'ddp', 'c15', 'ddq', 'v16', 'ddr', 'c16', 'pca', 'dds', 'cma',
                    'c17',
                    'ddt', 'v17', 'ddu', 'cm2', 'ss1', 'gs1', 'c18']
    # Supplemental sets
    set_sup_list = ['hop', 'arc', 'pc2', 'cns', 'cn2', 'e01', 'e02', 'bbd']
    all_set_list = set_2003_list  #+ set_2015_list + set_box_list + set_sup_list
    card_mask_path = os.path.abspath('data/mask.png')
    data_dir = os.path.abspath('/media/win10/data')
    darknet_dir = os.path.abspath('.')
fetch_data.py
@@ -1,35 +1,17 @@
from urllib import request, error
import ast
import json
import os
import pandas as pd
import re
import os
import transform_data
from urllib import request, error
from config import Config
"""
Note: All codes in this file realies on Scryfall API to aggregate card database and their images.
Scryfall API doc is available at: https://scryfall.com/docs/api
"""
# List of all black-bordered cards printed from 8th edition and onwards (8ed and 9ed are white-bordered)
# Core & expansion sets with 2003 frame
set_2003_list = ['mrd', 'dst', '5dn', 'chk', 'bok', 'sok', 'rav', 'gpt', 'dis', 'csp', 'tsp', 'plc', 'fut', '10e',
                 'lrw', 'mor', 'shm', 'eve', 'ala', 'con', 'arb', 'm10', 'zen', 'wwk', 'roe', 'm11', 'som', 'mbs',
                 'nph', 'm12', 'isd', 'dka', 'avr', 'm13', 'rtr', 'gtc', 'dgm', 'm14', 'ths', 'bng', 'jou']
# Core & expansion sets with 2015 frame
set_2015_list = ['m15', 'ktk', 'frf', 'dtk', 'bfz', 'ogw', 'soi', 'emn', 'kld', 'aer', 'akh', 'hou', 'xln', 'rix', 'dom']
# Box sets
set_box_list = ['evg', 'drb', 'dd2', 'ddc', 'td0', 'v09', 'ddd', 'h09', 'dde', 'dpa', 'v10', 'ddf', 'td0', 'pd2', 'ddg',
                'cmd', 'v11', 'ddh', 'pd3', 'ddi', 'v12', 'ddj', 'cm1', 'td2', 'ddk', 'v13', 'ddl', 'c13', 'ddm', 'md1',
                'v14', 'ddn', 'c14', 'ddo', 'v15', 'ddp', 'c15', 'ddq', 'v16', 'ddr', 'c16', 'pca', 'dds', 'cma', 'c17',
                'ddt', 'v17', 'ddu', 'cm2', 'ss1', 'gs1', 'c18']
# Supplemental sets
set_sup_list = ['hop', 'arc', 'pc2', 'cns', 'cn2', 'e01', 'e02', 'bbd']
all_set_list = set_2003_list
def fetch_all_cards_text(url='https://api.scryfall.com/cards/search?q=layout:normal+format:modern+lang:en+frame:2003',
                         csv_name=None):
@@ -113,7 +95,7 @@
    :return:
    """
    if out_dir is None:
        out_dir = '%s/card_img/%s/%s' % (transform_data.data_dir, size, row['set'])
        out_dir = '%s/card_img/%s/%s' % (Config.data_dir, size, row['set'])
    if not os.path.exists(out_dir):
        os.makedirs(out_dir)
@@ -145,8 +127,8 @@
def main():
    # Query card data by each set, then merge them together
    for set_name in all_set_list:
        csv_name = '%s/csv/%s.csv' % (transform_data.data_dir, set_name)
    for set_name in Config.all_set_list:
        csv_name = '%s/csv/%s.csv' % (Config.data_dir, set_name)
        print(csv_name)
        if not os.path.isfile(csv_name):
            df = fetch_all_cards_text(url='https://api.scryfall.com/cards/search?q=set:%s+lang:en' % set_name,
@@ -154,10 +136,10 @@
        else:
            df = load_all_cards_text(csv_name)
        df.sort_values('collector_number')
        fetch_all_cards_image(df, out_dir='%s/card_img/png/%s' % (transform_data.data_dir, set_name))
        fetch_all_cards_image(df, out_dir='%s/card_img/png/%s' % (Config.data_dir, set_name))
    #df = fetch_all_cards_text(url='https://api.scryfall.com/cards/search?q=layout:normal+lang:en+frame:2003',
    #                          csv_name='data/csv/all.csv')
    #                          csv_name='%s/csv/all.csv' % Config.data_dir)
    return
generate_data.py
@@ -1,16 +1,18 @@
from glob import glob
import matplotlib.pyplot as plt
import matplotlib.image as mpimage
import pickle
import math
import random
import os
import cv2
import fetch_data
from glob import glob
import math
import matplotlib.pyplot as plt
import matplotlib.image as mpimage
import numpy as np
import os
import pandas as pd
import pickle
import random
import transform_data
from config import Config
class Backgrounds:
    """
@@ -96,8 +98,8 @@
    #bg.get_random(display=True)
    card_pool = pd.DataFrame()
    for set_name in fetch_data.all_set_list:
        df = fetch_data.load_all_cards_text('data/csv/%s.csv' % set_name)
    for set_name in Config.all_set_list:
        df = fetch_data.load_all_cards_text('%s/csv/%s.csv' % (Config.data_dir, set_name))
        #for _ in range(3):
        #    card_info = df.iloc[random.randint(0, df.shape[0] - 1)]
        #    # Currently ignoring planeswalker cards due to their different card layout
@@ -119,8 +121,8 @@
    '''
    for _, card_info in card_pool.iterrows():
        img_name = '../usb/data/png/%s/%s_%s.png' % (card_info['set'], card_info['collector_number'],
                                                     fetch_data.get_valid_filename(card_info['name']))
        img_name = '%s/card_img/png/%s/%s_%s.png' % (Config.data_dir, card_info['set'], card_info['collector_number'],
                                            fetch_data.get_valid_filename(card_info['name']))
        print(img_name)
        card_img = cv2.imread(img_name)
        if card_img is None:
opencv_dnn.py
@@ -9,8 +9,8 @@
from PIL import Image
import time
from config import Config
import fetch_data
import transform_data
"""
@@ -54,7 +54,7 @@
        for card_name in card_names:
            # Fetch the image - name can be found based on the card's information
            card_info['name'] = card_name
            img_name = '%s/card_img/png/%s/%s_%s.png' % (transform_data.data_dir, card_info['set'],
            img_name = '%s/card_img/png/%s/%s_%s.png' % (Config.data_dir, card_info['set'],
                                                         card_info['collector_number'],
                                                         fetch_data.get_valid_filename(card_info['name']))
            card_img = cv2.imread(img_name)
@@ -62,7 +62,7 @@
            # If the image doesn't exist, download it from the URL
            if card_img is None:
                fetch_data.fetch_card_image(card_info,
                                            out_dir='%s/card_img/png/%s' % (transform_data.data_dir, card_info['set']))
                                            out_dir='%s/card_img/png/%s' % (Config.data_dir, card_info['set']))
                card_img = cv2.imread(img_name)
            if card_img is None:
                print('WARNING: card %s is not found!' % img_name)
@@ -284,7 +284,7 @@
    # Find the contour
    _, cnts, hier = cv2.findContours(img_erode, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
    if len(cnts) == 0:
        print('no contours')
        #print('no contours')
        return []
    # The hierarchy from cv2.findContours() is similar to a tree: each node has an access to the parent, the first child
@@ -343,7 +343,7 @@
        card_set = key[key.find('(') + 1:key.find(')')]
        confidence = sum(val) / f_len
        card_info = card_pool[(card_pool['name'] == card_name) & (card_pool['set'] == card_set)].iloc[0]
        img_name = '%s/card_img/tiny/%s/%s_%s.png' % (transform_data.data_dir, card_info['set'],
        img_name = '%s/card_img/tiny/%s/%s_%s.png' % (Config.data_dir, card_info['set'],
                                                      card_info['collector_number'],
                                                      fetch_data.get_valid_filename(card_info['name']))
        # If the card image is not found, just leave it blank
@@ -542,8 +542,8 @@
    else:
        # Merge database for all cards, then calculate pHash values of each, store them
        df_list = []
        for set_name in fetch_data.all_set_list:
            csv_name = '%s/csv/%s.csv' % (transform_data.data_dir, set_name)
        for set_name in Config.all_set_list:
            csv_name = '%s/csv/%s.csv' % (Config.data_dir, set_name)
            df = fetch_data.load_all_cards_text(csv_name)
            df_list.append(df)
        card_pool = pd.concat(df_list, sort=True)
resize_images.py
@@ -1,11 +1,12 @@
from transform_data import data_dir
from glob import glob
import cv2
from glob import glob
import os
from config import Config
card_size = (63, 88)
for subdir in glob(data_dir + "/card_img/png/*"):
for subdir in glob(Config.data_dir + "/card_img/png/*"):
    split = subdir.split('/')
    split[-2] = 'tiny'
    dir_out = '/'.join(split)
setup_train.py
@@ -1,13 +1,14 @@
import os
from glob import glob
import os
import random
import transform_data
from config import Config
def main():
    random.seed()
    data_list = []
    for subdir in glob('%s/train/*_update' % transform_data.data_dir):
    for subdir in glob('%s/train/*_update' % Config.data_dir):
        for data in glob(subdir + "/*.jpg"):
            data_list.append(os.path.abspath(data))
    random.shuffle(data_list)
@@ -15,10 +16,10 @@
    test_ratio = 0.1
    test_list = data_list[:int(test_ratio * len(data_list))]
    train_list = data_list[int(test_ratio * len(data_list)):]
    with open('%s/train.txt' % transform_data.darknet_dir, 'w') as train_txt:
    with open('%s/train.txt' % Config.darknet_dir, 'w') as train_txt:
        for data in train_list:
            train_txt.write(data + '\n')
    with open('%s/test.txt' % transform_data.darknet_dir, 'w') as test_txt:
    with open('%s/test.txt' % Config.darknet_dir, 'w') as test_txt:
        for data in test_list:
            test_txt.write(data + '\n')
    return
test_10.txt
File was deleted
test_file/frilly_0007.jpg
test_file/hand_of_card_easy.jpg
Binary files differ
test_file/test2.mp4
Binary files differ
train_10.txt
File was deleted
transform_data.py
@@ -1,20 +1,18 @@
import os
import random
import math
import cv2
import numpy as np
import imutils
import pandas as pd
import fetch_data
import generate_data
from shapely import geometry
import imgaug as ia
from imgaug import augmenters as iaa
from imgaug import parameters as iap
import imutils
import math
import numpy as np
import os
import pandas as pd
import random
from shapely import geometry
card_mask = cv2.imread('data/mask.png')
data_dir = os.path.abspath('/media/win10/data')
darknet_dir = os.path.abspath('.')
import fetch_data
import generate_data
from config import Config
def key_pts_to_yolo(key_pts, w_img, h_img):
@@ -104,6 +102,7 @@
        """
        self.check_visibility(visibility=visibility)
        img_result = np.zeros((self.height, self.width, 3), dtype=np.uint8)
        card_mask = cv2.imread(Config.card_mask_path)
        for card in self.cards:
            card_x = int(card.x + 0.5)
@@ -494,15 +493,15 @@
    random.seed()
    ia.seed(random.randrange(10000))
    bg_images = generate_data.load_dtd(dtd_dir='%s/dtd/images' % data_dir, dump_it=False)
    bg_images = generate_data.load_dtd(dtd_dir='%s/dtd/images' % Config.data_dir, dump_it=False)
    background = generate_data.Backgrounds(images=bg_images)
    card_pool = pd.DataFrame()
    for set_name in fetch_data.all_set_list:
        df = fetch_data.load_all_cards_text('%s/csv/%s.csv' % (data_dir, set_name))
    for set_name in Config.all_set_list:
        df = fetch_data.load_all_cards_text('%s/csv/%s.csv' % (Config.data_dir, set_name))
        card_pool = card_pool.append(df)
    class_ids = {}
    with open('%s/obj.names' % data_dir) as names_file:
    with open('%s/obj.names' % Config.data_dir) as names_file:
        class_name_list = names_file.read().splitlines()
        for i in range(len(class_name_list)):
            class_ids[class_name_list[i]] = i
@@ -522,12 +521,14 @@
        # Use 2 to 5 cards per generator
        for _, card_info in card_pool.sample(random.randint(2, 5)).iterrows():
            img_name = '%s/card_img/png/%s/%s_%s.png' % (data_dir, card_info['set'], card_info['collector_number'],
            img_name = '%s/card_img/png/%s/%s_%s.png' % (Config.data_dir, card_info['set'],
                                                         card_info['collector_number'],
                                                         fetch_data.get_valid_filename(card_info['name']))
            out_name += '%s%s_' % (card_info['set'], card_info['collector_number'])
            card_img = cv2.imread(img_name)
            if card_img is None:
                fetch_data.fetch_card_image(card_info, out_dir='%s/card_img/png/%s' % (data_dir, card_info['set']))
                fetch_data.fetch_card_image(card_info, out_dir='%s/card_img/png/%s' % (Config.data_dir,
                                                                                       card_info['set']))
                card_img = cv2.imread(img_name)
            if card_img is None:
                print('WARNING: card %s is not found!' % img_name)
@@ -547,15 +548,15 @@
            if i % 3 == 0:
                generator.generate_non_obstructive()
                generator.export_training_data(visibility=0.0, out_name='%s/train/non_obstructive_update/%s%d'
                                                                        % (data_dir, out_name, j), aug=seq)
                                                                        % (Config.data_dir, out_name, j), aug=seq)
            elif i % 3 == 1:
                generator.generate_horizontal_span(theta=random.uniform(-math.pi, math.pi))
                generator.export_training_data(visibility=0.0, out_name='%s/train/horizontal_span_update/%s%d'
                                                                        % (data_dir, out_name, j), aug=seq)
                                                                        % (Config.data_dir, out_name, j), aug=seq)
            else:
                generator.generate_vertical_span(theta=random.uniform(-math.pi, math.pi))
                generator.export_training_data(visibility=0.0, out_name='%s/train/vertical_span_update/%s%d'
                                                                        % (data_dir, out_name, j), aug=seq)
                                                                        % (Config.data_dir, out_name, j), aug=seq)
            #generator.generate_horizontal_span(theta=random.uniform(-math.pi, math.pi))
            #generator.render(display=True, aug=seq, debug=True)