├── .gitignore ├── LICENSE ├── README.md ├── __init__.py ├── configs ├── matplotlibrc ├── object_counting_aikea.config └── theanorc ├── core ├── __init__.py ├── args.py ├── dp_models.py ├── dp_tools.py ├── image.py ├── image.pyx ├── keras_models.py ├── math_tools.pyx ├── ml.py ├── plot.py ├── setup.py ├── so │ ├── __init__.py │ ├── image.so │ └── math_tools.so └── tools.py ├── data ├── 0_crop.jpg ├── 201306051201363153_crop.jpg ├── 83OzYO-1496387_crop.jpg ├── PhotoGrid_1452852247528_crop.jpg ├── hqdefault_crop.jpg └── synset_words.txt ├── docker ├── keras │ ├── python-2.7 │ │ └── Dockerfile │ └── python-3.4 │ │ └── Dockerfile ├── mongodb │ ├── Dockerfile │ └── docker-entrypoint.sh ├── nvidia-docker ├── opencv │ └── Dockerfile ├── openface │ ├── cudnn │ │ └── Dockerfile │ ├── facenet │ │ └── cudnn │ │ │ └── Dockerfile │ └── python │ │ └── Dockerfile └── pyda │ ├── python-2.7 │ └── Dockerfile │ └── python-3.4 │ ├── Dockerfile │ └── bt │ └── Dockerfile ├── examples ├── images │ └── vgg_filters_broccoli │ │ ├── 0_original.jpg │ │ ├── README.md │ │ ├── convolution2d_01.png │ │ ├── convolution2d_02.png │ │ ├── convolution2d_03.png │ │ ├── convolution2d_04.png │ │ ├── convolution2d_05.png │ │ ├── convolution2d_06.png │ │ ├── convolution2d_07.png │ │ ├── convolution2d_08.png │ │ ├── convolution2d_09.png │ │ ├── convolution2d_10.png │ │ ├── convolution2d_11.png │ │ ├── convolution2d_12.png │ │ └── convolution2d_13.png ├── keras │ ├── conv_filter_visualization.py │ ├── demo_C3D.py │ ├── demo_C3D_2.py │ ├── demo_inception.py │ ├── finetune_vgg.py │ ├── mnist_cnn_bn.py │ ├── mnist_visualize.py │ ├── simple_classifier.py │ ├── squeezenet_demo.py │ ├── vgg_demo.json │ ├── vgg_demo.py │ └── vgg_visualization.py ├── make_scene_better.py ├── ml_example.py ├── openface.json ├── openface_demo.py ├── otd_args.explain.json ├── synset_words.txt └── test_plot.py ├── fonts └── noto │ ├── NotoSansCJKtc-Black.otf │ ├── NotoSansCJKtc-Bold.otf │ ├── NotoSansCJKtc-DemiLight.otf │ ├── NotoSansCJKtc-Light.otf │ ├── NotoSansCJKtc-Medium.otf │ ├── NotoSansCJKtc-Regular.otf │ ├── NotoSansCJKtc-Thin.otf │ ├── NotoSansMonoCJKtc-Bold.otf │ └── NotoSansMonoCJKtc-Regular.otf ├── hypercolumn ├── finetune.py └── main.py ├── models ├── inception-v3.py ├── vgg-16.py └── vgg-19.py ├── openface ├── __init__.py ├── maps │ ├── 6-people-map.txt │ ├── mapping.json │ └── mapping.txt └── oftools.py ├── setdevenv ├── simdat.jpg ├── third-party └── google-images-download.py └── tools ├── convert_folder_names.py ├── download_args.json ├── dump_tf_model.py ├── hdf5_reader.py ├── html_creator.py ├── html_creator_gc.py ├── html_plots.template ├── image_downloader.py ├── pttcrawler.py ├── rename_img_numerical.sh ├── tf ├── download_and_preprocess_imagenet.sh ├── download_imagenet.sh └── dump_inception_v3_filters.py └── untar_imagenet.sh /.gitignore: -------------------------------------------------------------------------------- 1 | facenet_output.csv 2 | tests/openface/examples/facenet_output.csv 3 | pomodoro-cli 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: UTF-8 -*- 3 | 4 | __license__ = """ 5 | Simple Data Analysis Toolset 6 | 7 | ===================================================================== 8 | Copyright (C) 2015- Tammy Yang and others 9 | 10 | This program is free software: you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation, either version 3 of the License, or 13 | (at your option) any later version. 14 | This program is distributed in the hope that it will be useful, 15 | but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | GNU General Public License for more details. 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see . 20 | """ 21 | 22 | print(__license__) 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # simdat 2 | 3 | simdat states for "simple data analysis toolset" and is a simple tool for data analysis and machine learning. 4 | 5 | ## Installation 6 | 7 | * Download the source code 8 | * Add the parent directory to PYTHONPATH 9 | ```shell 10 | $cp simdat/setdevenv . && source setdevenv 11 | ``` 12 | * To use the plotting methods with ssh or docker, copy configs/matplotlibrc to ~/.config/matplotlib/ 13 | 14 | ## Setup 15 | * Include simdat in your python scripts 16 | ```python 17 | from simdat.core import tools, ml, plot 18 | ``` 19 | 20 | ## Architecture 21 | 22 | . 23 | |-- core # Core folder for tooling files 24 | |-- ml.py 25 | |-- plot.py 26 | |-- tools.py 27 | |-- docker # Folder of useful docker files 28 | |-- examples # Files of examples 29 | |-- ml.json 30 | |-- ml_example.py 31 | `-- setdevenv # Can be used for setting PYTHONPATH 32 | 33 | Module structure see [here](https://www.dropbox.com/s/q4mn2p507gksign/simdat.jpg?dl=0) 34 | 35 | ## License 36 | [GNU General Public License](http://www.gnu.org/licenses/) 37 | 38 | ## Author 39 | * Name: Tammy Yang 40 | * Email: tammy@dt42.io 41 | 42 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/__init__.py -------------------------------------------------------------------------------- /configs/matplotlibrc: -------------------------------------------------------------------------------- 1 | backend: agg 2 | -------------------------------------------------------------------------------- /configs/object_counting_aikea.config: -------------------------------------------------------------------------------- 1 | { 2 | "trigger_level": "L3", 3 | "dyda_config": "/etc/dyda/data/trainer.config", 4 | "pipeline_def": [{ 5 | "name": "data_reader", 6 | "component": "data_reader", 7 | "class": "BinaryDataReader", 8 | "output_type": "output_data", 9 | "snapshot": false, 10 | "type": "normal", 11 | "input_type": "package_external_data" 12 | }, 13 | { 14 | "name": "frame_selector", 15 | "component": "frame_selector", 16 | "class": "FrameSelectorDownsampleFirst", 17 | "type": "gate", 18 | "input_type": "use_previous_output", 19 | "dyda_config": { 20 | "interval": 1 21 | } 22 | }, 23 | { 24 | "name": "image_padder", 25 | "component": "image_processor", 26 | "class": "PadImageProcessor", 27 | "type": "normal", 28 | "input_type": "use", 29 | "additional_info": {"input_data": [ 30 | ["data_reader", "output_data"] 31 | ]} 32 | }, 33 | { 34 | "name": "tflite_detector", 35 | "component": "tflite_engine", 36 | "class": "DetectorTFLiteMobileNetSSD", 37 | "print_output": true, 38 | "output_type": "results", 39 | "type": "normal", 40 | "input_type": "use_previous_output", 41 | "dyda_config": { 42 | "model_file": "/usr/share/dlmodels/mobilenet-ssd-coco-tflite-2.0.0/model.tflite", 43 | "label_map": "/usr/share/dlmodels/mobilenet-ssd-coco-tflite-2.0.0/labels.txt", 44 | "num_threads": 3 45 | } 46 | }, 47 | { 48 | "name": "label_determinator", 49 | "component": "determinator", 50 | "class": "DeterminatorTargetLabel", 51 | "type": "normal", 52 | "input_type": "use_previous_results", 53 | "dyda_config": { 54 | "target": "person" 55 | } 56 | }, 57 | { 58 | "name": "unpad_box_processor", 59 | "component": "box_processor", 60 | "class": "UnpadBoxProcessor", 61 | "type": "normal", 62 | "input_type": "append", 63 | "additional_info": {"input_data": [ 64 | ["image_padder", "results"], 65 | ["label_determinator", "results"] 66 | ]} 67 | }, 68 | { 69 | "name": "tracker", 70 | "component": "tracker", 71 | "class": "TrackerSimple", 72 | "type": "normal", 73 | "input_type": "use_previous_results" 74 | }, 75 | { 76 | "name": "roi_determinator", 77 | "component": "determinator", 78 | "class": "DeterminatorByRoi", 79 | "type": "skip", 80 | "dyda_config": { 81 | "use_external_meta": true 82 | }, 83 | "type": "normal", 84 | "input_type": "use_previous_results" 85 | }, 86 | { 87 | "name": "accumulator", 88 | "component": "accumulator", 89 | "class": "AccumulatorObjectNumber", 90 | "type": "normal", 91 | "input_type": "use_previous_results", 92 | "dyda_config": { 93 | "reset_frame_num": -1, 94 | "appear_num_thre": 2 95 | } 96 | }, 97 | { 98 | "name": "tracker_output", 99 | "component": "output_generator", 100 | "class": "OutputGeneratorBehavior", 101 | "type": "normal", 102 | "output_type": "results", 103 | "input_type": "use", 104 | "print_output": false, 105 | "additional_info": {"input_data": [ 106 | ["tracker", "results"] 107 | ]}, 108 | "dyda_config": { 109 | "channel_num": 1 110 | } 111 | }, 112 | { 113 | "name": "counter_output", 114 | "component": "pipeline_comp", 115 | "class": "OutputGeneratorFromMeta", 116 | "type": "normal", 117 | "output_type": "results", 118 | "print_output": false, 119 | "input_type": "use_meta_pairs", 120 | "additional_info": {"comp_key_pairs": [ 121 | ["tracker_output", "timestamp"], 122 | ["tracker_output", "channel_index"], 123 | ["tracker_output", "size"], 124 | ["tracker_output", "annotations"], 125 | ["accumulator", "object_counting"] 126 | ]} 127 | }, 128 | { 129 | "name": "final_json_output", 130 | "component": "data_reader", 131 | "class": "InputDataAsResultsReader", 132 | "type": "output_generator", 133 | "input_type": "use_previous_results", 134 | "output_type": "results", 135 | "snapshot": false, 136 | "print_output": true, 137 | "dyda_config": { 138 | "unpack_single_list": false 139 | } 140 | }, 141 | { 142 | "name": "image_patcher", 143 | "component": "image_processor", 144 | "class": "PatchImageProcessor", 145 | "snapshot": false, 146 | "type": "output_generator", 147 | "input_type": "append", 148 | "output_type": "output_data", 149 | "additional_info": {"input_data": [ 150 | ["data_reader", "output_data"], 151 | ["final_json_output", "results"] 152 | ]}, 153 | "dyda_config": { 154 | "patch_color": [0, 255, 255], 155 | "patch_line_width": 3, 156 | "text_space": -10, 157 | "key_to_patch": ["track_id"] 158 | } 159 | }, 160 | { 161 | "name": "final_img_output", 162 | "component": "image_processor", 163 | "class": "PatchSysInfoImageProcessor", 164 | "dyda_config": { 165 | "patch_color": [255, 0, 0], 166 | "patch_line_width": 6, 167 | "text_space": 30, 168 | "keys_to_patch": ["object_counting"], 169 | "unpack_single_list": false, 170 | "snapshot_with_counter": false, 171 | "company_info": "All right reserved. AIKEA confidential", 172 | "attach_company_info": true, 173 | "patch_external_meta_roi": false 174 | }, 175 | "input_type": "append", 176 | "snapshot": false, 177 | "type": "output_generator", 178 | "output_type": "output_data", 179 | "additional_info": {"input_data": [ 180 | ["image_patcher", "output_data"], 181 | ["image_patcher", "results"] 182 | ]} 183 | } 184 | ] 185 | } 186 | -------------------------------------------------------------------------------- /configs/theanorc: -------------------------------------------------------------------------------- 1 | [global] 2 | floatX = float32 3 | device = gpu0 4 | 5 | [lib] 6 | cnmem = 1 7 | -------------------------------------------------------------------------------- /core/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/core/__init__.py -------------------------------------------------------------------------------- /core/args.py: -------------------------------------------------------------------------------- 1 | import os 2 | from simdat.core import tools 3 | 4 | io = tools.MLIO() 5 | 6 | class Args(object): 7 | def __init__(self, pfs=['ml.json']): 8 | """Init function of Args 9 | 10 | Keyword arguments: 11 | pfs -- profiles to read (default: ['ml.json']) 12 | 13 | """ 14 | self._add_args() 15 | for f in pfs: 16 | self._set_args(f) 17 | self._tune_args() 18 | 19 | def _add_args(self): 20 | """Called by __init__ of Args class""" 21 | pass 22 | 23 | def _tune_args(self): 24 | """Called by __init__ of Args class (after _set_args)""" 25 | pass 26 | 27 | def _set_args(self, f): 28 | """Read parameters from profile 29 | 30 | @param f: profile file 31 | 32 | """ 33 | 34 | if not os.path.isfile(f): 35 | print("[Args] WARNING: File %s does not exist" % f) 36 | return 37 | inparm = io.parse_json(f) 38 | cinst = self.__dict__.keys() 39 | for k in inparm: 40 | if k in cinst: 41 | setattr(self, k, inparm[k]) 42 | 43 | def _print_arg(self, arg, arg_dic): 44 | """Print argument explanation""" 45 | print('[Args] * %s *' % arg) 46 | print('[Args] Description: %s' % arg_dic['des']) 47 | print('[Args] Type: %s' % arg_dic['type']) 48 | print('[Args] Default: %s' % arg_dic['default']) 49 | 50 | def explain_args(self, fname, arg=''): 51 | """Print explanation for args 52 | 53 | @param fname: The json file which includes the explanations 54 | 55 | Keyword Arguments: 56 | arg -- specify the argument to print (default: all) 57 | 58 | """ 59 | intros = io.parse_json(fname) 60 | print('[Args] === Reading explanations from %s.' % fname) 61 | if len(arg) < 1: 62 | for _arg in intros.keys(): 63 | self._print_arg(_arg, intros[_arg]) 64 | else: 65 | self._print_arg(arg, intros[arg]) 66 | -------------------------------------------------------------------------------- /core/dp_models.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import h5py 4 | import numpy as np 5 | import scipy as sp 6 | from collections import OrderedDict 7 | from sklearn import cluster 8 | from simdat.core import image 9 | from simdat.core import ml 10 | from keras import regularizers 11 | from keras.models import Sequential 12 | # from keras.models import Graph 13 | from keras.models import Model 14 | from keras.layers import Input, Activation, merge 15 | from keras.layers import Flatten, Dense, Dropout 16 | from keras.layers import Convolution2D, MaxPooling2D 17 | from keras.layers import ZeroPadding2D 18 | from keras.layers import AveragePooling2D 19 | from keras.utils import np_utils 20 | 21 | 22 | class DP: 23 | def __init__(self): 24 | self.im = image.IMAGE() 25 | self.mlr = ml.MLRun() 26 | self.dp_init() 27 | 28 | def dp_init(self): 29 | """ place holder for child class """ 30 | pass 31 | 32 | def prepare_cifar10_data(self, nb_classes=10): 33 | """ Get Cifar10 data """ 34 | 35 | from keras.datasets import cifar10 36 | (X_train, y_train), (X_test, y_test) = cifar10.load_data() 37 | print('X_train shape:', X_train.shape) 38 | print(X_train.shape[0], 'train samples') 39 | print(X_test.shape[0], 'test samples') 40 | 41 | X_train = X_train.astype('float32') 42 | X_test = X_test.astype('float32') 43 | X_train /= 255 44 | X_test /= 255 45 | 46 | Y_train = np_utils.to_categorical(y_train, nb_classes) 47 | Y_test = np_utils.to_categorical(y_test, nb_classes) 48 | 49 | return X_train, X_test, Y_train, Y_test 50 | 51 | def prepare_mnist_data(self, rows=28, cols=28, nb_classes=10): 52 | """ Get MNIST data """ 53 | 54 | from keras.datasets import mnist 55 | 56 | (X_train, y_train), (X_test, y_test) = mnist.load_data() 57 | 58 | X_train = X_train.reshape(X_train.shape[0], 1, rows, cols) 59 | X_test = X_test.reshape(X_test.shape[0], 1, rows, cols) 60 | X_train = X_train.astype('float32') 61 | X_test = X_test.astype('float32') 62 | X_train /= 255 63 | X_test /= 255 64 | print('X_train shape:', X_train.shape) 65 | print(X_train.shape[0], 'train samples') 66 | print(X_test.shape[0], 'test samples') 67 | 68 | # convert class vectors to binary class matrices 69 | Y_train = np_utils.to_categorical(y_train, nb_classes) 70 | Y_test = np_utils.to_categorical(y_test, nb_classes) 71 | 72 | return X_train, X_test, Y_train, Y_test 73 | 74 | def visualize_model(self, model, to_file='model.png'): 75 | '''Visualize model (work with Keras 1.0)''' 76 | 77 | if type(model) == Sequential or type(model) == Model: 78 | from keras.utils.visualize_util import plot 79 | plot(model, to_file=to_file) 80 | 81 | elif type(model) == Graph: 82 | import pydot 83 | graph = pydot.Dot(graph_type='digraph') 84 | config = model.get_config() 85 | for input_node in config['input_config']: 86 | graph.add_node(pydot.Node(input_node['name'])) 87 | 88 | for layer_config in [config['node_config'], 89 | config['output_config']]: 90 | for node in layer_config: 91 | graph.add_node(pydot.Node(node['name'])) 92 | if node['inputs']: 93 | for e in node['inputs']: 94 | graph.add_edge(pydot.Edge(e, node['name'])) 95 | else: 96 | graph.add_edge(pydot.Edge(node['input'], node['name'])) 97 | 98 | graph.write_png(to_file) 99 | 100 | def extract_hypercolumn(self, model, la_idx, instance): 101 | ''' Extract HyperColumn of pixels (Theano Only) 102 | 103 | @param model: input DP model 104 | @param la_idx: indexes of the layers to be extract 105 | @param instamce: image instance used to extract the hypercolumns 106 | 107 | ''' 108 | import theano 109 | layers = [model.layers[li].get_output(train=False) for li in la_idx] 110 | get_feature = theano.function([model.layers[0].input], layers, 111 | allow_input_downcast=False) 112 | feature_maps = get_feature(instance) 113 | hypercolumns = [] 114 | for convmap in feature_maps: 115 | for fmap in convmap[0]: 116 | upscaled = sp.misc.imresize(fmap, size=(224, 224), 117 | mode="F", interp='bilinear') 118 | hypercolumns.append(upscaled) 119 | return np.asarray(hypercolumns) 120 | 121 | def is_dense(self, layer): 122 | '''Check if the layer is dense (fully connected) 123 | Return layer name if it is a dense layer, None otherwise''' 124 | 125 | layer_name = layer.get_config()['name'] 126 | ltype = layer_name.split('_')[0] 127 | if ltype == 'dense': 128 | return layer_name 129 | return None 130 | 131 | def is_convolutional(self, layer): 132 | '''Check if the layer is convolutional 133 | Return layer name if it is a dense layer, None otherwise''' 134 | 135 | layer_name = layer.get_config()['name'] 136 | ltype = layer_name.split('_')[0] 137 | if ltype.find('convolution') > -1: 138 | return layer_name 139 | return None 140 | 141 | def cluster_hc(self, hc, n_jobs=1): 142 | ''' Use KMeans to cluster hypercolumns''' 143 | 144 | ori_size = hc.shape[1] 145 | new_size = ori_size*ori_size 146 | m = hc.transpose(1, 2, 0).reshape(new_size, -1) 147 | kmeans = cluster.KMeans(n_clusters=2, max_iter=300, n_jobs=n_jobs, 148 | precompute_distances=True) 149 | cluster_labels = kmeans .fit_predict(m) 150 | imcluster = np.zeros((ori_size, ori_size)) 151 | imcluster = imcluster.reshape((new_size,)) 152 | imcluster = cluster_labels 153 | return imcluster.reshape(ori_size, ori_size) 154 | 155 | def prepare_data(self, img_loc, width, height, convert_Y=True, 156 | rc=False, scale=True, classes=None, 157 | sort=False, trans=True): 158 | """ Read images as dp inputs 159 | 160 | @param img_loc: path of the images or a list of image paths 161 | @param width: number rows used to resize the images 162 | @param height: number columns used to resize the images 163 | 164 | Arguments: 165 | rc -- True to random crop the images as four (default: False) 166 | scale -- True to divide input images by 255 (default: True) 167 | classes -- A pre-defined list of class index (default: None) 168 | convert_Y -- True to use np_utils.to_categorical to convert Y 169 | (default: True) 170 | sort -- True to sort the images (default: False) 171 | trans -- True to transport the image from (h, w, c) to (c, h, w) 172 | 173 | """ 174 | 175 | print('[dp_models] width = %i, height = %i' % (width, height)) 176 | if type(img_loc) is list: 177 | imgs = img_loc 178 | else: 179 | imgs = self.im.find_images(dir_path=img_loc) 180 | X = [] 181 | Y = [] 182 | F = [] 183 | create_new_cls = False 184 | if classes is None: 185 | create_new_cls = True 186 | classes = [] 187 | counter = 0 188 | 189 | if rc: 190 | print('[DP] Applying random crop to the image') 191 | if sort: 192 | imgs = sorted(imgs) 193 | for fimg in imgs: 194 | if counter % 1000 == 0: 195 | print('[DP] Reading images: %i' % counter) 196 | _cls_ix = self.mlr.get_class_from_path(fimg) 197 | if _cls_ix not in classes and create_new_cls: 198 | classes.append(_cls_ix) 199 | 200 | if rc: 201 | _img_original = self.im.read_and_random_crop( 202 | fimg, size=(height, width)).values() 203 | else: 204 | _img_original = [self.im.read(fimg, size=(height, width))] 205 | 206 | if _img_original[0] is None: 207 | continue 208 | for c in _img_original: 209 | if trans: 210 | img = c.transpose((2, 0, 1)) 211 | else: 212 | img = c 213 | X.append(img) 214 | Y.append(classes.index(_cls_ix)) 215 | F.append(os.path.basename(fimg)) 216 | counter += 1 217 | fname = str(counter) + '.jpg' 218 | 219 | X = np.array(X).astype('float32') 220 | if scale: 221 | X /= 255 222 | if convert_Y: 223 | Y = np_utils.to_categorical(np.array(Y), len(classes)) 224 | 225 | return np.array(X), np.array(Y), classes, F 226 | 227 | def prepare_data_test(self, img_loc, width, height, 228 | convert_Y=True, trans=True, 229 | scale=True, classes=None, y_as_str=True): 230 | """ Read images as dp inputs 231 | 232 | @param img_loc: path of the images or a list of image paths 233 | @param width: number rows used to resize the images 234 | @param height: number columns used to resize the images 235 | 236 | Arguments: 237 | y_as_str -- True to return Y as a list of class strings 238 | This overwrites convert_Y as False. (default: True) 239 | convert_Y -- True to use np_utils.to_categorical to convert Y 240 | (default: True) 241 | 242 | """ 243 | if y_as_str: 244 | X, Y, classes, F = self.prepare_data( 245 | img_loc, width, height, sort=True, trans=trans, 246 | scale=scale, classes=classes, convert_Y=False) 247 | _Y = [classes[_y] for _y in Y] 248 | return X, _Y, classes, F 249 | X, Y, classes, F = self.prepare_data( 250 | img_loc, width, height, scale=scale, trans=trans, 251 | classes=classes, convert_Y=convert_Y, sort=True) 252 | return X, Y, classes, F 253 | 254 | def prepare_data_train(self, img_loc, width, height, sort=False, 255 | trans=True, test_size=None, rc=False, 256 | scale=True, classes=None): 257 | """ Read images as dp inputs 258 | 259 | @param img_loc: path of the images or a list of image paths 260 | @param width: number rows used to resize the images 261 | @param height: number columns used to resize the images 262 | 263 | Arguments: 264 | 265 | sort -- True to sort the images (default: False) 266 | test_size -- size of the testing sample (default: 0.33) 267 | 268 | """ 269 | 270 | X, Y, classes, F = self.prepare_data( 271 | img_loc, width, height, rc=rc, trans=trans, 272 | scale=scale, classes=classes, sort=sort) 273 | 274 | if type(test_size) is float: 275 | self.mlr.args.test_size = test_size 276 | print('[DP] Changing test_size to %f. The one written in' 277 | 'ml.json will be overwritten!' % test_size) 278 | 279 | X_train, X_test, Y_train, Y_test = self.mlr.split_samples(X, Y) 280 | print('[DP] X_train shape: (%i, %i)' 281 | % (X_train.shape[0], X_train.shape[1])) 282 | print('[DP] Y_train shape: (%i, %i)' 283 | % (Y_train.shape[0], Y_train.shape[1])) 284 | print('[DP] %i train samples' % X_train.shape[0]) 285 | print('[DP] %i test samples' % X_test.shape[0]) 286 | 287 | return X_train, X_test, Y_train, Y_test, classes 288 | 289 | 290 | class DPModel(DP): 291 | def dp_init(self): 292 | """ init called by the DP class """ 293 | self.layers = None 294 | self.dpmodel_init() 295 | 296 | def dpmodel_init(self): 297 | """ place holder for child class """ 298 | pass 299 | 300 | def VGG_16(self, weights_path=None, lastFC=True): 301 | '''VGG-16 model, source from https://goo.gl/qqM88H''' 302 | 303 | self.layers = OrderedDict([ 304 | ('conv1', [ 305 | ZeroPadding2D((1, 1), input_shape=(3, 224, 224)), 306 | Convolution2D(64, 3, 3, activation='relu'), 307 | ZeroPadding2D((1, 1)), 308 | Convolution2D(64, 3, 3, activation='relu'), 309 | MaxPooling2D((2, 2), strides=(2, 2)) 310 | ]), 311 | ('conv2', [ 312 | ZeroPadding2D((1, 1)), 313 | Convolution2D(128, 3, 3, activation='relu'), 314 | ZeroPadding2D((1, 1)), 315 | Convolution2D(128, 3, 3, activation='relu'), 316 | MaxPooling2D((2, 2), strides=(2, 2)) 317 | ]), 318 | ('conv3', [ 319 | ZeroPadding2D((1, 1)), 320 | Convolution2D(256, 3, 3, activation='relu'), 321 | ZeroPadding2D((1, 1)), 322 | Convolution2D(256, 3, 3, activation='relu'), 323 | ZeroPadding2D((1, 1)), 324 | Convolution2D(256, 3, 3, activation='relu'), 325 | MaxPooling2D((2, 2), strides=(2, 2)) 326 | ]), 327 | ('conv4', [ 328 | ZeroPadding2D((1, 1)), 329 | Convolution2D(512, 3, 3, activation='relu'), 330 | ZeroPadding2D((1, 1)), 331 | Convolution2D(512, 3, 3, activation='relu'), 332 | ZeroPadding2D((1, 1)), 333 | Convolution2D(512, 3, 3, activation='relu'), 334 | MaxPooling2D((2, 2), strides=(2, 2)) 335 | ]), 336 | ('conv5', [ 337 | ZeroPadding2D((1, 1)), 338 | Convolution2D(512, 3, 3, activation='relu'), 339 | ZeroPadding2D((1, 1)), 340 | Convolution2D(512, 3, 3, activation='relu'), 341 | ZeroPadding2D((1, 1)), 342 | Convolution2D(512, 3, 3, activation='relu'), 343 | MaxPooling2D((2, 2), strides=(2, 2)) 344 | ]), 345 | ('fc', [ 346 | Flatten(), 347 | Dense(4096, activation='relu'), 348 | Dropout(0.5), 349 | Dense(4096, activation='relu'), 350 | Dropout(0.5), 351 | ]), 352 | ('classify', [ 353 | Dense(1000, activation='softmax') 354 | ]) 355 | ]) 356 | model = Sequential() 357 | for stack in self.layers: 358 | if stack == 'classify' and not lastFC: 359 | print('[DPModels] Skip the last FC layer') 360 | continue 361 | for l in self.layers[stack]: 362 | model.add(l) 363 | 364 | if weights_path: 365 | self.load_weights(model, weights_path, lastFC=lastFC) 366 | 367 | return model 368 | 369 | def load_weights(self, model, weights_path, lastFC=True): 370 | """ Load model weights 371 | 372 | @param model: the model 373 | @param weight_path: path of the weight file 374 | 375 | Arguments: 376 | 377 | lastFC -- True to load weights for the last FC layer (default: True) 378 | 379 | """ 380 | if lastFC: 381 | model.load_weights(weights_path) 382 | return 383 | f = h5py.File(weights_path) 384 | for k in range(f.attrs['nb_layers']): 385 | if k >= len(model.layers): 386 | break 387 | g = f['layer_{}'.format(k)] 388 | weights = [g['param_{}'.format(p)] for p in range(g.attrs['nb_params'])] 389 | model.layers[k].set_weights(weights) 390 | f.close() 391 | return 392 | 393 | def Simple(self, cats, img_row=224, img_col=224, conv_size=3, 394 | colors=3, weights_path=None, filter_size=32): 395 | '''Simple conv model to the best MNIST result. 396 | The input shape should be (n_imgs, colors, img_row, img_col). 397 | 398 | @param cats: total number of final categories 399 | 400 | Arguments: 401 | img_row -- number of rows of the image 402 | img_col -- number of cols of the image 403 | conv_size -- size of the conv window 404 | colors -- colors of the image (3 for RGB) 405 | weights_path -- used for loading the existing model 406 | filter_size -- number of the filters of the first conv layer 407 | 408 | ''' 409 | self.layers = OrderedDict([ 410 | ('conv1', [ 411 | Convolution2D(filter_size, conv_size, conv_size, 412 | activation='relu', border_mode='valid', 413 | input_shape=(colors, img_row, img_col)), 414 | Convolution2D(filter_size*2, conv_size, conv_size, 415 | activation='relu'), 416 | MaxPooling2D((2, 2), strides=(1, 1)), 417 | Dropout(0.25) 418 | ]), 419 | ('fc', [ 420 | Flatten(), 421 | Dense(128, activation='relu'), 422 | Dropout(0.5), 423 | ]), 424 | ('classify', [ 425 | Dense(cats, activation='softmax') 426 | ]) 427 | ]) 428 | model = Sequential() 429 | for stack in self.layers: 430 | for l in self.layers[stack]: 431 | model.add(l) 432 | 433 | if weights_path: 434 | model.load_weights(weights_path) 435 | 436 | return model 437 | 438 | 439 | class ImageNet(image.IMAGE): 440 | def get_labels(self, fname='synset_words.txt'): 441 | '''Get ImageNet labels from file''' 442 | 443 | if not self.check_exist(fname): 444 | print('ERROR: Cannot find %s.' % fname) 445 | sys.exit(1) 446 | return np.loadtxt(fname, str, delimiter='\t') 447 | 448 | def find_topk(self, prob, labels=None, fname='synset_words.txt', ntop=3): 449 | ''' Find the categories with highest probabilities 450 | 451 | @param prob: a list of probabilities of 1,000 categories 452 | 453 | Keyword arguments: 454 | labels -- ImageNet labels (default: re-gain from self.get_labels) 455 | fname -- filename of the ImageNet labels 456 | ntop -- how many top cats to be shown (default: 3) 457 | 458 | @retuen results = {INDEX: (probability, label, [cats])} 459 | example: {955: (0.00051713100401684642, 'n07754684', 460 | ['jackfruit', 'jak', 'jack'])} 461 | 462 | ''' 463 | if labels is None: 464 | labels = self.get_labels(fname) 465 | results = {} 466 | top_k = prob.flatten().argsort()[-1:-(ntop+1):-1] 467 | for k in top_k: 468 | l = labels[k].replace(',', '').split(' ') 469 | results[k] = (prob[k], l[0], l[1:]) 470 | return results 471 | -------------------------------------------------------------------------------- /core/dp_tools.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import h5py 4 | import numpy as np 5 | import scipy as sp 6 | from collections import OrderedDict 7 | from sklearn import cluster 8 | from simdat.core import image 9 | from simdat.core import ml 10 | from keras import regularizers 11 | from keras.models import Sequential 12 | # from keras.models import Graph 13 | from keras.models import Model 14 | from keras.layers import Input, Activation, merge 15 | from keras.layers import Flatten, Dense, Dropout 16 | from keras.layers import Convolution2D, MaxPooling2D 17 | from keras.layers import ZeroPadding2D 18 | from keras.layers import AveragePooling2D 19 | from keras.preprocessing.image import ImageDataGenerator 20 | from keras.utils import np_utils 21 | 22 | 23 | class DP: 24 | def __init__(self): 25 | self.im = image.IMAGE() 26 | self.mlr = ml.MLRun() 27 | self.dp_init() 28 | 29 | def dp_init(self): 30 | """ place holder for child class """ 31 | pass 32 | 33 | def train_data_generator(self, data_dir, img_width, img_height, 34 | class_mode="categorical", batch_size=32, 35 | train_mode=True): 36 | """trturn ImageDataGenerator for training data 37 | 38 | @param data_dir: path of the images 39 | @param img_width: image width 40 | @param img_height: image height 41 | 42 | Arguments: 43 | class_mode -- class mode for y labels, can be "categorical", 44 | "binary", "sparse" (default: categorical) 45 | batch_size -- Batch size (default: 32) 46 | classes -- A pre-defined list of class index (default: None) 47 | convert_Y -- True to use np_utils.to_categorical to convert Y 48 | (default: True) 49 | sort -- True to sort the images (default: False) 50 | trans -- True to transport the image from (h, w, c) to (c, h, w) 51 | 52 | """ 53 | 54 | if train_mode: 55 | datagen = ImageDataGenerator( 56 | rescale=1./255, 57 | shear_range=0.2, 58 | zoom_range=0.2, 59 | horizontal_flip=True) 60 | 61 | else: 62 | datagen = ImageDataGenerator(rescale=1./255) 63 | 64 | generator = datagen.flow_from_directory( 65 | data_dir, 66 | target_size=(img_width, img_height), 67 | batch_size=batch_size, 68 | class_mode=class_mode) 69 | 70 | return generator 71 | 72 | def val_data_generator(self, val_data_dir, img_width, img_height, 73 | class_mode="categorical", batch_size=32): 74 | """return ImageDataGenerator for validation data""" 75 | 76 | return self.train_data_generator( 77 | val_data_dir, img_width, img_height, train_mode=False, 78 | class_mode=class_mode, batch_size=batch_size) 79 | 80 | def prepare_cifar10_data(self, nb_classes=10): 81 | """ Get Cifar10 data """ 82 | 83 | from keras.datasets import cifar10 84 | (X_train, y_train), (X_test, y_test) = cifar10.load_data() 85 | print('X_train shape:', X_train.shape) 86 | print(X_train.shape[0], 'train samples') 87 | print(X_test.shape[0], 'test samples') 88 | 89 | X_train = X_train.astype('float32') 90 | X_test = X_test.astype('float32') 91 | X_train /= 255 92 | X_test /= 255 93 | 94 | Y_train = np_utils.to_categorical(y_train, nb_classes) 95 | Y_test = np_utils.to_categorical(y_test, nb_classes) 96 | 97 | return X_train, X_test, Y_train, Y_test 98 | 99 | def prepare_mnist_data(self, rows=28, cols=28, nb_classes=10): 100 | """ Get MNIST data """ 101 | 102 | from keras.datasets import mnist 103 | 104 | (X_train, y_train), (X_test, y_test) = mnist.load_data() 105 | 106 | X_train = X_train.reshape(X_train.shape[0], 1, rows, cols) 107 | X_test = X_test.reshape(X_test.shape[0], 1, rows, cols) 108 | X_train = X_train.astype('float32') 109 | X_test = X_test.astype('float32') 110 | X_train /= 255 111 | X_test /= 255 112 | print('X_train shape:', X_train.shape) 113 | print(X_train.shape[0], 'train samples') 114 | print(X_test.shape[0], 'test samples') 115 | 116 | # convert class vectors to binary class matrices 117 | Y_train = np_utils.to_categorical(y_train, nb_classes) 118 | Y_test = np_utils.to_categorical(y_test, nb_classes) 119 | 120 | return X_train, X_test, Y_train, Y_test 121 | 122 | def visualize_model(self, model, to_file='model.png'): 123 | '''Visualize model (work with Keras 1.0)''' 124 | 125 | if type(model) == Sequential or type(model) == Model: 126 | from keras.utils.visualize_util import plot 127 | plot(model, to_file=to_file) 128 | 129 | elif type(model) == Graph: 130 | import pydot 131 | graph = pydot.Dot(graph_type='digraph') 132 | config = model.get_config() 133 | for input_node in config['input_config']: 134 | graph.add_node(pydot.Node(input_node['name'])) 135 | 136 | for layer_config in [config['node_config'], 137 | config['output_config']]: 138 | for node in layer_config: 139 | graph.add_node(pydot.Node(node['name'])) 140 | if node['inputs']: 141 | for e in node['inputs']: 142 | graph.add_edge(pydot.Edge(e, node['name'])) 143 | else: 144 | graph.add_edge(pydot.Edge(node['input'], node['name'])) 145 | 146 | graph.write_png(to_file) 147 | 148 | def extract_hypercolumn(self, model, la_idx, instance): 149 | ''' Extract HyperColumn of pixels (Theano Only) 150 | 151 | @param model: input DP model 152 | @param la_idx: indexes of the layers to be extract 153 | @param instamce: image instance used to extract the hypercolumns 154 | 155 | ''' 156 | import theano 157 | layers = [model.layers[li].get_output(train=False) for li in la_idx] 158 | get_feature = theano.function([model.layers[0].input], layers, 159 | allow_input_downcast=False) 160 | feature_maps = get_feature(instance) 161 | hypercolumns = [] 162 | for convmap in feature_maps: 163 | for fmap in convmap[0]: 164 | upscaled = sp.misc.imresize(fmap, size=(224, 224), 165 | mode="F", interp='bilinear') 166 | hypercolumns.append(upscaled) 167 | return np.asarray(hypercolumns) 168 | 169 | def is_dense(self, layer): 170 | '''Check if the layer is dense (fully connected) 171 | Return layer name if it is a dense layer, None otherwise''' 172 | 173 | layer_name = layer.get_config()['name'] 174 | ltype = layer_name.split('_')[0] 175 | if ltype == 'dense': 176 | return layer_name 177 | return None 178 | 179 | def is_convolutional(self, layer): 180 | '''Check if the layer is convolutional 181 | Return layer name if it is a dense layer, None otherwise''' 182 | 183 | layer_name = layer.get_config()['name'] 184 | ltype = layer_name.split('_')[0] 185 | if ltype.find('convolution') > -1: 186 | return layer_name 187 | return None 188 | 189 | def cluster_hc(self, hc, n_jobs=1): 190 | ''' Use KMeans to cluster hypercolumns''' 191 | 192 | ori_size = hc.shape[1] 193 | new_size = ori_size*ori_size 194 | m = hc.transpose(1, 2, 0).reshape(new_size, -1) 195 | kmeans = cluster.KMeans(n_clusters=2, max_iter=300, n_jobs=n_jobs, 196 | precompute_distances=True) 197 | cluster_labels = kmeans .fit_predict(m) 198 | imcluster = np.zeros((ori_size, ori_size)) 199 | imcluster = imcluster.reshape((new_size,)) 200 | imcluster = cluster_labels 201 | return imcluster.reshape(ori_size, ori_size) 202 | 203 | def prepare_data(self, img_loc, width, height, convert_Y=True, 204 | rc=False, scale=True, classes=None, 205 | sort=False, trans=True): 206 | """ Read images as dp inputs 207 | 208 | @param img_loc: path of the images or a list of image paths 209 | @param width: number rows used to resize the images 210 | @param height: number columns used to resize the images 211 | 212 | Arguments: 213 | rc -- True to random crop the images as four (default: False) 214 | scale -- True to divide input images by 255 (default: True) 215 | classes -- A pre-defined list of class index (default: None) 216 | convert_Y -- True to use np_utils.to_categorical to convert Y 217 | (default: True) 218 | sort -- True to sort the images (default: False) 219 | trans -- True to transport the image from (h, w, c) to (c, h, w) 220 | 221 | """ 222 | 223 | print('[dp_models] width = %i, height = %i' % (width, height)) 224 | if type(img_loc) is list: 225 | imgs = img_loc 226 | else: 227 | imgs = self.im.find_images(dir_path=img_loc) 228 | X = [] 229 | Y = [] 230 | F = [] 231 | create_new_cls = False 232 | if classes is None: 233 | create_new_cls = True 234 | classes = [] 235 | counter = 0 236 | 237 | if rc: 238 | print('[DP] Applying random crop to the image') 239 | if sort: 240 | imgs = sorted(imgs) 241 | for fimg in imgs: 242 | if counter % 1000 == 0: 243 | print('[DP] Reading images: %i' % counter) 244 | _cls_ix = self.mlr.get_class_from_path(fimg) 245 | if _cls_ix not in classes and create_new_cls: 246 | classes.append(_cls_ix) 247 | 248 | if rc: 249 | _img_original = self.im.read_and_random_crop( 250 | fimg, size=(height, width)).values() 251 | else: 252 | _img_original = [self.im.read(fimg, size=(height, width))] 253 | 254 | if _img_original[0] is None: 255 | continue 256 | for c in _img_original: 257 | if trans: 258 | img = c.transpose((2, 0, 1)) 259 | else: 260 | img = c 261 | X.append(img) 262 | Y.append(classes.index(_cls_ix)) 263 | F.append(os.path.basename(fimg)) 264 | counter += 1 265 | fname = str(counter) + '.jpg' 266 | 267 | X = np.array(X).astype('float32') 268 | if scale: 269 | X /= 255 270 | if convert_Y: 271 | Y = np_utils.to_categorical(np.array(Y), len(classes)) 272 | 273 | return np.array(X), np.array(Y), classes, F 274 | 275 | def prepare_data_test(self, img_loc, width, height, 276 | convert_Y=True, trans=True, 277 | scale=True, classes=None, y_as_str=True): 278 | """ Read images as dp inputs 279 | 280 | @param img_loc: path of the images or a list of image paths 281 | @param width: number rows used to resize the images 282 | @param height: number columns used to resize the images 283 | 284 | Arguments: 285 | y_as_str -- True to return Y as a list of class strings 286 | This overwrites convert_Y as False. (default: True) 287 | convert_Y -- True to use np_utils.to_categorical to convert Y 288 | (default: True) 289 | 290 | """ 291 | if y_as_str: 292 | X, Y, classes, F = self.prepare_data( 293 | img_loc, width, height, sort=True, trans=trans, 294 | scale=scale, classes=classes, convert_Y=False) 295 | _Y = [classes[_y] for _y in Y] 296 | return X, _Y, classes, F 297 | X, Y, classes, F = self.prepare_data( 298 | img_loc, width, height, scale=scale, trans=trans, 299 | classes=classes, convert_Y=convert_Y, sort=True) 300 | return X, Y, classes, F 301 | 302 | def prepare_data_train(self, img_loc, width, height, sort=False, 303 | trans=True, test_size=None, rc=False, 304 | scale=True, classes=None): 305 | """ Read images as dp inputs 306 | 307 | @param img_loc: path of the images or a list of image paths 308 | @param width: number rows used to resize the images 309 | @param height: number columns used to resize the images 310 | 311 | Arguments: 312 | 313 | sort -- True to sort the images (default: False) 314 | test_size -- size of the testing sample (default: 0.33) 315 | 316 | """ 317 | 318 | X, Y, classes, F = self.prepare_data( 319 | img_loc, width, height, rc=rc, trans=trans, 320 | scale=scale, classes=classes, sort=sort) 321 | 322 | if type(test_size) is float: 323 | self.mlr.args.test_size = test_size 324 | print('[DP] Changing test_size to %f. The one written in' 325 | 'ml.json will be overwritten!' % test_size) 326 | 327 | X_train, X_test, Y_train, Y_test = self.mlr.split_samples(X, Y) 328 | print('[DP] X_train shape: (%i, %i)' 329 | % (X_train.shape[0], X_train.shape[1])) 330 | print('[DP] Y_train shape: (%i, %i)' 331 | % (Y_train.shape[0], Y_train.shape[1])) 332 | print('[DP] %i train samples' % X_train.shape[0]) 333 | print('[DP] %i test samples' % X_test.shape[0]) 334 | 335 | return X_train, X_test, Y_train, Y_test, classes 336 | 337 | 338 | class ImageNet(image.IMAGE): 339 | def get_labels(self, fname='synset_words.txt'): 340 | '''Get ImageNet labels from file''' 341 | 342 | if not self.check_exist(fname): 343 | print('ERROR: Cannot find %s.' % fname) 344 | sys.exit(1) 345 | return np.loadtxt(fname, str, delimiter='\t') 346 | 347 | def find_topk(self, prob, labels=None, fname='synset_words.txt', ntop=3): 348 | ''' Find the categories with highest probabilities 349 | 350 | @param prob: a list of probabilities of 1,000 categories 351 | 352 | Keyword arguments: 353 | labels -- ImageNet labels (default: re-gain from self.get_labels) 354 | fname -- filename of the ImageNet labels 355 | ntop -- how many top cats to be shown (default: 3) 356 | 357 | @retuen results = {INDEX: (probability, label, [cats])} 358 | example: {955: (0.00051713100401684642, 'n07754684', 359 | ['jackfruit', 'jak', 'jack'])} 360 | 361 | ''' 362 | if labels is None: 363 | labels = self.get_labels(fname) 364 | results = {} 365 | top_k = prob.flatten().argsort()[-1:-(ntop+1):-1] 366 | for k in top_k: 367 | l = labels[k].replace(',', '').split(' ') 368 | results[k] = (prob[k], l[0], l[1:]) 369 | return results 370 | -------------------------------------------------------------------------------- /core/math_tools.pyx: -------------------------------------------------------------------------------- 1 | from operator import mul 2 | 3 | 4 | class MathTools(): 5 | def __init__(self): 6 | pass 7 | 8 | def max_size(self, mat, value=0): 9 | """Find pos, h, w of the largest rectangle containing all `value`'s. 10 | For each row solve "Largest Rectangle in a Histrogram" problem [1]: 11 | [1]: http://blog.csdn.net/arbuckle/archive/2006/05/06/710988.aspx 12 | 13 | @param mat: input matrix 14 | 15 | Keyword arguments: 16 | value -- the value to be found in the rectangle 17 | 18 | @return (height, width), (start_y, start_x) 19 | """ 20 | start_row = 0 21 | it = iter(mat) 22 | hist = [(el == value) for el in next(it, [])] 23 | max_size, start_pos = self.max_rectangle_size(hist) 24 | counter = 0 25 | for row in it: 26 | counter += 1 27 | hist = [(1+h) if el == value else 0 for h, el in zip(hist, row)] 28 | _max_size, _start = self.max_rectangle_size(hist) 29 | if self.area(_max_size) > self.area(max_size): 30 | max_size = _max_size 31 | start_pos = _start 32 | start_row = counter 33 | y = start_row - max_size[0] + 1 34 | if max_size[1] == len(hist): 35 | x = 0 36 | else: 37 | x = min(abs(start_pos - max_size[1] + 1), start_pos) 38 | return max_size, (y, x) 39 | 40 | def max_rectangle_size(self, histogram): 41 | """Find height, width of the largest rectangle that fits entirely 42 | under the histogram. Algorithm is "Linear search using a stack of 43 | incomplete subproblems" [1]. 44 | [1]: http://blog.csdn.net/arbuckle/archive/2006/05/06/710988.aspx 45 | """ 46 | from collections import namedtuple 47 | Info = namedtuple('Info', 'start height') 48 | 49 | # Maintain a stack 50 | stack = [] 51 | top = lambda: stack[-1] 52 | max_size = (0, 0) 53 | pos = 0 54 | for pos, height in enumerate(histogram): 55 | # Position where rectangle starts 56 | start = pos 57 | while True: 58 | # If the stack is empty, push 59 | if len(stack) == 0: 60 | stack.append(Info(start, height)) 61 | # If the right bar is higher than the current top, push 62 | elif height > top().height: 63 | stack.append(Info(start, height)) 64 | # Else, calculate the rectangle size 65 | elif stack and height < top().height: 66 | max_size = max(max_size, (top().height, 67 | (pos - top().start)), key=self.area) 68 | start, _ = stack.pop() 69 | continue 70 | # Height == top().height goes here 71 | break 72 | 73 | pos += 1 74 | start_pos = 0 75 | for start, height in stack: 76 | _max_size = (height, (pos - start)) 77 | if self.area(_max_size) > self.area(max_size): 78 | max_size = _max_size 79 | start_pos = start 80 | 81 | return max_size, start_pos 82 | 83 | def area(self, size): 84 | return reduce(mul, size) 85 | 86 | 87 | -------------------------------------------------------------------------------- /core/setup.py: -------------------------------------------------------------------------------- 1 | import glob, os 2 | import shutil 3 | from distutils.core import setup 4 | from Cython.Build import cythonize 5 | 6 | os.chdir("./") 7 | for f in glob.glob("*.c"): 8 | if os.path.exists(f): 9 | print('Deleting %s' % f) 10 | os.remove(f) 11 | fso = os.path.join('so/', f).replace('.c', '.so') 12 | if os.path.exists(fso): 13 | print('Deleting %s' % fso) 14 | os.remove(fso) 15 | setup( 16 | name='simdat', 17 | version='1.1.5', 18 | description='Data analysis tools.', 19 | author='Tammy Yang', 20 | ext_modules = cythonize("./*.pyx"), 21 | ) 22 | 23 | print("Moving simdat/core/*.so to so/") 24 | for f in glob.glob("simdat/core/*.so"): 25 | src = os.path.join(os.getcwd(), f) 26 | if os.path.exists(src): 27 | des = src.replace('simdat/core/simdat/core/', 'simdat/core/so/') 28 | shutil.move(src, des) 29 | -------------------------------------------------------------------------------- /core/so/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/core/so/__init__.py -------------------------------------------------------------------------------- /core/so/image.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/core/so/image.so -------------------------------------------------------------------------------- /core/so/math_tools.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/core/so/math_tools.so -------------------------------------------------------------------------------- /data/0_crop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/data/0_crop.jpg -------------------------------------------------------------------------------- /data/201306051201363153_crop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/data/201306051201363153_crop.jpg -------------------------------------------------------------------------------- /data/83OzYO-1496387_crop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/data/83OzYO-1496387_crop.jpg -------------------------------------------------------------------------------- /data/PhotoGrid_1452852247528_crop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/data/PhotoGrid_1452852247528_crop.jpg -------------------------------------------------------------------------------- /data/hqdefault_crop.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/data/hqdefault_crop.jpg -------------------------------------------------------------------------------- /docker/keras/python-2.7/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM pyda-python2.7 2 | 3 | RUN pip install git+git://github.com/Theano/Theano.git 4 | RUN pip install git+https://github.com/fchollet/keras.git 5 | 6 | EXPOSE 8888 7 | -------------------------------------------------------------------------------- /docker/keras/python-3.4/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM pydata:latest 2 | 3 | RUN pip3 install git+git://github.com/Theano/Theano.git 4 | RUN pip3 install git+https://github.com/fchollet/keras.git 5 | 6 | EXPOSE 8888 7 | -------------------------------------------------------------------------------- /docker/mongodb/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright https://github.com/docker-library/mongo 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | 6 | # http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License. 13 | 14 | FROM ubuntu:14.04 15 | 16 | # add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added 17 | RUN groupadd -r mongodb && useradd -r -g mongodb mongodb 18 | 19 | RUN apt-get update \ 20 | && apt-get install -y --no-install-recommends \ 21 | ca-certificates curl \ 22 | numactl \ 23 | && rm -rf /var/lib/apt/lists/* 24 | 25 | # grab gosu for easy step-down from root 26 | RUN gpg --keyserver ha.pool.sks-keyservers.net --recv-keys B42F6819007F00F88E364FD4036A9C25BF357DD4 27 | RUN curl -o /usr/local/bin/gosu -SL "https://github.com/tianon/gosu/releases/download/1.6/gosu-$(dpkg --print-architecture)" \ 28 | && curl -o /usr/local/bin/gosu.asc -SL "https://github.com/tianon/gosu/releases/download/1.6/gosu-$(dpkg --print-architecture).asc" \ 29 | && gpg --verify /usr/local/bin/gosu.asc \ 30 | && rm /usr/local/bin/gosu.asc \ 31 | && chmod +x /usr/local/bin/gosu 32 | 33 | # pub 4096R/AAB2461C 2014-02-25 [expires: 2016-02-25] 34 | # Key fingerprint = DFFA 3DCF 326E 302C 4787 673A 01C4 E7FA AAB2 461C 35 | # uid MongoDB 2.6 Release Signing Key 36 | # 37 | # pub 4096R/EA312927 2015-10-09 [expires: 2017-10-08] 38 | # Key fingerprint = 42F3 E95A 2C4F 0827 9C49 60AD D68F A50F EA31 2927 39 | # uid MongoDB 3.2 Release Signing Key 40 | # 41 | ENV GPG_KEYS \ 42 | DFFA3DCF326E302C4787673A01C4E7FAAAB2461C \ 43 | 42F3E95A2C4F08279C4960ADD68FA50FEA312927 44 | RUN set -ex \ 45 | && for key in $GPG_KEYS; do \ 46 | apt-key adv --keyserver ha.pool.sks-keyservers.net --recv-keys "$key"; \ 47 | done 48 | 49 | ENV MONGO_MAJOR testing 50 | ENV MONGO_VERSION 3.2.0~rc6 51 | 52 | RUN echo "deb http://repo.mongodb.org/apt/debian wheezy/mongodb-org/$MONGO_MAJOR main" > /etc/apt/sources.list.d/mongodb-org.list 53 | 54 | RUN set -x \ 55 | && apt-get update \ 56 | && apt-get install -y \ 57 | mongodb-org=$MONGO_VERSION \ 58 | mongodb-org-server=$MONGO_VERSION \ 59 | mongodb-org-shell=$MONGO_VERSION \ 60 | mongodb-org-mongos=$MONGO_VERSION \ 61 | mongodb-org-tools=$MONGO_VERSION \ 62 | && rm -rf /var/lib/apt/lists/* \ 63 | && rm -rf /var/lib/mongodb \ 64 | && mv /etc/mongod.conf /etc/mongod.conf.orig 65 | 66 | RUN mkdir -p /data/db && chown -R mongodb:mongodb /data/db 67 | VOLUME /data/db 68 | 69 | COPY docker-entrypoint.sh /entrypoint.sh 70 | ENTRYPOINT ["/entrypoint.sh"] 71 | 72 | EXPOSE 27017 73 | CMD ["mongod"] 74 | -------------------------------------------------------------------------------- /docker/mongodb/docker-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright https://github.com/docker-library/mongo 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | 17 | if [ "${1:0:1}" = '-' ]; then 18 | set -- mongod "$@" 19 | fi 20 | 21 | if [ "$1" = 'mongod' ]; then 22 | chown -R mongodb /data/db 23 | 24 | numa='numactl --interleave=all' 25 | if $numa true &> /dev/null; then 26 | set -- $numa "$@" 27 | fi 28 | 29 | exec gosu mongodb "$@" 30 | fi 31 | 32 | exec "$@" 33 | -------------------------------------------------------------------------------- /docker/nvidia-docker: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # Copyright (c) 2015, NVIDIA CORPORATION. All rights reserved. 3 | 4 | DOCKER=${DOCKER:-"docker"} 5 | 6 | NV_DEVICE="/dev/nvidia" 7 | UVM_DEVICE="${NV_DEVICE}-uvm" 8 | CTL_DEVICE="${NV_DEVICE}ctl" 9 | 10 | CUDA_VERSION_LABEL="com.nvidia.cuda.version" 11 | 12 | NV_BINS_VOLUME="/usr/local/bin" 13 | NV_BINS="nvidia-cuda-mps-control \ 14 | nvidia-cuda-mps-server \ 15 | nvidia-debugdump \ 16 | nvidia-persistenced \ 17 | nvidia-smi" 18 | 19 | NV_LIBS_VOLUME="/usr/local/nvidia" 20 | NV_LIBS_CUDA="cuda \ 21 | nvcuvid \ 22 | nvidia-compiler \ 23 | nvidia-encode \ 24 | nvidia-ml" 25 | 26 | NV_DOCKER_ARGS="" 27 | 28 | __log() 29 | { 30 | local level="$1" 31 | local msg="$2" 32 | 33 | printf "[ NVIDIA ] =$level= $msg\n" >&2 34 | } 35 | 36 | __image_label() 37 | { 38 | local image="$1" 39 | local label="$2" 40 | 41 | echo $( $DOCKER inspect --format="{{index .Config.Labels \"$label\"}}" $image ) 42 | } 43 | 44 | __nvsmi_query() 45 | { 46 | local section="$1" 47 | local gpu_id="$2" # optional 48 | local cmd="nvidia-smi -q" 49 | 50 | if [ $# -eq 2 ]; then 51 | cmd="$cmd -i $gpu_id" 52 | fi 53 | echo $( $cmd | grep "$section" | awk '{print $4}' ) 54 | } 55 | 56 | __library_paths() 57 | { 58 | local lib="$1" 59 | 60 | echo $( ldconfig -p | grep "lib${lib}.so" | awk '{print $4}' ) 61 | } 62 | 63 | __library_arch() 64 | { 65 | local lib="$1" 66 | 67 | echo $( file -L $lib | awk '{print $3}' | cut -d- -f1 ) 68 | } 69 | 70 | __filter_duplicate_paths() 71 | { 72 | local paths="$1" 73 | 74 | local sums="$( md5sum $paths | sed 's/[^/]*$/ &/' )" 75 | local uniq="$( echo "$sums" | uniq -u -f2 | awk '{print $2$3}')" 76 | local dupl="$( echo "$sums" | uniq --all-repeated=separate -f2 \ 77 | | uniq -w 32 | awk 'NF {print $2$3}')" 78 | echo $uniq $dupl 79 | } 80 | 81 | check_prerequisites() 82 | { 83 | local cmds="nvidia-smi nvidia-modprobe" 84 | 85 | for cmd in $cmds; do 86 | command -v $cmd >/dev/null && continue 87 | __log ERROR "Command not found: $cmd" 88 | exit 1 89 | done 90 | } 91 | 92 | parse_docker_args() 93 | { 94 | local args="$1" 95 | local help="$2" 96 | 97 | local shift=1 98 | local skip=0 99 | local non_bool_args="$( $DOCKER help $help | \ 100 | sed '/^\s*\(-[^=]\+\)=[^{true}{false}].*/!d;s//\1/;s/, /\n/' )" 101 | 102 | for arg in $args; do 103 | test $skip -eq 1 && skip=0 && continue 104 | case $arg in 105 | -*) 106 | for nb_arg in $non_bool_args; do 107 | test $arg = $nb_arg && skip=1 && break 108 | done 109 | shift=$((shift+$skip+1)) ;; 110 | *) 111 | return $shift ;; 112 | esac 113 | done 114 | return 0 115 | } 116 | 117 | check_image_version() 118 | { 119 | local image="$1" 120 | local driver_version="$( __nvsmi_query "Driver Version" )" 121 | local cuda_image_version="$( __image_label $image $CUDA_VERSION_LABEL )" 122 | 123 | if [ -z $cuda_image_version ]; then 124 | __log INFO "Not a CUDA image, nothing to be done" 125 | return 1 126 | fi 127 | __log INFO "Driver version: $driver_version" 128 | __log INFO "CUDA image version: $cuda_image_version" 129 | return 0 130 | } 131 | 132 | load_uvm() 133 | { 134 | if [ ! -e $UVM_DEVICE ]; then 135 | nvidia-modprobe -u -c=0 136 | fi 137 | } 138 | 139 | build_docker_args() 140 | { 141 | local args="--device=$CTL_DEVICE --device=$UVM_DEVICE" 142 | 143 | for gpu in $( echo $GPU | tr -s ", " " " ); do 144 | local minor="$( __nvsmi_query "Minor Number" $gpu )" 145 | if [ -z $minor ]; then 146 | __log WARN "Could not find GPU device: $gpu" 147 | continue 148 | fi 149 | args="$args --device=${NV_DEVICE}$minor" 150 | done 151 | 152 | for lib in $NV_LIBS_CUDA; do 153 | local paths="$( __library_paths $lib )" 154 | if [ -z "$paths" ]; then 155 | __log WARN "Could not find library: $lib" 156 | continue 157 | fi 158 | for path in $( __filter_duplicate_paths "$paths" ); do 159 | args="$args -v $path:$path" 160 | case $( __library_arch "$path" ) in 161 | 32) args="$args -v $path:$NV_LIBS_VOLUME/lib/$(basename $path)" ;; 162 | 64) args="$args -v $path:$NV_LIBS_VOLUME/lib64/$(basename $path)" ;; 163 | esac 164 | done 165 | done 166 | 167 | for bin in $NV_BINS; do 168 | local path="$( which $bin )" 169 | if [ -z $path ]; then 170 | __log WARN "Could not find binary: $bin" 171 | continue 172 | fi 173 | args="$args -v $path:$NV_BINS_VOLUME/$bin" 174 | done 175 | 176 | NV_DOCKER_ARGS=$args 177 | } 178 | 179 | print_debug() 180 | { 181 | if [ ! -z $NVDEBUG ]; then 182 | seq -s= 60 | tr -d '[:digit:]' 183 | echo $NV_DOCKER_ARGS | sed 's/-[-v][^/]*//g' | tr ' ' '\n' 184 | seq -s= 60 | tr -d '[:digit:]' 185 | fi 186 | } 187 | 188 | setup() 189 | { 190 | local image="$1" 191 | 192 | check_image_version $image 193 | if [ $? -eq 0 ]; then 194 | build_docker_args 195 | load_uvm 196 | print_debug >&2 197 | fi 198 | echo 199 | } 200 | 201 | check_prerequisites 202 | parse_docker_args "$*"; ret=$? 203 | 204 | DOCKER_ARGS="" 205 | CMD="$( eval echo \$$ret )" 206 | 207 | i=0; while [ $i -lt $ret ]; do 208 | DOCKER_ARGS="$DOCKER_ARGS $1" 209 | i=$((i+1)) 210 | shift 211 | done 212 | 213 | case $CMD in 214 | run|create) 215 | parse_docker_args "$*" $CMD; ret=$? 216 | if [ $ret -gt 0 ]; then 217 | image="$( eval echo \$$ret )" 218 | setup $image 219 | fi 220 | ;; 221 | esac 222 | 223 | $DOCKER $DOCKER_ARGS $NV_DOCKER_ARGS $@ 224 | -------------------------------------------------------------------------------- /docker/opencv/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | MAINTAINER Tammy Yang 3 | 4 | RUN apt-get update && apt-get install -y \ 5 | build-essential \ 6 | cmake \ 7 | curl \ 8 | zip \ 9 | && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 10 | 11 | RUN cd ~ && \ 12 | mkdir -p src && \ 13 | cd src && \ 14 | curl -L https://github.com/Itseez/opencv/archive/2.4.11.zip -o ocv.zip && \ 15 | unzip ocv.zip && \ 16 | cd opencv-2.4.11 && \ 17 | mkdir release && \ 18 | cd release && \ 19 | cmake -D CMAKE_BUILD_TYPE=RELEASE \ 20 | -D CMAKE_INSTALL_PREFIX=/usr/local \ 21 | -D CUDA_GENERATION=Kepler \ 22 | .. && \ 23 | make -j8 && \ 24 | make install 25 | 26 | EXPOSE 9000 27 | 28 | -------------------------------------------------------------------------------- /docker/openface/cudnn/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM pyda:python-2.7 2 | MAINTAINER Brandon Amos 3 | 4 | RUN apt-get update && apt-get install -y \ 5 | cmake \ 6 | curl \ 7 | libatlas-dev \ 8 | libavcodec-dev \ 9 | libavformat-dev \ 10 | libboost-all-dev \ 11 | libgtk2.0-dev \ 12 | libjpeg-dev \ 13 | liblapack-dev \ 14 | libswscale-dev \ 15 | pkg-config \ 16 | && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 17 | 18 | RUN apt-get update && apt-get install -y software-properties-common 19 | RUN curl -s https://raw.githubusercontent.com/torch/ezinstall/master/install-deps | bash -e 20 | RUN git clone https://github.com/torch/distro.git ~/torch --recursive 21 | RUN cd ~/torch && ./install.sh 22 | 23 | RUN ~/torch/install/bin/luarocks install nn 24 | RUN ~/torch/install/bin/luarocks install dpnn 25 | RUN ~/torch/install/bin/luarocks install image 26 | RUN ~/torch/install/bin/luarocks install optim 27 | RUN ~/torch/install/bin/luarocks install csvigo 28 | RUN ~/torch/install/bin/luarocks install cutorch 29 | RUN ~/torch/install/bin/luarocks install cunn 30 | RUN ~/torch/install/bin/luarocks install cudnn 31 | 32 | RUN cd ~ && \ 33 | mkdir -p src && \ 34 | cd src && \ 35 | curl -L \ 36 | https://github.com/davisking/dlib/releases/download/v18.16/dlib-18.16.tar.bz2 \ 37 | -o dlib.tar.bz2 && \ 38 | tar xf dlib.tar.bz2 && \ 39 | cd dlib-18.16/python_examples && \ 40 | mkdir build && \ 41 | cd build && \ 42 | cmake ../../tools/python && \ 43 | cmake --build . --config Release && \ 44 | cp dlib.so .. 45 | 46 | RUN cp /root/src/dlib-18.16/python_examples/build/dlib.so /usr/lib/python2.7/dist-packages/ 47 | 48 | EXPOSE 9000 49 | -------------------------------------------------------------------------------- /docker/openface/facenet/cudnn/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM cudnn:latest 2 | MAINTAINER Tammy Yang 3 | 4 | RUN curl -s https://raw.githubusercontent.com/torch/ezinstall/master/install-deps | bash -e 5 | RUN git clone https://github.com/torch/distro.git ~/torch --recursive 6 | RUN cd ~/torch && ./install.sh 7 | 8 | RUN ~/torch/install/bin/luarocks install nn 9 | RUN ~/torch/install/bin/luarocks install dpnn 10 | RUN ~/torch/install/bin/luarocks install image 11 | RUN ~/torch/install/bin/luarocks install optim 12 | RUN ~/torch/install/bin/luarocks install csvigo 13 | RUN ~/torch/install/bin/luarocks install cutorch 14 | RUN ~/torch/install/bin/luarocks install cunn 15 | RUN ~/torch/install/bin/luarocks install cudnn 16 | 17 | -------------------------------------------------------------------------------- /docker/openface/python/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:14.04 2 | MAINTAINER Tammy Yang 3 | 4 | RUN apt-get update && apt-get install -y \ 5 | build-essential \ 6 | cmake \ 7 | curl \ 8 | gfortran \ 9 | git \ 10 | libatlas-dev \ 11 | libavcodec-dev \ 12 | libavformat-dev \ 13 | libboost-all-dev \ 14 | libgtk2.0-dev \ 15 | libjpeg-dev \ 16 | liblapack-dev \ 17 | libswscale-dev \ 18 | pkg-config \ 19 | python-dev \ 20 | python-pip \ 21 | wget \ 22 | zip \ 23 | && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 24 | 25 | RUN pip2 install numpy scipy pandas 26 | RUN pip2 install scikit-learn scikit-image 27 | 28 | RUN cd ~ && \ 29 | mkdir -p src && \ 30 | cd src && \ 31 | curl -L https://github.com/Itseez/opencv/archive/2.4.11.zip -o ocv.zip && \ 32 | unzip ocv.zip && \ 33 | cd opencv-2.4.11 && \ 34 | mkdir release && \ 35 | cd release && \ 36 | cmake -D CMAKE_BUILD_TYPE=RELEASE \ 37 | -D CMAKE_INSTALL_PREFIX=/usr/local \ 38 | -D CUDA_GENERATION=Kepler \ 39 | .. && \ 40 | make -j8 && \ 41 | make install 42 | 43 | RUN cd ~ && \ 44 | mkdir -p src && \ 45 | cd src && \ 46 | curl -L \ 47 | https://github.com/davisking/dlib/releases/download/v18.16/dlib-18.16.tar.bz2 \ 48 | -o dlib.tar.bz2 && \ 49 | tar xf dlib.tar.bz2 && \ 50 | cd dlib-18.16/python_examples && \ 51 | mkdir build && \ 52 | cd build && \ 53 | cmake ../../tools/python && \ 54 | cmake --build . --config Release && \ 55 | cp dlib.so .. 56 | 57 | EXPOSE 9000 58 | -------------------------------------------------------------------------------- /docker/pyda/python-2.7/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM cudnn:v4 2 | 3 | RUN apt-get update 4 | RUN apt-get upgrade -y 5 | # basic tools 6 | RUN apt-get install -y openssh-server git-core curl wget vim-tiny build-essential python-dev python-setuptools 7 | 8 | # compilers 9 | RUN apt-get install -y gfortran build-essential make gcc build-essential 10 | 11 | # install python 12 | RUN apt-get install -y python2.7 python2.7-dev python-pip 13 | 14 | # python-PIL 15 | RUN apt-get install -y python-pil 16 | RUN apt-get install -y python-httplib2 ipython 17 | RUN apt-get install -y python-numpy python-scipy python-pip 18 | RUN apt-get install -y libatlas-dev libatlas3gf-base 19 | RUN apt-get install -y python-skimage python-matplotlib python-pandas 20 | RUN apt-get install -y python-h5py 21 | RUN pip install scikit-learn 22 | 23 | # install opencv 2.4.12 24 | RUN apt-get install -y cmake 25 | RUN apt-get install -y zip 26 | RUN cd ~ && \ 27 | mkdir -p src && \ 28 | cd src && \ 29 | curl -L https://github.com/Itseez/opencv/archive/2.4.12.zip -o ocv.zip && \ 30 | unzip ocv.zip && \ 31 | cd opencv-2.4.12 && \ 32 | mkdir release && \ 33 | cd release && \ 34 | cmake -D CMAKE_BUILD_TYPE=RELEASE \ 35 | -D CMAKE_INSTALL_PREFIX=/usr/local \ 36 | -D BUILD_PYTHON_SUPPORT=ON \ 37 | .. && \ 38 | make -j8 && \ 39 | make install 40 | 41 | RUN sh -c 'echo "/usr/local/lib" > /etc/ld.so.conf.d/opencv.conf' 42 | RUN ldconfig 43 | 44 | EXPOSE 8888 45 | -------------------------------------------------------------------------------- /docker/pyda/python-3.4/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:15.04 2 | 3 | #RUN echo "deb ftp://mirror.hetzner.de/ubuntu/packages precise main restricted universe multiverse" > /etc/apt/sources.list 4 | RUN apt-get update 5 | RUN apt-get upgrade -y 6 | 7 | # basic tools 8 | RUN apt-get install -y openssh-server git-core curl wget vim-tiny build-essential python3-dev python3-setuptools 9 | 10 | # compilers 11 | RUN apt-get install -y gfortran build-essential make gcc build-essential 12 | 13 | # install python 14 | RUN apt-get install -y python3.4 python3.4-dev python3-pip 15 | 16 | # python-PIL 17 | RUN apt-get install -y python3-pil 18 | RUN apt-get install -y python3-httplib2 ipython3 19 | RUN apt-get install -y python3-numpy python3-scipy python3-pip python3-scipy 20 | RUN apt-get install -y libatlas-dev libatlas3gf-base 21 | RUN apt-get install -y python3-skimage python3-matplotlib python3-pandas 22 | RUN apt-get install -y python3-h5py 23 | RUN apt-get install -y python-opencv 24 | RUN pip3 install scikit-learn 25 | 26 | EXPOSE 8888 27 | -------------------------------------------------------------------------------- /docker/pyda/python-3.4/bt/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM pyda:latest 2 | 3 | RUN pip3 install bt 4 | 5 | EXPOSE 8888 6 | 7 | -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/0_original.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/0_original.jpg -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/README.md: -------------------------------------------------------------------------------- 1 | ![](0_original.jpg) 2 | ![](convolution2d_01.png) 3 | ![](convolution2d_02.png) 4 | ![](convolution2d_03.png) 5 | ![](convolution2d_04.png) 6 | ![](convolution2d_05.png) 7 | ![](convolution2d_06.png) 8 | ![](convolution2d_07.png) 9 | ![](convolution2d_08.png) 10 | ![](convolution2d_09.png) 11 | ![](convolution2d_10.png) 12 | ![](convolution2d_11.png) 13 | ![](convolution2d_12.png) 14 | ![](convolution2d_13.png) 15 | -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_01.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_02.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_03.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_04.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_05.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_06.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_07.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_08.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_09.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_10.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_11.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_12.png -------------------------------------------------------------------------------- /examples/images/vgg_filters_broccoli/convolution2d_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/examples/images/vgg_filters_broccoli/convolution2d_13.png -------------------------------------------------------------------------------- /examples/keras/conv_filter_visualization.py: -------------------------------------------------------------------------------- 1 | '''Visualization of the filters of VGG16, via gradient ascent in input space. 2 | 3 | This script can run on CPU in a few minutes (with the TensorFlow backend). 4 | 5 | Results example: http://i.imgur.com/4nj4KjN.jpg 6 | 7 | Before running this script, download the weights for the VGG16 model at: 8 | https://drive.google.com/file/d/0Bz7KyqmuGsilT0J5dmRCM0ROVHc/view?usp=sharing 9 | (source: https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3) 10 | and make sure the variable `weights_path` in this script matches the location of the file. 11 | ''' 12 | from __future__ import print_function 13 | from scipy.misc import imsave 14 | import numpy as np 15 | import time 16 | import os 17 | import h5py 18 | from simdat.core import dp_models 19 | from keras.models import Sequential 20 | from keras.layers import Convolution2D, ZeroPadding2D, MaxPooling2D 21 | from keras import backend as K 22 | 23 | dp = dp_models.DPModel() 24 | # dimensions of the generated pictures for each filter. 25 | img_width = 224 26 | img_height = 224 27 | # img_width = 128 28 | # img_height = 128 29 | 30 | # path to the model weights file. 31 | weights_path = '/home/tammy/www/vgg-16/vgg16_weights.h5' 32 | 33 | # the name of the layer we want to visualize (see model definition below) 34 | output_index = 65 35 | 36 | # util function to convert a tensor into a valid image 37 | def deprocess_image(x): 38 | # normalize tensor: center on 0., ensure std is 0.1 39 | x -= x.mean() 40 | x /= (x.std() + 1e-5) 41 | x *= 0.1 42 | 43 | # clip to [0, 1] 44 | x += 0.5 45 | x = np.clip(x, 0, 1) 46 | 47 | # convert to RGB array 48 | x *= 255 49 | x = x.transpose((1, 2, 0)) 50 | x = np.clip(x, 0, 255).astype('uint8') 51 | return x 52 | 53 | # build the VGG16 network 54 | model = dp.VGG_16(weights_path=weights_path) 55 | model.summary() 56 | input_img = model.layers[0].input 57 | # this is a placeholder tensor that will contain our generated images 58 | print('Model loaded.') 59 | 60 | 61 | def normalize(x): 62 | # utility function to normalize a tensor by its L2 norm 63 | return x / (K.sqrt(K.mean(K.square(x))) + 1e-5) 64 | 65 | 66 | kept_filters = [] 67 | start_time = time.time() 68 | 69 | layer_output = model.layers[-5].output 70 | loss = K.mean(layer_output[:, output_index]) 71 | 72 | # we compute the gradient of the input picture wrt this loss 73 | grads = K.gradients(loss, input_img)[0] 74 | 75 | # normalization trick: we normalize the gradient 76 | grads = normalize(grads) 77 | 78 | # this function returns the loss and grads given the input picture 79 | # Keras.backend.function(inputs, outputs) 80 | # inputs: list of placeholder/variable tensors. 81 | # outputs: list of output tensors. 82 | iterate = K.function([input_img], [loss, grads]) 83 | 84 | # step size for gradient ascent 85 | step = 1. 86 | 87 | # we start from a gray image with some random noise 88 | # input_img_data = np.random.random((1, 3, img_width, img_height)) * 20 + 128. 89 | input_img_data = np.random.random((1, 3, img_width, img_height)) * 20 + 224. 90 | 91 | # we run gradient ascent for 20 steps 92 | for i in range(20): 93 | loss_value, grads_value = iterate([input_img_data]) 94 | input_img_data += grads_value * step 95 | 96 | print('Current loss value:', loss_value) 97 | if loss_value <= 0.: 98 | # some filters get stuck to 0, we can skip them 99 | break 100 | 101 | # decode the resulting input image 102 | if loss_value > 0: 103 | img = deprocess_image(input_img_data[0]) 104 | end_time = time.time() 105 | print('Processed in %ds' % (end_time - start_time)) 106 | 107 | # save the result to disk 108 | imsave('stitched_filters.png', img) 109 | -------------------------------------------------------------------------------- /examples/keras/demo_C3D.py: -------------------------------------------------------------------------------- 1 | ''' Original Model/Weights/Sources from https://goo.gl/b8hPpu''' 2 | import os 3 | import cv2 4 | import time 5 | import numpy as np 6 | import argparse 7 | from simdat.core import plot 8 | from simdat.core import dp_models 9 | from simdat.core import tools 10 | from keras.models import model_from_json 11 | 12 | 13 | def main(): 14 | parser = argparse.ArgumentParser( 15 | description="Demo Sports 1M C3D Network on Keras" 16 | ) 17 | parser.add_argument( 18 | "--model-loc", type=str, default=os.getcwd(), dest='ofolder', 19 | help="Path of the folder to output or to load the model." 20 | ) 21 | parser.add_argument( 22 | "-p", "--path", type=str, default=None, required=True, 23 | help="Path of the video." 24 | ) 25 | parser.add_argument( 26 | "--img-width", type=int, default=128, dest='width', 27 | help="Rows of the images, default: 128." 28 | ) 29 | parser.add_argument( 30 | "--img-height", type=int, default=171, dest='height', 31 | help="Columns of the images, default: 171." 32 | ) 33 | 34 | t0 = time.time() 35 | tl = tools.TOOLS() 36 | pl = plot.PLOT() 37 | mdls = dp_models.DPModel() 38 | args = parser.parse_args() 39 | path_model = os.path.join(args.ofolder, 'model.json') 40 | path_weights = os.path.join(args.ofolder, 'weights.h5') 41 | path_label = os.path.join(args.ofolder, 'labels.txt') 42 | t0 = tl.print_time(t0, 'init') 43 | 44 | model = model_from_json(open(path_model).read()) 45 | model.load_weights(path_weights) 46 | print(model.summary()) 47 | t0 = tl.print_time(t0, 'load model') 48 | model.compile(loss='mean_squared_error', optimizer='sgd') 49 | t0 = tl.print_time(t0, 'compile model') 50 | 51 | with open(path_label, 'r') as f: 52 | labels = [line.strip() for line in f.readlines()] 53 | print('Total labels: {}'.format(len(labels))) 54 | 55 | X_test, Y_test, classes, F = mdls.prepare_data_test( 56 | args.path, args.width, args.height, trans=False, scale=False) 57 | t0 = tl.print_time(t0, 'load data') 58 | 59 | # c x l x h x w where c is the number of 60 | # channels, l is length in number of frames, h and w are the 61 | # height and width of the frame 62 | # Original shape = (16, 3, 122, 122) 63 | # New shape = (3, 16, 122, 122) 64 | results = [] 65 | detected_lbs = {} 66 | for i in range(0, X_test.shape[0]-16): 67 | X = X_test[i:i+16, 8:120, 30:142, :].transpose((3, 0, 1, 2)) 68 | output = model.predict_on_batch(np.array([X])) 69 | # iframe = int(F[i].split('.')[0].split('_')[1]) 70 | iframe = int(F[i].split('.')[0].split('-')[1]) 71 | pos_max = output[0].argmax() 72 | results.append(pos_max) 73 | if pos_max not in detected_lbs: 74 | detected_lbs[pos_max] = labels[pos_max] 75 | 76 | pl.plot(results, xlabel='Frame', ylabel='Detected Sport') 77 | print(detected_lbs) 78 | t0 = tl.print_time(t0, 'predict') 79 | 80 | if __name__ == '__main__': 81 | main() 82 | -------------------------------------------------------------------------------- /examples/keras/demo_C3D_2.py: -------------------------------------------------------------------------------- 1 | ''' Original Model/Weights/Sources from https://goo.gl/b8hPpu''' 2 | import os 3 | import cv2 4 | import time 5 | import numpy as np 6 | import argparse 7 | from cv2 import imread 8 | from cv2 import resize 9 | from keras.models import model_from_json 10 | 11 | 12 | def check_ext(file_name, extensions): 13 | """Check the file extension 14 | 15 | @param file_name: input file name 16 | @param extensions: string or list, extension(s) to check 17 | 18 | @return bool: True if it is matched 19 | 20 | """ 21 | if file_name.endswith(extensions): 22 | return True 23 | return False 24 | 25 | 26 | def find_files(dir_path=None, keyword=None, suffix=('.json')): 27 | """Find files under a directory 28 | 29 | Keyword arguments: 30 | dir_path -- path of the directory to check (default: '.') 31 | keyword -- keyword used to filter files (default: None) 32 | suffix -- file extensions to be selected (default: ('.json')) 33 | 34 | @return output: a list of file paths found 35 | 36 | """ 37 | if dir_path is None: 38 | dir_path = os.getcwd() 39 | output = [] 40 | for dirPath, dirNames, fileNames in os.walk(dir_path): 41 | dirmatch = False 42 | if keyword is not None and dirPath.find(keyword) > 0: 43 | dirmatch = True 44 | for f in fileNames: 45 | if keyword is not None and dirPath.find(keyword) < 0: 46 | if not dirmatch: 47 | continue 48 | if check_ext(f, suffix): 49 | output.append(os.path.join(dirPath, f)) 50 | return output 51 | 52 | 53 | def find_images(dir_path=None, keyword=None): 54 | """Find images under a directory 55 | 56 | Keyword arguments: 57 | dir_path -- path of the directory to check (default: '.') 58 | keyword -- keyword used to filter images (default: None) 59 | 60 | @return output: a list of images found 61 | 62 | """ 63 | 64 | if dir_path is not None and os.path.isfile(dir_path): 65 | return [dir_path] 66 | return find_files(dir_path=dir_path, keyword=keyword, 67 | suffix=('.jpg', 'png', '.JPEG')) 68 | 69 | 70 | def read(fimg, size=None): 71 | """Read image 72 | 73 | @param fimg: input image file name 74 | 75 | Keyword arguments: 76 | size -- tuple of new size in (height, width) 77 | 78 | """ 79 | 80 | img = imread(fimg) 81 | if img is None: 82 | print("[IMAGE] Error reading file %s" % fimg) 83 | return img 84 | if size is not None: 85 | img = resize(img, size) 86 | 87 | return img 88 | 89 | 90 | def prepare_data(img_loc, width, height, sort=False): 91 | """ Read images as dp inputs 92 | 93 | @param img_loc: path of the images or a list of image paths 94 | @param width: number rows used to resize the images 95 | @param height: number columns used to resize the images 96 | 97 | Arguments: 98 | sort -- True to sort the images (default: False) 99 | 100 | """ 101 | 102 | print('Width = %i, Height = %i' % (width, height)) 103 | if type(img_loc) is list: 104 | imgs = img_loc 105 | else: 106 | imgs = find_images(dir_path=img_loc) 107 | X = [] 108 | 109 | if sort: 110 | imgs = sorted(imgs) 111 | for fimg in imgs: 112 | _img_original = [read(fimg, size=(height, width))] 113 | if _img_original[0] is None: 114 | continue 115 | for c in _img_original: 116 | X.append(c) 117 | 118 | X = np.array(X).astype('float32') 119 | return np.array(X) 120 | 121 | 122 | def main(): 123 | parser = argparse.ArgumentParser( 124 | description="Demo Sports 1M C3D Network on Keras" 125 | ) 126 | parser.add_argument( 127 | "--model-loc", type=str, default=os.getcwd(), dest='ofolder', 128 | help="Path of the folder to output or to load the model." 129 | ) 130 | parser.add_argument( 131 | "-p", "--path", type=str, default=None, required=True, 132 | help="Path of the video." 133 | ) 134 | parser.add_argument( 135 | "--img-width", type=int, default=128, dest='width', 136 | help="Rows of the images, default: 128." 137 | ) 138 | parser.add_argument( 139 | "--img-height", type=int, default=171, dest='height', 140 | help="Columns of the images, default: 171." 141 | ) 142 | 143 | t0 = time.time() 144 | args = parser.parse_args() 145 | 146 | path_model = os.path.join(args.ofolder, 'model.json') 147 | path_weights = os.path.join(args.ofolder, 'weights.h5') 148 | path_label = os.path.join(args.ofolder, 'labels.txt') 149 | 150 | model = model_from_json(open(path_model).read()) 151 | model.load_weights(path_weights) 152 | print(model.summary()) 153 | model.compile(loss='mean_squared_error', optimizer='sgd') 154 | 155 | with open(path_label, 'r') as f: 156 | labels = [line.strip() for line in f.readlines()] 157 | print('Total labels: {}'.format(len(labels))) 158 | 159 | X_test = prepare_data( 160 | args.path, args.width, args.height, sort=True) 161 | 162 | results = [] 163 | detected_lbs = {} 164 | for i in range(0, X_test.shape[0]-16): 165 | X = X_test[i:i+16, 8:120, 30:142, :].transpose((3, 0, 1, 2)) 166 | output = model.predict_on_batch(np.array([X])) 167 | pos_max = output[0].argmax() 168 | results.append(pos_max) 169 | if pos_max not in detected_lbs: 170 | detected_lbs[pos_max] = labels[pos_max] 171 | 172 | print(detected_lbs) 173 | 174 | if __name__ == '__main__': 175 | main() 176 | -------------------------------------------------------------------------------- /examples/keras/demo_inception.py: -------------------------------------------------------------------------------- 1 | from simdat.core import dp_models 2 | dp = dp_models.DPModel() 3 | model = dp.Inception_v3() 4 | print(model.summary()) 5 | # model.compile('rmsprop', 'categorical_crossentropy') 6 | -------------------------------------------------------------------------------- /examples/keras/finetune_vgg.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import argparse 4 | import numpy as np 5 | from random import shuffle 6 | from simdat.core import dp_models 7 | from simdat.core import image 8 | from simdat.core import tools 9 | from keras.optimizers import SGD 10 | from keras.layers.core import Dense, Activation 11 | from keras.models import model_from_json 12 | from keras.utils import np_utils 13 | from keras.preprocessing.image import ImageDataGenerator 14 | 15 | 16 | def add_traiining_args(train_parser): 17 | train_parser.add_argument( 18 | "-v", "--vgg-weights", type=str, dest='weights', 19 | default='/home/tammy/SOURCES/keras/examples/vgg16_weights.h5', 20 | help="Path of vgg weights" 21 | ) 22 | train_parser.add_argument( 23 | "--model-loc", type=str, default=os.getcwd(), dest='ofolder', 24 | help="Path of the folder to output or to load the model." 25 | ) 26 | train_parser.add_argument( 27 | "--batch-size", type=int, default=80, dest='batchsize', 28 | help="Size of the mini batch. Default: 80." 29 | ) 30 | train_parser.add_argument( 31 | "--epochs", type=int, default=20, 32 | help="Number of epochs, default 20." 33 | ) 34 | train_parser.add_argument( 35 | "--lr", type=float, default=0.001, 36 | help="Learning rate of SGD, default 0.001." 37 | ) 38 | train_parser.add_argument( 39 | "--lr-decay", type=float, default=1e-6, dest='lrdecay', 40 | help="Decay of SGD lr, default 1e-6." 41 | ) 42 | train_parser.add_argument( 43 | "--momentum", type=float, default=0.9, 44 | help="Momentum of SGD lr, default 0.9." 45 | ) 46 | group = train_parser.add_mutually_exclusive_group() 47 | group.add_argument( 48 | "--rc", default=False, action='store_true', 49 | help="Randomly crop the images (default: False)." 50 | ) 51 | group.add_argument( 52 | "--augmentation", default=False, action='store_true', 53 | help="True to use ImageDataGenerator." 54 | ) 55 | 56 | 57 | def print_precision_recall(precision, recall, total): 58 | for item in precision: 59 | print('[finetune_vgg] Item %s' % item) 60 | if recall[item] == 0: 61 | p = -1 62 | else: 63 | p = float(precision[item])/float(recall[item]) 64 | if item in total and total[item] != 0: 65 | r = float(precision[item])/float(total[item]) 66 | else: 67 | r = -1 68 | print('[finetune_vgg] precision = %.2f' % p) 69 | print('[finetune_vgg] recall = %.2f' % r) 70 | 71 | 72 | def add_prediction_args(predict_parser): 73 | predict_parser.add_argument( 74 | "--model-loc", type=str, default=os.getcwd(), dest='ofolder', 75 | help="Path of the folder to output or to load the model." 76 | ) 77 | predict_parser.add_argument( 78 | "--batch-size", type=int, default=80, dest='batchsize', 79 | help="Size of the mini batch. Default: 80." 80 | ) 81 | predict_parser.add_argument( 82 | "--input", type=str, default=None, 83 | help="Input image to be predicted, this overwrites --path option." 84 | ) 85 | predict_parser.add_argument( 86 | "--threshold", type=float, default=0.0, 87 | help="Threshold applied to judge whether it is identified correctly." 88 | ) 89 | predict_parser.add_argument( 90 | "--output-loc", type=str, dest='output_loc', 91 | default='/home/tammy/www/prediction.json', 92 | help="Path to store the prediction results." 93 | ) 94 | predict_parser.add_argument( 95 | "--cm", default=False, action='store_true', 96 | help="Draw confusion matrix." 97 | ) 98 | 99 | 100 | def main(): 101 | parser = argparse.ArgumentParser( 102 | description="Use Simple model to train a classifier." 103 | ) 104 | subparsers = parser.add_subparsers( 105 | help='commands', dest='sbp_name' 106 | ) 107 | parser.add_argument( 108 | "-p", "--path", type=str, default='.', 109 | help="Path where the images are. Default: $PWD." 110 | ) 111 | parser.add_argument( 112 | "--img-width", type=int, default=224, dest='width', 113 | help="Rows of the images, default: 224." 114 | ) 115 | parser.add_argument( 116 | "--img-height", type=int, default=224, dest='height', 117 | help="Columns of the images, default: 224." 118 | ) 119 | parser.add_argument( 120 | "--seed", type=int, default=1337, 121 | help="Random seed, default: 1337." 122 | ) 123 | 124 | predict_parser = subparsers.add_parser( 125 | "predict", help='Predict the images.' 126 | ) 127 | add_prediction_args(predict_parser) 128 | 129 | batch_train_parser = subparsers.add_parser( 130 | "batch-train", help='Command to train with batches.' 131 | ) 132 | add_traiining_args(batch_train_parser) 133 | batch_train_parser.add_argument( 134 | "--size", type=int, default=5000, 135 | help="Size of the image batch (default: 5,000)" 136 | ) 137 | 138 | finetune_parser = subparsers.add_parser( 139 | "train", help='Command to finetune the images.' 140 | ) 141 | add_traiining_args(finetune_parser) 142 | 143 | crop_parser = subparsers.add_parser( 144 | "augmentation", help='Generate scroped images.' 145 | ) 146 | 147 | t0 = time.time() 148 | tl = tools.DATA() 149 | simdat_im = image.IMAGE() 150 | mdls = dp_models.DPModel() 151 | 152 | args = parser.parse_args() 153 | np.random.seed(args.seed) 154 | 155 | if args.sbp_name in ['train', 'predict', 'batch-train']: 156 | tl.check_dir(args.ofolder) 157 | path_model = os.path.join(args.ofolder, 'model.json') 158 | path_weights = os.path.join(args.ofolder, 'weights.h5') 159 | path_cls = os.path.join(args.ofolder, 'classes.json') 160 | 161 | if args.sbp_name == 'batch-train': 162 | imgs = simdat_im.find_images(dir_path=args.path) 163 | classes = simdat_im.find_folders(dir_path=args.path) 164 | 165 | model = mdls.VGG_16(args.weights, lastFC=False) 166 | sgd = SGD(lr=args.lr, decay=args.lrdecay, 167 | momentum=args.momentum, nesterov=True) 168 | print('[finetune_vgg] lr = %f, decay = %f, momentum = %f' 169 | % (args.lr, args.lrdecay, args.momentum)) 170 | 171 | print('[finetune_vgg] Adding Dense(nclasses, activation=softmax).') 172 | model.add(Dense(len(classes), activation='softmax')) 173 | model.compile(optimizer=sgd, loss='categorical_crossentropy') 174 | t0 = tl.print_time(t0, 'compile the model to be fine tuned.') 175 | 176 | shuffle(imgs) 177 | for e in range(args.epochs): 178 | print("[finetune_vgg] Epoch %d/%d" % (e+1, args.epochs)) 179 | for i in range(len(imgs)/args.size + 1): 180 | start = i*args.size 181 | end = ((i + 1)*args.size) 182 | files = imgs[start:end] 183 | shuffle(files) 184 | if (i + 1)*args.size > len(imgs): 185 | end = len(imgs) 186 | X_train, X_test, Y_train, Y_test, _c = mdls.prepare_data_train( 187 | files, args.width, args.height, 188 | classes=classes, rc=args.rc) 189 | model.fit(X_train, Y_train, batch_size=args.batchsize, 190 | nb_epoch=1, show_accuracy=True, verbose=1, 191 | validation_data=(X_test, Y_test)) 192 | 193 | t0 = tl.print_time(t0, 'fit') 194 | 195 | tl.write_json(classes, fname=path_cls) 196 | json_string = model.to_json() 197 | open(path_model, 'w').write(json_string) 198 | model.save_weights(path_weights, overwrite=True) 199 | 200 | elif args.sbp_name == 'train': 201 | 202 | scale = True 203 | if args.augmentation: 204 | scale = False 205 | X_train, X_test, Y_train, Y_test, classes = mdls.prepare_data_train( 206 | args.path, args.width, args.height, rc=args.rc, scale=scale) 207 | tl.write_json(classes, fname=path_cls) 208 | nclasses = len(classes) 209 | t0 = tl.print_time(t0, 'prepare data') 210 | 211 | model = mdls.VGG_16(args.weights, lastFC=False) 212 | sgd = SGD(lr=args.lr, decay=args.lrdecay, 213 | momentum=args.momentum, nesterov=True) 214 | print('[finetune_vgg] lr = %f, decay = %f, momentum = %f' 215 | % (args.lr, args.lrdecay, args.momentum)) 216 | 217 | print('[finetune_vgg] Adding Dense(nclasses, activation=softmax).') 218 | model.add(Dense(nclasses, activation='softmax')) 219 | model.compile(optimizer=sgd, loss='categorical_crossentropy') 220 | t0 = tl.print_time(t0, 'compile the model to be fine tuned.') 221 | 222 | for stack in ['conv1', 'conv2', 'conv3', 'conv4', 'conv5']: 223 | for l in mdls.layers[stack]: 224 | l.trainable = False 225 | 226 | if args.augmentation: 227 | datagen = ImageDataGenerator( 228 | featurewise_center=True, 229 | samplewise_center=False, 230 | featurewise_std_normalization=True, 231 | samplewise_std_normalization=False, 232 | zca_whitening=False, 233 | rotation_range=20, 234 | width_shift_range=0.2, 235 | height_shift_range=0.2, 236 | horizontal_flip=True, 237 | vertical_flip=False) 238 | 239 | datagen.fit(X_train) 240 | model.fit_generator( 241 | datagen.flow(X_train, Y_train, batch_size=args.batchsize), 242 | samples_per_epoch=X_train.shape[0], 243 | nb_epoch=args.epochs, show_accuracy=True, 244 | validation_data=(X_test, Y_test), 245 | nb_worker=1) 246 | 247 | else: 248 | model.fit(X_train, Y_train, batch_size=args.batchsize, 249 | nb_epoch=args.epochs, show_accuracy=True, verbose=1, 250 | validation_data=(X_test, Y_test)) 251 | t0 = tl.print_time(t0, 'fit') 252 | score = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0) 253 | print('[finetune_vgg] Test score:', score[0]) 254 | print('[finetune_vgg] Test accuracy:', score[1]) 255 | t0 = tl.print_time(t0, 'evaluate') 256 | 257 | json_string = model.to_json() 258 | open(path_model, 'w').write(json_string) 259 | model.save_weights(path_weights, overwrite=True) 260 | 261 | elif args.sbp_name == 'predict': 262 | cls_map = tl.parse_json(path_cls) 263 | model = model_from_json(open(path_model).read()) 264 | t0 = tl.print_time(t0, 'load model from json') 265 | 266 | model.load_weights(path_weights) 267 | t0 = tl.print_time(t0, 'load model weights') 268 | 269 | if args.cm: 270 | from simdat.core import plot 271 | from sklearn.metrics import confusion_matrix 272 | pl = plot.PLOT() 273 | 274 | X_test, Y_test, classes, F = mdls.prepare_data_test( 275 | args.path, args.width, args.height, convert_Y=False, 276 | y_as_str=False, classes=cls_map) 277 | t0 = tl.print_time(t0, 'prepare data') 278 | results = model.predict_classes( 279 | X_test, batch_size=args.batchsize, verbose=1) 280 | cm = confusion_matrix(Y_test, results) 281 | pl.plot_confusion_matrix(cm, xticks=cls_map, yticks=cls_map, 282 | xrotation=90) 283 | 284 | else: 285 | X_test, Y_test, classes, F = mdls.prepare_data_test( 286 | args.path, args.width, args.height) 287 | t0 = tl.print_time(t0, 'prepare data') 288 | 289 | results = model.predict_proba( 290 | X_test, batch_size=args.batchsize, verbose=1) 291 | outputs = [] 292 | precision = dict((el, 0) for el in cls_map) 293 | recall = dict((el, 0) for el in cls_map) 294 | total = dict((el, 0) for el in classes) 295 | for i in range(0, len(F)): 296 | _cls = results[i].argmax() 297 | max_prob = results[i][_cls] 298 | outputs.append({'input': F[i], 'max_probability': max_prob}) 299 | cls = cls_map[_cls] 300 | recall[cls] += 1 301 | total[Y_test[i]] += 1 302 | if max_prob >= args.threshold: 303 | outputs[-1]['class'] = cls 304 | if Y_test[i] == cls: 305 | precision[cls] += 1 306 | else: 307 | print('[finetune_vgg] %s: %s (%.2f)' 308 | % (F[i], cls, max_prob)) 309 | else: 310 | print('[finetune_vgg] %s: low probability (%.2f),' 311 | ' cannot find a match' % (F[i], max_prob)) 312 | outputs[-1]['class'] = None 313 | tl.write_json(outputs, fname=args.output_loc) 314 | print_precision_recall(precision, recall, total) 315 | 316 | elif args.sbp_name == 'augmentation': 317 | fimgs = simdat_im.find_images(dir_path=args.path) 318 | for fimg in fimgs: 319 | imgs = simdat_im.read_and_random_crop(fimg, save=True) 320 | 321 | else: 322 | print('Wrong command.') 323 | parser.print_help() 324 | 325 | if __name__ == '__main__': 326 | main() 327 | -------------------------------------------------------------------------------- /examples/keras/mnist_cnn_bn.py: -------------------------------------------------------------------------------- 1 | '''Trains a simple convnet on the MNIST dataset. 2 | 3 | Gets to 99.25% test accuracy after 12 epochs 4 | (there is still a lot of margin for parameter tuning). 5 | 16 seconds per epoch on a GRID K520 GPU. 6 | ''' 7 | 8 | from __future__ import print_function 9 | import numpy as np 10 | np.random.seed(1337) # for reproducibility 11 | 12 | from keras.datasets import mnist 13 | from keras.models import Sequential 14 | from keras.layers.core import Dense, Dropout, Activation, Flatten 15 | from keras.layers.convolutional import Convolution2D, MaxPooling2D 16 | from keras.layers.normalization import BatchNormalization 17 | from keras.utils import np_utils 18 | 19 | batch_size = 128 20 | nb_classes = 10 21 | nb_epoch = 12 22 | 23 | # input image dimensions 24 | img_rows, img_cols = 28, 28 25 | # number of convolutional filters to use 26 | nb_filters = 32 27 | # size of pooling area for max pooling 28 | nb_pool = 2 29 | # convolution kernel size 30 | nb_conv = 3 31 | 32 | # the data, shuffled and split between train and test sets 33 | (X_train, y_train), (X_test, y_test) = mnist.load_data() 34 | 35 | X_train = X_train.reshape(X_train.shape[0], 1, img_rows, img_cols) 36 | X_test = X_test.reshape(X_test.shape[0], 1, img_rows, img_cols) 37 | X_train = X_train.astype('float32') 38 | X_test = X_test.astype('float32') 39 | X_train /= 255 40 | X_test /= 255 41 | print('X_train shape:', X_train.shape) 42 | print(X_train.shape[0], 'train samples') 43 | print(X_test.shape[0], 'test samples') 44 | 45 | # convert class vectors to binary class matrices 46 | Y_train = np_utils.to_categorical(y_train, nb_classes) 47 | Y_test = np_utils.to_categorical(y_test, nb_classes) 48 | 49 | model = Sequential() 50 | 51 | model.add(Convolution2D(nb_filters, nb_conv, nb_conv, 52 | border_mode='valid', 53 | input_shape=(1, img_rows, img_cols))) 54 | model.add(Activation('relu')) 55 | model.add(Convolution2D(nb_filters, nb_conv, nb_conv)) 56 | model.add(Activation('relu')) 57 | model.add(MaxPooling2D(pool_size=(nb_pool, nb_pool))) 58 | model.add(Dropout(0.25)) 59 | 60 | model.add(Flatten()) 61 | model.add(Dense(128)) 62 | model.add(BatchNormalization()) 63 | model.add(Activation('relu')) 64 | model.add(Dropout(0.5)) 65 | model.add(Dense(nb_classes)) 66 | model.add(Activation('softmax')) 67 | 68 | model.compile(loss='categorical_crossentropy', 69 | optimizer='adadelta', 70 | metrics=['accuracy']) 71 | 72 | model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, 73 | verbose=1, validation_data=(X_test, Y_test)) 74 | score = model.evaluate(X_test, Y_test, verbose=0) 75 | print('Test score:', score[0]) 76 | print('Test accuracy:', score[1]) 77 | -------------------------------------------------------------------------------- /examples/keras/mnist_visualize.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Train a simple convnet on the MNIST dataset and visualize filters 3 | Reference: mnist_cnn.py in keras examples and https://goo.gl/2qIZdC 4 | This works for Keras 1.0 API 5 | ''' 6 | from __future__ import absolute_import 7 | from __future__ import print_function 8 | import os 9 | import warnings 10 | import pylab as pl 11 | import matplotlib.cm as cm 12 | import numpy as np 13 | import numpy.ma as ma 14 | np.random.seed(1337) # for reproducibility 15 | 16 | import theano 17 | from keras import backend as K 18 | from keras.datasets import mnist 19 | from keras.models import Sequential 20 | from keras.layers.core import Dense, Dropout, Activation, Flatten 21 | from keras.layers.convolutional import Convolution2D, MaxPooling2D 22 | from keras.utils import np_utils 23 | from mpl_toolkits.axes_grid1 import make_axes_locatable 24 | 25 | 26 | os.environ['THEANO_FLAGS'] = 'mode=FAST_RUN,device=gpu,floatX=float32' 27 | warnings.filterwarnings("ignore", category=DeprecationWarning) 28 | 29 | 30 | def nice_imshow(ax, data, name='output.png', vmin=None, vmax=None, cmap=None): 31 | """Wrapper around pl.imshow""" 32 | if cmap is None: 33 | cmap = cm.jet 34 | if vmin is None: 35 | vmin = data.min() 36 | if vmax is None: 37 | vmax = data.max() 38 | divider = make_axes_locatable(ax) 39 | cax = divider.append_axes("right", size="5%", pad=0.05) 40 | im = ax.imshow(data, vmin=vmin, vmax=vmax, 41 | interpolation='nearest', cmap=cmap) 42 | pl.colorbar(im, cax=cax) 43 | pl.savefig(name) 44 | 45 | 46 | def make_mosaic(imgs, nrows, ncols, border=1): 47 | """ 48 | Given a set of images with all the same shape, makes a 49 | mosaic with nrows and ncols 50 | """ 51 | nimgs = imgs.shape[0] 52 | imshape = imgs.shape[1:] 53 | mosaic = ma.masked_all( 54 | (nrows * imshape[0] + (nrows - 1) * border, 55 | ncols * imshape[1] + (ncols - 1) * border), dtype=np.float32) 56 | paddedh = imshape[0] + border 57 | paddedw = imshape[1] + border 58 | for i in xrange(nimgs): 59 | row = int(np.floor(i / ncols)) 60 | col = i % ncols 61 | mosaic[row * paddedh:row * paddedh + imshape[0], 62 | col * paddedw:col * paddedw + imshape[1]] = imgs[i] 63 | return mosaic 64 | 65 | 66 | np.set_printoptions(precision=5, suppress=True) 67 | nb_classes = 10 68 | 69 | (X_train, y_train), (X_test, y_test) = mnist.load_data() 70 | 71 | X_train = X_train.reshape(X_train.shape[0], 1, 28, 28) 72 | X_test = X_test.reshape(X_test.shape[0], 1, 28, 28) 73 | X_train = X_train.astype("float32") 74 | X_test = X_test.astype("float32") 75 | X_train /= 255 76 | X_test /= 255 77 | print('X_train shape:', X_train.shape) 78 | print(X_train.shape[0], 'train samples') 79 | print(X_test.shape[0], 'test samples') 80 | 81 | # convert class vectors to binary class matrices 82 | Y_train = np_utils.to_categorical(y_train, nb_classes) 83 | Y_test = np_utils.to_categorical(y_test, nb_classes) 84 | i = 4600 85 | pl.imshow(X_train[i, 0], interpolation='nearest', cmap=cm.binary) 86 | print("label : ", Y_train[i, :]) 87 | 88 | model = Sequential() 89 | 90 | model.add(Convolution2D(32, 3, 3, border_mode='valid', 91 | input_shape=X_train.shape[1:])) 92 | model.add(Dropout(0.1)) 93 | convout1 = Activation('relu') 94 | model.add(convout1) 95 | model.add(Convolution2D(32, 3, 3)) 96 | 97 | convout2 = Activation('relu') 98 | model.add(convout2) 99 | model.add(MaxPooling2D(pool_size=(2, 2))) 100 | model.add(Dropout(0.25)) 101 | 102 | model.add(Flatten()) 103 | model.add(Dense(128)) 104 | model.add(Activation('relu')) 105 | model.add(Dropout(0.5)) 106 | 107 | model.add(Dense(nb_classes)) 108 | model.add(Activation('softmax')) 109 | 110 | model.compile(loss='categorical_crossentropy', 111 | optimizer='adadelta', metrics=['accuracy']) 112 | 113 | WEIGHTS_FNAME = 'mnist_cnn_weights_v1.hdf' 114 | if True and os.path.exists(WEIGHTS_FNAME): 115 | # Just change the True to false to force re-training 116 | print('Loading existing weights') 117 | model.load_weights(WEIGHTS_FNAME) 118 | else: 119 | batch_size = 128 120 | nb_epoch = 12 121 | model.fit(X_train, Y_train, batch_size=batch_size, nb_epoch=nb_epoch, 122 | verbose=1, validation_data=(X_test, Y_test)) 123 | model.save_weights(WEIGHTS_FNAME, overwrite=True) 124 | 125 | score = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0) 126 | print('Test score:', score[0]) 127 | print('Test accuracy:', score[1]) 128 | 129 | # K.learning_phase() is a flag that indicates if the network is 130 | # in training or predict phase. It allow layer (e.g. Dropout) 131 | # to only be applied during training 132 | inputs = [K.learning_phase()] + model.inputs 133 | _convout1_f = K.function(inputs, [convout1.output]) 134 | 135 | # Visualize the first layer of convolutions on an input image 136 | i = 4600 137 | X = X_test[i:i+1] 138 | 139 | pl.figure() 140 | pl.title('input') 141 | nice_imshow(pl.gca(), np.squeeze(X), vmin=0, vmax=1, 142 | cmap=cm.binary, name='mnist_vis_input.png') 143 | 144 | # Visualize weights 145 | W = model.layers[0].W.get_value(borrow=True) 146 | W = np.squeeze(W) 147 | print("W shape : ", W.shape) 148 | pl.figure(figsize=(15, 15)) 149 | pl.title('conv1 weights') 150 | nice_imshow(pl.gca(), make_mosaic(W, 6, 6), cmap=cm.binary, 151 | name='mnist_vis_conv1_weights.png') 152 | 153 | 154 | # Visualize convolution result (after activation) 155 | def convout1_f(X): 156 | # The [0] is to disable the training phase flag 157 | return _convout1_f([0] + [X]) 158 | 159 | 160 | C1 = convout1_f(X) 161 | C1 = np.squeeze(C1) 162 | print("C1 shape : ", C1.shape) 163 | 164 | pl.figure(figsize=(15, 15)) 165 | pl.suptitle('convout1') 166 | nice_imshow(pl.gca(), make_mosaic(C1, 6, 6), cmap=cm.binary, 167 | name='mnist_vis_convout1.png') 168 | -------------------------------------------------------------------------------- /examples/keras/simple_classifier.py: -------------------------------------------------------------------------------- 1 | import time 2 | import argparse 3 | import numpy as np 4 | from simdat.core import dp_models 5 | from simdat.core import tools 6 | from keras.optimizers import SGD 7 | from keras.utils import np_utils 8 | 9 | 10 | def main(): 11 | parser = argparse.ArgumentParser( 12 | description="Use Simple model to train a classifier." 13 | ) 14 | parser.add_argument( 15 | "-p", "--path", type=str, default='.', 16 | help="Path where the images are. Default: $PWD." 17 | ) 18 | parser.add_argument( 19 | "--img-rows", type=int, default=224, dest='rows', 20 | help="Rows of the images, default: 224." 21 | ) 22 | parser.add_argument( 23 | "--img-cols", type=int, default=224, dest='cols', 24 | help="Columns of the images, default: 224." 25 | ) 26 | parser.add_argument( 27 | "--seed", type=int, default=1337, 28 | help="Random seed, default: 1337." 29 | ) 30 | parser.add_argument( 31 | "--batch-size", type=int, default=64, dest='batchsize', 32 | help="Size of the mini batch. Default: 64." 33 | ) 34 | parser.add_argument( 35 | "--epochs", type=int, default=20, 36 | help="Number of epochs, default 20." 37 | ) 38 | 39 | t0 = time.time() 40 | mdls = dp_models.DPModel() 41 | tl = tools.TOOLS() 42 | 43 | args = parser.parse_args() 44 | np.random.seed(args.seed) 45 | 46 | X_train, X_test, Y_train, Y_test, classes = mdls.prepare_data( 47 | args.path, args.rows, args.cols) 48 | t0 = tl.print_time(t0, 'prepare data') 49 | model = mdls.Simple(len(classes), img_row=X_train.shape[2], 50 | img_col=X_train.shape[3], colors=X_train.shape[1]) 51 | sgd = SGD(lr=0.001, decay=1e-6, momentum=0.9, nesterov=True) 52 | model.compile(optimizer=sgd, loss='categorical_crossentropy') 53 | t0 = tl.print_time(t0, 'compile the Simple model') 54 | 55 | model.fit(X_train, Y_train, batch_size=args.batchsize, 56 | nb_epoch=args.epochs, show_accuracy=True, verbose=1, 57 | validation_data=(X_test, Y_test)) 58 | t0 = tl.print_time(t0, 'fit') 59 | score = model.evaluate(X_test, Y_test, show_accuracy=True, verbose=0) 60 | print('Test score:', score[0]) 61 | print('Test accuracy:', score[1]) 62 | t0 = tl.print_time(t0, 'evaluate') 63 | 64 | if __name__ == '__main__': 65 | main() 66 | -------------------------------------------------------------------------------- /examples/keras/squeezenet_demo.py: -------------------------------------------------------------------------------- 1 | """ 2 | Usage: python squeezenet_demo.py -p "/home/db/www/database/tests/train" -v -p "/home/db/www/database/tests/validation" 3 | """ 4 | import time 5 | import argparse 6 | from simdat.core import dp_tools 7 | from simdat.core import keras_models as km 8 | from simdat.core import tools 9 | from keras.optimizers import SGD 10 | 11 | dp = dp_tools.DP() 12 | tl = tools.TOOLS() 13 | 14 | 15 | def main(): 16 | parser = argparse.ArgumentParser( 17 | description="SqueezeNet example." 18 | ) 19 | parser.add_argument( 20 | "--epochs", type=int, default=20, 21 | help="Number of epochs, default 20." 22 | ) 23 | parser.add_argument( 24 | "--lr", type=float, default=0.001, 25 | help="Learning rate of SGD, default 0.001." 26 | ) 27 | parser.add_argument( 28 | "-p", "--path", type=str, default='.', required=True, 29 | help="Path where the images are. Default: $PWD." 30 | ) 31 | parser.add_argument( 32 | "-v", "--val-path", type=str, default='.', required=True, 33 | dest='valpath', help="Path where the val images are. Default: $PWD." 34 | ) 35 | parser.add_argument( 36 | "--img-width", type=int, default=224, dest='width', 37 | help="Rows of the images, default: 224." 38 | ) 39 | parser.add_argument( 40 | "--img-height", type=int, default=224, dest='height', 41 | help="Columns of the images, default: 224." 42 | ) 43 | parser.add_argument( 44 | "--channels", type=int, default=3, 45 | help="Channels of the images, default: 3." 46 | ) 47 | 48 | args = parser.parse_args() 49 | 50 | train_generator = dp.train_data_generator( 51 | args.path, args.width, args.height) 52 | validation_generator = dp.val_data_generator( 53 | args.valpath, args.width, args.height) 54 | 55 | nb_train_samples = train_generator.nb_sample 56 | nb_val_samples = validation_generator.nb_sample 57 | print("[squeezenet] Number of training samples: %i " % nb_train_samples) 58 | print("[squeezenet] Number of training samples: %i " % nb_val_samples) 59 | nb_class = train_generator.nb_class 60 | print('[squeezenet] Total classes are %i' % nb_class) 61 | 62 | t0 = time.time() 63 | print "[squeezenet] Building the model..." 64 | model = km.SqueezeNet( 65 | nb_class, inputs=(args.channels, args.height, args.width)) 66 | dp.visualize_model(model) 67 | 68 | sgd = SGD(lr=args.lr, decay=0.0002, momentum=0.9, nesterov=True) 69 | model.compile( 70 | optimizer=sgd, loss='categorical_crossentropy', metrics=['accuracy']) 71 | print "[squeezenet] Model built." 72 | 73 | print "[squeezenet] Start training..." 74 | model.fit_generator( 75 | train_generator, 76 | samples_per_epoch=nb_train_samples, 77 | nb_epoch=args.epochs, 78 | validation_data=validation_generator, 79 | nb_val_samples=nb_val_samples) 80 | 81 | print "[squeezenet] Model trained." 82 | 83 | t0 = tl.print_time(t0, 'score squeezenet') 84 | model.save_weights('squeeze_net.h5', overwrite=True) 85 | 86 | if __name__ == '__main__': 87 | main() 88 | -------------------------------------------------------------------------------- /examples/keras/vgg_demo.json: -------------------------------------------------------------------------------- 1 | { 2 | "weight_path": "/docker/vgg/vgg16_weights.h5", 3 | "imagenet_labels": "/docker/vgg/synset_words.txt" 4 | } 5 | -------------------------------------------------------------------------------- /examples/keras/vgg_demo.py: -------------------------------------------------------------------------------- 1 | import os 2 | import time 3 | import numpy as np 4 | import argparse 5 | from keras.optimizers import SGD 6 | from simdat.core import dp_models 7 | from simdat.core import plot 8 | from simdat.core import image 9 | from simdat.core import ml 10 | 11 | im = image.IMAGE() 12 | 13 | class DEMOArgs(ml.MLArgs): 14 | def _add_args(self): 15 | self._add_ml_args() 16 | self.weight_path = None 17 | self.imagenet_labels = None 18 | 19 | class DEMO(dp_models.DPModel): 20 | def dpmodel_init(self): 21 | self.t0 = time.time() 22 | self.imnet = dp_models.ImageNet() 23 | self.pl = plot.PLOT() 24 | self.args = DEMOArgs(pfs=['/docker/vgg_demo.json']) 25 | self.model = self.VGG_16(self.args.weight_path) 26 | self.t0 = self.pl.print_time(self.t0, 'initiate') 27 | 28 | sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True) 29 | self.model.compile(optimizer=sgd, loss='categorical_crossentropy') 30 | self.t0 = self.pl.print_time(self.t0, 'compile model') 31 | 32 | def _predict(self, fimg, plot=False): 33 | print('Processing %s' % fimg) 34 | name, ext = os.path.splitext(fimg) 35 | img_original = im.read(fimg, size=(224, 224)) 36 | img = img_original.transpose((2, 0, 1)) 37 | img = np.expand_dims(img, axis=0) 38 | out = self.model.predict(img) 39 | prob = out.ravel() 40 | if plot: 41 | self.pl.plot(out.ravel()) 42 | result = self.imnet.find_topk(prob, fname=self.args.imagenet_labels) 43 | return result 44 | 45 | def predict(self, imgs, plot=False): 46 | results = {} 47 | for fimg in imgs: 48 | result = self._predict(fimg, plot=plot) 49 | results[os.path.basename(fimg)] = result 50 | self.t0 = self.pl.print_time(self.t0, 'compute for all images') 51 | print(results) 52 | return results 53 | 54 | def main(): 55 | parser = argparse.ArgumentParser( 56 | description="Simple Keras Demo" 57 | ) 58 | parser.add_argument( 59 | "-w", "--workdir", type=str, default="/docker/images/tests/", 60 | help="Working directory where the images are stored." + 61 | " (default: /docker/images/tests/)" 62 | ) 63 | args = parser.parse_args() 64 | 65 | images = im.find_images(dir_path=args.workdir) 66 | demo = DEMO() 67 | demo.predict(images) 68 | 69 | if __name__ == '__main__': 70 | main() 71 | 72 | -------------------------------------------------------------------------------- /examples/keras/vgg_visualization.py: -------------------------------------------------------------------------------- 1 | '''Visualization of the convolutional filters of VGG16 2 | 3 | References: 4 | https://github.com/julienr/ipynb_playground/blob/master/keras/convmnist/keras_cnn_mnist.ipynb 5 | https://gist.github.com/baraldilorenzo/07d7802847aaad0a35d3 6 | 7 | Before running this script, download the weights for the VGG16 model at: 8 | https://drive.google.com/file/d/0Bz7KyqmuGsilT0J5dmRCM0ROVHc/view?usp=sharing 9 | and make sure the variable `args.weights` in this script matches the location. 10 | ''' 11 | from __future__ import print_function 12 | import numpy as np 13 | import numpy.ma as ma 14 | import time 15 | import os 16 | import math 17 | import argparse 18 | import pylab as pl 19 | import matplotlib.cm as cm 20 | from keras import backend as K 21 | from mpl_toolkits.axes_grid1 import make_axes_locatable 22 | from simdat.core import dp_models 23 | from simdat.core import tools 24 | 25 | 26 | def nice_imshow(ax, data, name='output.png', vmin=None, vmax=None, cmap=None): 27 | """Wrapper around pl.imshow""" 28 | if cmap is None: 29 | cmap = cm.jet 30 | if vmin is None: 31 | vmin = data.min() 32 | if vmax is None: 33 | vmax = data.max() 34 | divider = make_axes_locatable(ax) 35 | cax = divider.append_axes("right", size="5%", pad=0.05) 36 | im = ax.imshow(data, vmin=vmin, vmax=vmax, 37 | interpolation='nearest', cmap=cmap) 38 | pl.colorbar(im, cax=cax) 39 | pl.savefig(name) 40 | 41 | 42 | def make_mosaic(imgs, border=1): 43 | """ 44 | Given a set of images with all the same shape, makes a 45 | mosaic with nrows and ncols 46 | """ 47 | nimgs = imgs.shape[0] 48 | nrows = math.ceil(math.sqrt(nimgs)) 49 | imshape = imgs.shape[1:] 50 | mosaic = ma.masked_all( 51 | (nrows * imshape[0] + (nrows - 1) * border, 52 | nrows * imshape[1] + (nrows - 1) * border), dtype=np.float32) 53 | paddedh = imshape[0] + border 54 | paddedw = imshape[1] + border 55 | for i in xrange(nimgs): 56 | row = int(np.floor(i / nrows)) 57 | col = i % nrows 58 | mosaic[row * paddedh:row * paddedh + imshape[0], 59 | col * paddedw:col * paddedw + imshape[1]] = imgs[i] 60 | return mosaic 61 | 62 | 63 | def main(): 64 | parser = argparse.ArgumentParser( 65 | description="Simple script to visualize VGG fliters." 66 | ) 67 | parser.add_argument( 68 | "-p", "--path", type=str, default=None, required=True, 69 | help="Path where the image is." 70 | ) 71 | parser.add_argument( 72 | "-w", "--weights", type=str, default=None, required=True, 73 | help="Path of the VGG-16 weight file." 74 | ) 75 | 76 | args = parser.parse_args() 77 | 78 | # simdat dependencies 79 | dp = dp_models.DPModel() 80 | tl = tools.DATA() 81 | 82 | # basic parameters 83 | img_width = 224 84 | img_height = 224 85 | 86 | model = dp.VGG_16(weights_path=args.weights) 87 | model.summary() 88 | X, Y, cls, F = dp.prepare_data_test( 89 | args.path, img_width, img_height, convert_Y=False, y_as_str=False) 90 | inputs = [K.learning_phase()] + model.inputs 91 | 92 | # Visualize convolution result (after activation) 93 | def conv_f(X): 94 | # The [0] is to disable the training phase flag 95 | return _conv_f([0] + [X]) 96 | 97 | for layer in model.layers: 98 | lname = dp.is_convolutional(layer) 99 | if lname is None: 100 | continue 101 | # return the output of a certain layer given a certain input 102 | # http://keras.io/getting-started/faq/ 103 | _conv_f = K.function(inputs, [layer.output]) 104 | C1 = conv_f(X) 105 | C1 = np.squeeze(C1) 106 | print("%s shape : " % lname, C1.shape) 107 | pl.figure(figsize=(15, 15)) 108 | pl.suptitle(lname) 109 | nice_imshow(pl.gca(), make_mosaic(C1), cmap=cm.binary, 110 | name=lname + '.png') 111 | 112 | # TODO: Visualize weights 113 | 114 | if __name__ == '__main__': 115 | main() 116 | -------------------------------------------------------------------------------- /examples/make_scene_better.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import os 3 | import sys 4 | import argparse 5 | import logging 6 | import numpy as np 7 | from scipy import ndimage 8 | from simdat.core.so import image 9 | from simdat.core import plot 10 | 11 | imgtl = image.OverlayTextDetection() 12 | 13 | 14 | def test(imgs): 15 | pl = plot.PLOT() 16 | for _img in imgs: 17 | print('Processing %s' % _img) 18 | img = imgtl.read(_img) 19 | 20 | 21 | def main(): 22 | 23 | parser = argparse.ArgumentParser( 24 | description="Simple tool to make the scene image better." 25 | ) 26 | group = parser.add_mutually_exclusive_group() 27 | group.add_argument( 28 | "-f", "--fname", type=str, default=None, 29 | help="Specify the filename of the image to handle." 30 | ) 31 | group.add_argument( 32 | "-d", "--dir", type=str, default=None, 33 | help="Specify the directory to look for images (default .)." 34 | ) 35 | parser.add_argument( 36 | "-a", "--action", type=str, default='scene', 37 | help="Select action: black-bar/crop-text \ 38 | (default: scene)." 39 | ) 40 | parser.add_argument( 41 | "-e", "--explain", action='store_true', 42 | help="Explain the arguments used." 43 | ) 44 | parser.add_argument( 45 | "-v", "--verbosity", action="count", 46 | help="increase output verbosity" 47 | ) 48 | parser.add_argument( 49 | "-s", "--save", action='store_true', 50 | help="save intermediate" 51 | ) 52 | parser.add_argument( 53 | "-t", "--test", action='store_true' 54 | ) 55 | args = parser.parse_args() 56 | 57 | log_level = logging.WARNING 58 | if args.verbosity == 1: 59 | log_level = logging.INFO 60 | elif args.verbosity == 2: 61 | log_level = logging.DEBUG 62 | logging.basicConfig(level=log_level, 63 | format='[MSB %(levelname)s] %(message)s') 64 | 65 | if args.fname is not None: 66 | imgtl.check_exist(args.fname) 67 | imgs = [args.fname] 68 | elif args.dir is not None: 69 | imgs = imgtl.find_images(dir_path=args.dir) 70 | else: 71 | imgs = imgtl.find_images() 72 | 73 | if args.test: 74 | test(imgs) 75 | sys.exit(1) 76 | 77 | if len(imgs) == 0: 78 | print('No image is found') 79 | for fimg in imgs: 80 | print('Processing %s' % fimg) 81 | name, ext = os.path.splitext(fimg) 82 | img = imgtl.read(fimg) 83 | gray = imgtl.gray(img) 84 | if args.action == 'black-bar': 85 | fname = ''.join([name, '_crop', ext]) 86 | imgtl.crop_black_bars(img, fname=fname) 87 | elif args.action == 'scene': 88 | if args.explain: 89 | fexplain = 'otd_args.explain.json' 90 | if not imgtl.check_exist(fexplain): 91 | print('ERROR: %s does not exist' % fexplain) 92 | sys.exit(1) 93 | imgtl.args.explain_args(fexplain) 94 | sys.exit(1) 95 | fname = ''.join([name, '_scene', ext]) 96 | croped = imgtl.crop_black_bars(img) 97 | text_removed = imgtl.detect_text_area(croped, save=args.save) 98 | imgtl.save(text_removed, fname) 99 | elif args.action == 'crop-text': 100 | fname = ''.join([name, '_text', ext]) 101 | img = imgtl.detect_text_area(img, save=args.save) 102 | imgtl.save(img, fname) 103 | 104 | if __name__ == '__main__': 105 | main() 106 | -------------------------------------------------------------------------------- /examples/ml_example.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import numpy as np 3 | import logging 4 | from simdat.core import ml 5 | 6 | log_level = logging.DEBUG 7 | #Train a model 8 | data = np.array([[1, 2, 3, 4], [2, 2, 3, 4], 9 | [3, 2, 3, 4], [4, 2, 3, 4], 10 | [3, 2, 3, 4], [4, 2, 3, 4], 11 | [3, 2, 3, 4], [4, 2, 3, 4], 12 | [3, 2, 3, 4], [4, 2, 3, 4], 13 | [3, 2, 3, 4], [4, 2, 3, 4], 14 | [3, 2, 3, 4], [4, 2, 3, 4]]) 15 | target = np.array([1, 0, 16 | 0, 1, 17 | 0, 1, 18 | 1, 0, 19 | 1, 0, 20 | 0, 1, 21 | 1, 0]) 22 | a = ml.SVMRun() 23 | results = a.run(data, target) 24 | 25 | #Load the existing model and test 26 | td = np.array([[1, 2, 3, 4], [2, 2, 3, 4], 27 | [3, 2, 3, 4], [4, 2, 3, 4]]) 28 | tt = np.array([1, 0, 1, 1]) 29 | model = a.read_model('./output/SVC.pkl') 30 | a.test(td, tt, model) 31 | 32 | #Predict 33 | a.predict(td, model, outf='./output/result.json') 34 | -------------------------------------------------------------------------------- /examples/openface.json: -------------------------------------------------------------------------------- 1 | { 2 | "pathOF": "/tammy/openface/", 3 | "parentModel": "models", 4 | "parentdlibModel": "dlib", 5 | "fdlibFaceMean": "mean.csv", 6 | "fdlibPredictor": "shape_predictor_68_face_landmarks.dat", 7 | "fmodel": "nn4.v1.t7", 8 | "imgDim": 96, 9 | "align_method": "homography", 10 | "outf": "./result.json", 11 | "cuda": false 12 | } 13 | -------------------------------------------------------------------------------- /examples/openface_demo.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import argparse 4 | import itertools 5 | import numpy as np 6 | from simdat.openface import oftools 7 | from simdat.core.so import image 8 | from simdat.core import tools 9 | from simdat.core import plot 10 | from simdat.core import ml 11 | 12 | 13 | class DEMO(oftools.OpenFace): 14 | def of_init(self): 15 | """ Init function for child class """ 16 | 17 | self.im = image.IMAGE() 18 | self.io = tools.MLIO() 19 | self.pl = plot.PLOT() 20 | self.mpath = None 21 | self.dbs = None 22 | self.ml = None 23 | self.classifier = None 24 | 25 | def set_classifier(self, method): 26 | """ Set the chosen classifier. 27 | Need to be called before training, testing and predicting. 28 | 29 | @param method: classification method to be used. 30 | Can be RF/Neighbors/SVC 31 | 32 | """ 33 | if method == 'RF': 34 | self.ml = ml.RFRun(pfs=['ml.json']) 35 | self.classifier = method 36 | elif method == 'Neighbors': 37 | self.ml = ml.NeighborsRun(pfs=['ml.json']) 38 | self.classifier = method 39 | else: 40 | self.ml = ml.SVMRun(pfs=['ml.json']) 41 | self.classifier = 'SVC' 42 | 43 | def set_dbs(self, dbpath): 44 | """ Set the dbs. dbs are generated by self.act_rep """ 45 | 46 | self.dbs = self.io.find_files(dir_path=dbpath, suffix=('json')) 47 | 48 | def read_model(self, root='./'): 49 | """ Read the persistent model from pickle file. 50 | It depends on self.classifier which should be 51 | set by self.set_classifier. Called by act_predict and act_test 52 | 53 | Keyword arguments: 54 | root -- the parent directory of the pickle files (default: $PWD) 55 | 56 | """ 57 | self._check_classifier() 58 | mpath = root + self.classifier + '.pkl' 59 | if not self.io.check_exist(mpath): 60 | print('[openface_demo] Error: %s does not exist.' % mpath) 61 | sys.exit(1) 62 | return self.ml.read_model(mpath) 63 | 64 | def _pick_imgs(self): 65 | """ Pick representations of the images 66 | found in the current directory """ 67 | 68 | self._check_dbs() 69 | return self.pick_reps(self.dbs) 70 | 71 | def _check_dbs(self): 72 | """ Check if self.dbs are properly set """ 73 | 74 | if self.dbs is None or len(self.dbs) == 0: 75 | print('[openface_demo] Error: No db is found. ' 76 | 'Make sure self.set_dbs(dbpath) ran properly') 77 | sys.exit(1) 78 | 79 | def _check_classifier(self): 80 | """ Check if self.ml is properly set """ 81 | 82 | if self.ml is None: 83 | print('[openface_demo] Error: No db is found. ' 84 | 'Make sure self.set_classifier(method=$METHOD) ran properly') 85 | sys.exit(1) 86 | 87 | def _pca(self, df, ncomp=2, pca_method='PCA'): 88 | """ Draw for principal component analysis 89 | 90 | @param df: DataFrame of the input data 91 | 92 | Keyword arguments: 93 | ncomp -- number or components to be kept (Default: 2) 94 | method -- method to be used 95 | PCA(default)/Randomized/Sparse 96 | 97 | """ 98 | mltl = ml.MLTools() 99 | res = self.read_df(df, dtype='train', group=False, conv=False) 100 | p = df['class'].value_counts().idxmax() 101 | data = res['data'] 102 | fname = p + '_pca.png' 103 | if ncomp == 1: 104 | pca_data = mltl.PCA(data, ncomp=1, 105 | method=pca_method) 106 | pca_data = np.array(pca_data).T[0] 107 | self.pl.histogram(pca_data, fname=fname) 108 | return p, pca_data 109 | else: 110 | pca_data = mltl.PCA(data, method=pca_method) 111 | pca_data = np.array(pca_data).T 112 | self.pl.plot_points(pca_data[0], pca_data[1], fname=fname, 113 | xmin=-1, xmax=1, ymin=-1, ymax=1) 114 | return p, [pca_data[0], pca_data[1]] 115 | 116 | def act_reps(self, dir_path=None): 117 | """ Get facenet representations for images in the current directory. 118 | The results will be saved to './result.json' You may copy the db 119 | manually to where self.set_dbs can find. 120 | 121 | Keyword arguments: 122 | dir_path -- directory of the images to process (default: $PWD) 123 | 124 | """ 125 | images = self.im.find_images(dir_path=dir_path) 126 | return self.get_reps(images, output=True, class_kwd='') 127 | 128 | def act_train(self): 129 | """ Training the classifier. This should be done after self.act_reps 130 | is properly executed, and this function relied the existing 131 | dbs created by self.act_reps. """ 132 | 133 | self._check_classifier() 134 | df = self._pick_imgs() 135 | res = self.read_df(df, dtype='train', group=False) 136 | mf = self.ml.run(res['data'], res['target']) 137 | 138 | def act_pca(self, ncomp=2, mpf='./mapping.json'): 139 | 140 | """ decompose a multivariate dataset in an orthogonal 141 | set that explain a maximum amount of the variance 142 | 143 | Keyword Arguments: 144 | ncomp -- number or components to be kept (Default: 2) 145 | mpf -- mapping file of class_from_fath vs real class 146 | during training which should be generated 147 | by self.act_train. 148 | 149 | """ 150 | print('[openface_demo] ncomp = %i' % ncomp) 151 | mapping = self.io.parse_json(mpf) 152 | df = self._pick_imgs() 153 | all_data = [] 154 | labels = [] 155 | for p in mapping.keys(): 156 | df['class'] = df['class'].astype(type(p)) 157 | _df = df[df['class'] == p] 158 | if _df.empty: 159 | continue 160 | p, data = self._pca(_df, ncomp=ncomp, pca_method='PCA') 161 | all_data.append(data) 162 | labels.append(p) 163 | if ncomp == 1: 164 | self.pl.plot_1D_dists(all_data, legend=labels) 165 | else: 166 | self.pl.plot_classes(all_data, legend=labels) 167 | 168 | def act_compare(self, img1=None, img2=None, thre=1.1): 169 | """ Compare the distance between two images 170 | 171 | @param img1: path of the first image 172 | @param img2: path of the second image 173 | 174 | Keyword Arguments: 175 | thre -- distance threthold to decide whether two faces are alike 176 | (default: 1.1 which was suggested in the facenet paper) 177 | 178 | """ 179 | if (img1 is None) or (img2 is None): 180 | print('[openface_demo] ERROR: images are None') 181 | sys.exit(1) 182 | res = self.get_reps([img1, img2], class_kwd='').values() 183 | return self.compare(res[0], res[1], thre=thre) 184 | 185 | def act_compare_dir(self, dir_path, thre=1.1): 186 | """ Compare all face images in the directory 187 | 188 | @param dir_path: parent directory of the images to be predicted 189 | 190 | Keyword Arguments: 191 | thre -- distance threthold to decide whether two faces are alike 192 | (default: 1.1 which was suggested in the facenet paper) 193 | 194 | """ 195 | res = self.act_reps(dir_path=dir_path) 196 | for (item1, item2) in itertools.combinations(res, 2): 197 | sim, dis = self.compare(res[item1], res[item2], thre=thre) 198 | 199 | def act_predict(self, mpf='./mapping.json', 200 | model_root='./', dir_path=None): 201 | """ Predict based on the trained model 202 | 203 | Keyword Arguments: 204 | model_root -- parent directory of the model pickle file (default: ./) 205 | mpf -- mapping file of class_from_fath vs real class 206 | during training which should be generated 207 | by self.act_train. 208 | dir_path -- parent directory of the images to be predicted 209 | 210 | """ 211 | model = self.read_model(root=model_root) 212 | res = self.act_reps(dir_path=dir_path) 213 | mapping = self.io.parse_json(mpf) 214 | for item in res: 215 | cl = self.ml.predict(res[item]['rep'], model)['Result'][0] 216 | print ('[openface_demo] Parsing %s' % res[item]['path']) 217 | print [c for c in mapping if mapping[c] == cl][0] 218 | 219 | def act_test(self, mpf='./mapping.json', model_root='./', 220 | thre=0.4, matched_out='/www/experiments/'): 221 | """ Predict based on the trained model 222 | 223 | Keyword Arguments: 224 | model_root -- parent directory of the model pickle file (default: ./) 225 | mpf -- mapping file of class_from_fath vs real class 226 | during training which should be generated 227 | by self.act_train (default: ./mapping.json) 228 | thre -- threshold to be applied to the output probability 229 | (default: 0.4) 230 | matched_out -- where to output images with roi plotted 231 | (default: /www/experiments) 232 | 233 | """ 234 | print('[openface_demo] Threshold applied %.2f' % thre) 235 | from datetime import date 236 | model = self.read_model(root=model_root) 237 | df = self._pick_imgs() 238 | res = self.read_df(df, dtype='test', mpf=mpf, group=True) 239 | match = 0 240 | nwrong = 0 241 | today = date.today().strftime("%Y%m%d") 242 | new_home = matched_out + today 243 | for i in range(0, len(res['data'])): 244 | r1 = self.ml.test(res['data'][i], res['target'][i], model, 245 | target_names=res['target_names']) 246 | cat = res['target'][i][0] 247 | found = False 248 | mis_match = False 249 | if r1['prob'] is None: 250 | for p in range(0, len(r1['predicted'])): 251 | if cat == r1['predicted'][p]: 252 | path = res['path'][i] 253 | self.pl.patch_rectangle_img( 254 | path, res['pos'][i][p], 255 | new_name=None) 256 | found = True 257 | else: 258 | for p in range(0, len(r1['prob'])): 259 | prob = r1['prob'][p] 260 | vmax = max(prob) 261 | imax = prob.argmax() 262 | if vmax > thre: 263 | if imax == cat: 264 | path = res['path'][i] 265 | self.pl.patch_rectangle_img( 266 | path, res['pos'][i][p], 267 | new_home=new_home) 268 | found = True 269 | else: 270 | mis_match = True 271 | if found: 272 | match += 1 273 | if mis_match: 274 | nwrong += 1 275 | try: 276 | print('[openface_demo] Recall = %.2f' 277 | % (float(match)/float(len(res['data'])))) 278 | print('[openface_demo] Precision = %.2f' 279 | % (float(match)/float(match + nwrong))) 280 | except: 281 | pass 282 | print('[openface_demo] Images with roi are saved to %s' % new_home) 283 | 284 | 285 | def main(): 286 | parser = argparse.ArgumentParser( 287 | description="Simple Openface Demo" 288 | ) 289 | parser.add_argument( 290 | "-a", "--action", type=str, default='reps', 291 | help="Action to be taken reps(default)" + 292 | "/train/test/predict/pca/compare_dir/compare" 293 | ) 294 | parser.add_argument( 295 | "-c", "--classifier", type=str, default='SVC', 296 | help="Classifier to be used SVC(default)/Neighbors/RF" 297 | ) 298 | parser.add_argument( 299 | "-p", "--pcut", type=float, default=0.4, 300 | help="Probability cut to be applied to the classifier" + 301 | " (default: 0.4, used by action=test)" 302 | ) 303 | parser.add_argument( 304 | "--mpf", type=str, default='./mapping.json', 305 | help="Path of the mapping file which is generated by action=train" + 306 | " (default: ./mapping.json, used by action=test/predict/pca)" 307 | ) 308 | parser.add_argument( 309 | "--img1", type=str, 310 | help="Path of the first image passed to act_compare" 311 | ) 312 | parser.add_argument( 313 | "--img2", type=str, 314 | help="Path of the first image passed to act_compare" 315 | ) 316 | parser.add_argument( 317 | "--model-path", dest='model_path', type=str, default='./', 318 | help="Root directory of the model pickle files" + 319 | " (default: ./ , used by action=test/predict)" 320 | ) 321 | parser.add_argument( 322 | "-d", "--dbpath", type=str, default='/www/database/db/', 323 | help="Path of dbs which are generated by action=rep" 324 | " (default: /www/database/db/)" 325 | ) 326 | parser.add_argument( 327 | "-w", "--workdir", type=str, default=None, 328 | help="Working directory where the images are stored." + 329 | " (default: $PWD, used by action=predict/compare_dir)" 330 | ) 331 | 332 | pfs = ['openface.json', 'ml.json'] 333 | 334 | args = parser.parse_args() 335 | if args.action != 'compare' and (args.img1 or args.img2): 336 | parser.error('--img1/--img2 can only be set when' 337 | ' --action=compare') 338 | 339 | demo = DEMO(pfs) 340 | demo.set_dbs(args.dbpath) 341 | 342 | if args.workdir is None: 343 | args.workdir = os.getcwd() 344 | 345 | parms = {} 346 | 347 | if args.action == 'rep': 348 | parms['dir_path'] = args.workdir 349 | elif args.action == 'pca': 350 | parms['mpf'] = args.mpf 351 | elif args.action == 'predict': 352 | demo.set_classifier(args.classifier) 353 | parms['mpf'] = args.mpf 354 | parms['model_root'] = args.model_path 355 | parms['dir_path'] = args.workdir 356 | elif args.action == 'test': 357 | demo.set_classifier(args.classifier) 358 | parms['thre'] = args.pcut 359 | parms['mpf'] = args.mpf 360 | parms['model_root'] = args.model_path 361 | elif args.action == 'train': 362 | demo.set_classifier(args.classifier) 363 | elif args.action == 'compare_dir': 364 | parms['dir_path'] = args.workdir 365 | elif args.action == 'compare': 366 | parms['img1'] = args.img1 367 | parms['img2'] = args.img2 368 | 369 | getattr(demo, 'act_' + args.action)(**parms) 370 | 371 | if __name__ == '__main__': 372 | main() 373 | -------------------------------------------------------------------------------- /examples/otd_args.explain.json: -------------------------------------------------------------------------------- 1 | { 2 | "ramin": { 3 | "des": "Ratio to the total area for setting a minimum threshold of the selected area", 4 | "type": "float", 5 | "default": 0.05 6 | }, 7 | "ramax": { 8 | "des": "Ratio to the total area for setting a maximum threshold of the selected area", 9 | "type": "float", 10 | "default": 0.05 11 | }, 12 | "rmor_sel": { 13 | "des": "Ratio to the maximum value of the matrix after applying all morphological transform. This is used to filter out values below the threshold.", 14 | "type": "float", 15 | "default": 0.33 16 | }, 17 | "mor_ch": { 18 | "des": "Height of the closing kernel of morphological transform.", 19 | "type": "float", 20 | "default": 0.1 21 | }, 22 | "mor_cw": { 23 | "des": "Width of the closing kernel of morphological transform.", 24 | "type": "float", 25 | "default": 0.1 26 | }, 27 | "mor_oh": { 28 | "des": "Height of the opening kernel of morphological transform.", 29 | "type": "float", 30 | "default": 0.05 31 | }, 32 | "mor_ow": { 33 | "des": "Width of the opening kernel of morphological transform.", 34 | "type": "float", 35 | "default": 0.05 36 | }, 37 | "mor_ds": { 38 | "des": "Length of the w and h of the dilation kernel.", 39 | "type": "float", 40 | "default": 0.04 41 | }, 42 | "cwhratio": { 43 | "des": "Minimum ratio of w/h and h/w of the contour rectangle.", 44 | "type": "float", 45 | "default": 1.5 46 | }, 47 | "rlbpmin": { 48 | "des": "Ratio to the maximum of lbp matrix. Only values ABOVE this range will be selected.", 49 | "type": "float", 50 | "default": 0.03 51 | }, 52 | "ramax": { 53 | "des": "Ratio to the maximum of lbp matrix. Only values BELOW this range will be selected.", 54 | "type": "float", 55 | "default": 0.3 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /examples/test_plot.py: -------------------------------------------------------------------------------- 1 | from simdat.core import plot 2 | pl = plot.PLOT() 3 | a = [[1, 2, 3, 4, 5], 4 | [2, 2, 2, 2, 2], 5 | [1, 1, 1, 1, 1], 6 | [1, 2, 3, 4, 5], 7 | [5, 4, 3, 2, 1]] 8 | 9 | b = [[[1, 2, 3, 4, 5], [2, 2, 2, 2, 2]], 10 | [[-1, -1, -1, -1, -1],[5, 4, 3, 2, 1]]] 11 | 12 | c = [[1, 2, 3, 4, 5], [2, 2, 2, 2, 2]] 13 | d = [30, 50, 15, 5] 14 | # Example to draw multiple bars 15 | 16 | # xticks = [2007, 2008, 2009, 2010, 2011, 17 | # 2012, 2013, 2014, 2015] 18 | # legend = ['Average Return(%)', 'Accuracy(%)'] 19 | # c = [[57.17,2.57, -30.52, 51.59,45.83,35.57,49.57,75.92,17.42], 20 | # [64.7, 62.9, 67.9, 67, 63.3, 64.1, 64.3, 63, 64]] 21 | # title = 'TW 3231 Average Revenue vs Accuracy' 22 | # pl.plot_multi_bars(c, xticks=xticks, legend=legend, title=title, 23 | # color='blue', leg_loc='rb') 24 | 25 | # Example to draw two 1D distributions with different axises 26 | # pl.diff_axis_1D(c, legend=legend, leg_loc='lt', xticks=xticks) 27 | 28 | # Example to draw 1D distributions 29 | pl.plot_1D_dists(a, leg_loc='rt') 30 | 31 | # Example to draw 2D distributions 32 | # pl.plot_2D_dists(a, clear=False) 33 | 34 | # Example to draw scatter plot of classified data 35 | # pl.plot_classes(b) 36 | 37 | # Example to draw stacked bars 38 | # pl.plot_stacked_bar(a, color='brown') 39 | 40 | # Example to draw pie chart 41 | # pl.plot_pie(d, expl=2) 42 | 43 | # Example to draw histogram chart 44 | # pl.histogram(d) 45 | 46 | # Example to draw matrix 47 | # pl.plot_matrix(a, show_text=False, color='viridis') 48 | 49 | # Example to draw bars with errors 50 | # err = [1, 3, 2, 5] 51 | # pl.plot_single_bar(d, err=err, xrotation=0, width=0.5) 52 | 53 | # Example to patch a shape to the existing figure 54 | # x = (1000, 1200) 55 | # y = (1500, 2000) 56 | # pl.patch_line(x, y, clear=False, fname=None) 57 | # pl.patch_ellipse(0.5, 0.5, w=10, h=5, angle=45) 58 | # pl.patch_rectangle(0, 0, w=1000, h=500, clear=False, fname=None) 59 | # pl.patch_arrow(10, 20, width=100, fill=True, clear=False) 60 | # pl.patch_textbox(0.5, 0.5, 'I hate to plot') 61 | 62 | -------------------------------------------------------------------------------- /fonts/noto/NotoSansCJKtc-Black.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/fonts/noto/NotoSansCJKtc-Black.otf -------------------------------------------------------------------------------- /fonts/noto/NotoSansCJKtc-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/fonts/noto/NotoSansCJKtc-Bold.otf -------------------------------------------------------------------------------- /fonts/noto/NotoSansCJKtc-DemiLight.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/fonts/noto/NotoSansCJKtc-DemiLight.otf -------------------------------------------------------------------------------- /fonts/noto/NotoSansCJKtc-Light.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/fonts/noto/NotoSansCJKtc-Light.otf -------------------------------------------------------------------------------- /fonts/noto/NotoSansCJKtc-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/fonts/noto/NotoSansCJKtc-Medium.otf -------------------------------------------------------------------------------- /fonts/noto/NotoSansCJKtc-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/fonts/noto/NotoSansCJKtc-Regular.otf -------------------------------------------------------------------------------- /fonts/noto/NotoSansCJKtc-Thin.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/fonts/noto/NotoSansCJKtc-Thin.otf -------------------------------------------------------------------------------- /fonts/noto/NotoSansMonoCJKtc-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/fonts/noto/NotoSansMonoCJKtc-Bold.otf -------------------------------------------------------------------------------- /fonts/noto/NotoSansMonoCJKtc-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/fonts/noto/NotoSansMonoCJKtc-Regular.otf -------------------------------------------------------------------------------- /hypercolumn/finetune.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | import time 4 | import numpy as np 5 | from keras.optimizers import SGD 6 | from simdat.core import dp_models 7 | from simdat.core import ml 8 | from simdat.core import plot 9 | from simdat.core import image 10 | 11 | im = image.IMAGE() 12 | pl = plot.PLOT() 13 | mlr = ml.MLRun() 14 | 15 | t0 = time.time() 16 | mdls = dp_models.DPModel() 17 | imnet = dp_models.ImageNet() 18 | 19 | weight_path = '/home/tammy/SOURCES/keras/examples/vgg16_weights.h5' 20 | t0 = pl.print_time(t0, 'initiate') 21 | 22 | model = mdls.VGG_16(weight_path) 23 | t0 = pl.print_time(t0, 'load weights') 24 | sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True) 25 | model.compile(optimizer=sgd, loss='categorical_crossentropy') 26 | t0 = pl.print_time(t0, 'compile') 27 | 28 | imgs = im.find_images() 29 | X = [] 30 | Y = [] 31 | 32 | for fimg in imgs: 33 | _cls_ix = int(mlr.get_class_from_path(fimg)) 34 | _cls = [0]*1000 35 | _cls[_cls_ix-1] = 1 36 | Y.append(_cls) 37 | _img_original = im.read(fimg, size=(224, 224)) 38 | _img = _img_original.transpose((2, 0, 1)) 39 | X.append(_img) 40 | 41 | X = np.array(X) 42 | Y = np.array(Y) 43 | 44 | train_X, test_X, train_Y, test_Y = mlr.split_samples(X, Y) 45 | 46 | for stack in ['conv1', 'conv2', 'conv3', 'conv4', 'conv5']: 47 | for l in mdls.layers[stack]: 48 | l.trainable = False 49 | 50 | batch_size = 128 51 | nb_epoch = 5 52 | 53 | model.fit(train_X, train_Y, 54 | batch_size=batch_size, nb_epoch=nb_epoch, 55 | show_accuracy=True, verbose=1, 56 | validation_data=(test_X, test_Y)) 57 | score = model.evaluate(test_X, test_Y, show_accuracy=True, verbose=0) 58 | print('Test score:', score[0]) 59 | print('Test accuracy:', score[1]) 60 | 61 | -------------------------------------------------------------------------------- /hypercolumn/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import cv2 3 | import time 4 | import numpy as np 5 | from keras.optimizers import SGD 6 | from simdat.core import dp_models 7 | from simdat.core import plot 8 | from simdat.core import image 9 | from simdat.core import ml 10 | 11 | t0 = time.time() 12 | mdls = dp_models.DPModel() 13 | imnet = dp_models.ImageNet() 14 | im = image.IMAGE() 15 | pl = plot.PLOT() 16 | mlr = ml.SVMRun() 17 | 18 | weight_path = '/tammy/SOURCES/keras/examples/vgg16_weights.h5' 19 | img_path = 'images/0001/airportwaitingarea_0004.jpg' 20 | t0 = pl.print_time(t0, 'initiate') 21 | 22 | model = mdls.VGG_16(weight_path) 23 | t0 = pl.print_time(t0, 'load weights') 24 | sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True) 25 | model.compile(optimizer=sgd, loss='categorical_crossentropy') 26 | t0 = pl.print_time(t0, 'compile') 27 | 28 | imgs = im.find_images() 29 | t0 = pl.print_time(t0, 'find images') 30 | X = [] 31 | Y = [] 32 | 33 | for fimg in imgs: 34 | t0 = pl.print_time(t0, 'compute for one image') 35 | print('Processing %s' % fimg) 36 | _cls = int(mlr.get_class_from_path(fimg)) 37 | Y.append(_cls) 38 | name, ext = os.path.splitext(fimg) 39 | img_original = im.read(fimg, size=(224, 224)) 40 | img = img_original.transpose((2, 0, 1)) 41 | img = np.expand_dims(img, axis=0) 42 | 43 | layers_extract = [3, 8, 15, 22, 29] 44 | hc = mdls.extract_hypercolumn(model, layers_extract, img) 45 | # new_shape = 224*224 46 | # ave = np.average(hc.transpose(1, 2, 0), axis=2).reshape(new_shape) 47 | # X.append(ave) 48 | X.append(hc.ravel()) 49 | 50 | mf = mlr.run(X, Y) 51 | -------------------------------------------------------------------------------- /models/inception-v3.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Original source see https://goo.gl/ztgFY7 3 | ''' 4 | from keras.models import Model 5 | from keras.layers import ( 6 | Input, 7 | Dense, 8 | Flatten, 9 | merge, 10 | Lambda 11 | ) 12 | from keras.layers.convolutional import ( 13 | Convolution2D, 14 | MaxPooling2D, 15 | AveragePooling2D, 16 | ZeroPadding2D 17 | ) 18 | from keras.layers.normalization import BatchNormalization 19 | from keras.regularizers import l2 20 | import keras.backend as K 21 | 22 | 23 | # Evidently this model breaks Python's default recursion limit 24 | # This is a theano issue 25 | import sys 26 | sys.setrecursionlimit(10000) 27 | 28 | 29 | def BNConv(nb_filter, nb_row, nb_col, w_decay, subsample=(1, 1), border_mode="same"): 30 | def f(input): 31 | conv = Convolution2D(nb_filter=nb_filter, nb_row=nb_row, nb_col=nb_col, subsample=subsample, 32 | border_mode=border_mode, activation="relu", 33 | W_regularizer=l2(w_decay) if w_decay else None, init="he_normal")(input) 34 | return BatchNormalization(mode=0, axis=1)(conv) 35 | return f 36 | 37 | 38 | def inception_v3(w_decay=None): 39 | input = Input(shape=(3, 299, 299)) 40 | 41 | conv_1 = BNConv(32, 3, 3, w_decay, subsample=(2, 2), border_mode="valid")(input) 42 | conv_2 = BNConv(32, 3, 3, w_decay, border_mode="valid")(conv_1) 43 | conv_3 = BNConv(64, 3, 3, w_decay)(conv_2) 44 | pool_4 = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), border_mode="valid")(conv_3) 45 | 46 | conv_5 = BNConv(80, 1, 1, w_decay)(pool_4) 47 | conv_6 = BNConv(192, 3, 3, w_decay, border_mode="valid")(conv_5) 48 | pool_7 = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), border_mode="valid")(conv_6) 49 | 50 | inception_8 = InceptionFig5(w_decay)(pool_7) 51 | inception_9 = InceptionFig5(w_decay)(inception_8) 52 | inception_10 = InceptionFig5(w_decay)(inception_9) 53 | 54 | inception_11 = DimReductionA(w_decay)(inception_10) 55 | 56 | inception_12 = InceptionFig6(w_decay)(inception_11) 57 | inception_13 = InceptionFig6(w_decay)(inception_12) 58 | inception_14 = InceptionFig6(w_decay)(inception_13) 59 | inception_15 = InceptionFig6(w_decay)(inception_14) 60 | inception_16 = InceptionFig6(w_decay)(inception_15) 61 | 62 | inception_17 = DimReductionB(w_decay)(inception_16) 63 | 64 | inception_18 = InceptionFig7(w_decay)(inception_17) 65 | inception_19 = InceptionFig7(w_decay)(inception_18) 66 | 67 | pool_20 = Lambda(lambda x: K.mean(x, axis=(2, 3)), output_shape=(2048, ))(inception_19) 68 | 69 | model = Model(input, pool_20) 70 | 71 | return model 72 | 73 | 74 | def InceptionFig5(w_decay): 75 | def f(input): 76 | 77 | # Tower A 78 | conv_a1 = BNConv(64, 1, 1, w_decay)(input) 79 | conv_a2 = BNConv(96, 3, 3, w_decay)(conv_a1) 80 | conv_a3 = BNConv(96, 3, 3, w_decay)(conv_a2) 81 | 82 | # Tower B 83 | conv_b1 = BNConv(48, 1, 1, w_decay)(input) 84 | conv_b2 = BNConv(64, 3, 3, w_decay)(conv_b1) 85 | 86 | # Tower C 87 | pool_c1 = AveragePooling2D(pool_size=(3, 3), strides=(1, 1), border_mode="same")(input) 88 | conv_c2 = BNConv(64, 1, 1, w_decay)(pool_c1) 89 | 90 | # Tower D 91 | conv_d1 = BNConv(64, 1, 1, w_decay)(input) 92 | 93 | return merge([conv_a3, conv_b2, conv_c2, conv_d1], mode='concat', concat_axis=1) 94 | 95 | return f 96 | 97 | 98 | def InceptionFig6(w_decay): 99 | def f(input): 100 | conv_a1 = BNConv(128, 1, 1, w_decay)(input) 101 | conv_a2 = BNConv(128, 1, 7, w_decay)(conv_a1) 102 | conv_a3 = BNConv(128, 7, 1, w_decay)(conv_a2) 103 | conv_a4 = BNConv(128, 1, 7, w_decay)(conv_a3) 104 | conv_a5 = BNConv(192, 7, 1, w_decay)(conv_a4) 105 | 106 | # Tower B 107 | conv_b1 = BNConv(128, 1, 1, w_decay)(input) 108 | conv_b2 = BNConv(128, 1, 7, w_decay)(conv_b1) 109 | conv_b3 = BNConv(192, 7, 1, w_decay)(conv_b2) 110 | 111 | # Tower C 112 | pool_c1 = AveragePooling2D(pool_size=(3, 3), strides=(1, 1), border_mode="same")(input) 113 | conv_c2 = BNConv(192, 1, 1, w_decay)(pool_c1) 114 | 115 | # Tower D 116 | conv_d = BNConv(192, 1, 1, w_decay)(input) 117 | 118 | return merge([conv_a5, conv_b3, conv_c2, conv_d], mode="concat", concat_axis=1) 119 | 120 | return f 121 | 122 | 123 | def InceptionFig7(w_decay): 124 | def f(input): 125 | # Tower A 126 | conv_a1 = BNConv(448, 1, 1, w_decay)(input) 127 | conv_a2 = BNConv(384, 3, 3, w_decay)(conv_a1) 128 | conv_a3 = BNConv(384, 1, 3, w_decay)(conv_a2) 129 | conv_a4 = BNConv(384, 3, 1, w_decay)(conv_a3) 130 | 131 | # Tower B 132 | conv_b1 = BNConv(384, 1, 1, w_decay)(input) 133 | conv_b2 = BNConv(384, 1, 3, w_decay)(conv_b1) 134 | conv_b3 = BNConv(384, 3, 1, w_decay)(conv_b2) 135 | 136 | # Tower C 137 | pool_c1 = AveragePooling2D(pool_size=(3, 3), strides=(1, 1), border_mode="same")(input) 138 | conv_c2 = BNConv(192, 1, 1, w_decay)(pool_c1) 139 | 140 | # Tower D 141 | conv_d = BNConv(320, 1, 1, w_decay)(input) 142 | 143 | return merge([conv_a4, conv_b3, conv_c2, conv_d], mode="concat", concat_axis=1) 144 | 145 | return f 146 | 147 | 148 | def DimReductionA(w_decay): 149 | def f(input): 150 | conv_a1 = BNConv(64, 1, 1, w_decay)(input) 151 | conv_a2 = BNConv(96, 3, 3, w_decay)(conv_a1) 152 | conv_a3 = BNConv(96, 3, 3, w_decay, subsample=(2, 2), border_mode="valid")(conv_a2) 153 | 154 | # another inconsistency between model.txt and the paper 155 | # the Fig 10 in the paper shows a 1x1 convolution before 156 | # the 3x3. Going with model.txt 157 | conv_b = BNConv(384, 3, 3, w_decay, subsample=(2, 2), border_mode="valid")(input) 158 | 159 | pool_c = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), border_mode="valid")(input) 160 | 161 | return merge([conv_a3, conv_b, pool_c], mode="concat", concat_axis=1) 162 | return f 163 | 164 | 165 | def DimReductionB(w_decay): 166 | def f(input): 167 | # Tower A 168 | conv_a1 = BNConv(192, 1, 1, w_decay)(input) 169 | conv_a2 = BNConv(320, 3, 3, w_decay, subsample=(2, 2), border_mode="valid")(conv_a1) 170 | 171 | # Tower B 172 | conv_b1 = BNConv(192, 1, 1, w_decay)(input) 173 | conv_b2 = BNConv(192, 1, 7, w_decay)(conv_b1) 174 | conv_b3 = BNConv(192, 7, 1, w_decay)(conv_b2) 175 | conv_b4 = BNConv(192, 3, 3, w_decay, subsample=(2, 2), border_mode="valid")(conv_b3) 176 | 177 | # Tower C 178 | pool_c = MaxPooling2D(pool_size=(3, 3), strides=(2, 2), border_mode="valid")(input) 179 | 180 | return merge([conv_a2, conv_b4, pool_c], mode="concat", concat_axis=1) 181 | return f 182 | 183 | 184 | def main(): 185 | import time 186 | start = time.time() 187 | model = inception_v3() 188 | duration = time.time() - start 189 | print "{} s to make model".format(duration) 190 | start = time.time() 191 | model.output 192 | duration = time.time() - start 193 | print "{} s to get output".format(duration) 194 | start = time.time() 195 | model.compile(loss="categorical_crossentropy", optimizer="sgd") 196 | # model.compile(loss={"distance": "binary_crossentropy"}, optimizer="sgd") 197 | duration = time.time() - start 198 | print "{} s to get compile".format(duration) 199 | 200 | if __name__ == '__main__': 201 | main() 202 | -------------------------------------------------------------------------------- /models/vgg-16.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Copied from https://goo.gl/qqM88H 3 | ''' 4 | 5 | from keras.models import Sequential 6 | from keras.layers.core import Flatten, Dense, Dropout 7 | from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D 8 | from keras.optimizers import SGD 9 | import cv2, numpy as np 10 | 11 | def VGG_16(weights_path=None): 12 | model = Sequential() 13 | model.add(ZeroPadding2D((1,1),input_shape=(3,224,224))) 14 | model.add(Convolution2D(64, 3, 3, activation='relu')) 15 | model.add(ZeroPadding2D((1,1))) 16 | model.add(Convolution2D(64, 3, 3, activation='relu')) 17 | model.add(MaxPooling2D((2,2), strides=(2,2))) 18 | 19 | model.add(ZeroPadding2D((1,1))) 20 | model.add(Convolution2D(128, 3, 3, activation='relu')) 21 | model.add(ZeroPadding2D((1,1))) 22 | model.add(Convolution2D(128, 3, 3, activation='relu')) 23 | model.add(MaxPooling2D((2,2), strides=(2,2))) 24 | 25 | model.add(ZeroPadding2D((1,1))) 26 | model.add(Convolution2D(256, 3, 3, activation='relu')) 27 | model.add(ZeroPadding2D((1,1))) 28 | model.add(Convolution2D(256, 3, 3, activation='relu')) 29 | model.add(ZeroPadding2D((1,1))) 30 | model.add(Convolution2D(256, 3, 3, activation='relu')) 31 | model.add(MaxPooling2D((2,2), strides=(2,2))) 32 | 33 | model.add(ZeroPadding2D((1,1))) 34 | model.add(Convolution2D(512, 3, 3, activation='relu')) 35 | model.add(ZeroPadding2D((1,1))) 36 | model.add(Convolution2D(512, 3, 3, activation='relu')) 37 | model.add(ZeroPadding2D((1,1))) 38 | model.add(Convolution2D(512, 3, 3, activation='relu')) 39 | model.add(MaxPooling2D((2,2), strides=(2,2))) 40 | 41 | model.add(ZeroPadding2D((1,1))) 42 | model.add(Convolution2D(512, 3, 3, activation='relu')) 43 | model.add(ZeroPadding2D((1,1))) 44 | model.add(Convolution2D(512, 3, 3, activation='relu')) 45 | model.add(ZeroPadding2D((1,1))) 46 | model.add(Convolution2D(512, 3, 3, activation='relu')) 47 | model.add(MaxPooling2D((2,2), strides=(2,2))) 48 | 49 | model.add(Flatten()) 50 | model.add(Dense(4096, activation='relu')) 51 | model.add(Dropout(0.5)) 52 | model.add(Dense(4096, activation='relu')) 53 | model.add(Dropout(0.5)) 54 | model.add(Dense(1000, activation='softmax')) 55 | 56 | if weights_path: 57 | model.load_weights(weights_path) 58 | 59 | return model 60 | 61 | if __name__ == "__main__": 62 | im = cv2.resize(cv2.imread('cat.jpg'), (224, 224)).astype(np.float32) 63 | im[:,:,0] -= 103.939 64 | im[:,:,1] -= 116.779 65 | im[:,:,2] -= 123.68 66 | im = im.transpose((2,0,1)) 67 | im = np.expand_dims(im, axis=0) 68 | 69 | # Test pretrained model 70 | model = VGG_16('vgg16_weights.h5') 71 | sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True) 72 | model.compile(optimizer=sgd, loss='categorical_crossentropy') 73 | out = model.predict(im) 74 | print np.argmax(out) 75 | -------------------------------------------------------------------------------- /models/vgg-19.py: -------------------------------------------------------------------------------- 1 | ''' 2 | Copied from https://goo.gl/rvcNDw 3 | ''' 4 | from keras.models import Sequential 5 | from keras.layers.core import Flatten, Dense, Dropout 6 | from keras.layers.convolutional import Convolution2D, MaxPooling2D, ZeroPadding2D 7 | from keras.optimizers import SGD 8 | import cv2, numpy as np 9 | 10 | def VGG_19(weights_path=None): 11 | model = Sequential() 12 | model.add(ZeroPadding2D((1,1),input_shape=(3,224,224))) 13 | model.add(Convolution2D(64, 3, 3, activation='relu')) 14 | model.add(ZeroPadding2D((1,1))) 15 | model.add(Convolution2D(64, 3, 3, activation='relu')) 16 | model.add(MaxPooling2D((2,2), strides=(2,2))) 17 | 18 | model.add(ZeroPadding2D((1,1))) 19 | model.add(Convolution2D(128, 3, 3, activation='relu')) 20 | model.add(ZeroPadding2D((1,1))) 21 | model.add(Convolution2D(128, 3, 3, activation='relu')) 22 | model.add(MaxPooling2D((2,2), strides=(2,2))) 23 | 24 | model.add(ZeroPadding2D((1,1))) 25 | model.add(Convolution2D(256, 3, 3, activation='relu')) 26 | model.add(ZeroPadding2D((1,1))) 27 | model.add(Convolution2D(256, 3, 3, activation='relu')) 28 | model.add(ZeroPadding2D((1,1))) 29 | model.add(Convolution2D(256, 3, 3, activation='relu')) 30 | model.add(ZeroPadding2D((1,1))) 31 | model.add(Convolution2D(256, 3, 3, activation='relu')) 32 | model.add(MaxPooling2D((2,2), strides=(2,2))) 33 | 34 | model.add(ZeroPadding2D((1,1))) 35 | model.add(Convolution2D(512, 3, 3, activation='relu')) 36 | model.add(ZeroPadding2D((1,1))) 37 | model.add(Convolution2D(512, 3, 3, activation='relu')) 38 | model.add(ZeroPadding2D((1,1))) 39 | model.add(Convolution2D(512, 3, 3, activation='relu')) 40 | model.add(ZeroPadding2D((1,1))) 41 | model.add(Convolution2D(512, 3, 3, activation='relu')) 42 | model.add(MaxPooling2D((2,2), strides=(2,2))) 43 | 44 | model.add(ZeroPadding2D((1,1))) 45 | model.add(Convolution2D(512, 3, 3, activation='relu')) 46 | model.add(ZeroPadding2D((1,1))) 47 | model.add(Convolution2D(512, 3, 3, activation='relu')) 48 | model.add(ZeroPadding2D((1,1))) 49 | model.add(Convolution2D(512, 3, 3, activation='relu')) 50 | model.add(ZeroPadding2D((1,1))) 51 | model.add(Convolution2D(512, 3, 3, activation='relu')) 52 | model.add(MaxPooling2D((2,2), strides=(2,2))) 53 | 54 | model.add(Flatten()) 55 | model.add(Dense(4096, activation='relu')) 56 | model.add(Dropout(0.5)) 57 | model.add(Dense(4096, activation='relu')) 58 | model.add(Dropout(0.5)) 59 | model.add(Dense(1000, activation='softmax')) 60 | 61 | if weights_path: 62 | model.load_weights(weights_path) 63 | 64 | return model 65 | 66 | if __name__ == "__main__": 67 | im = cv2.resize(cv2.imread('cat.jpg'), (224, 224)).astype(np.float32) 68 | im[:,:,0] -= 103.939 69 | im[:,:,1] -= 116.779 70 | im[:,:,2] -= 123.68 71 | im = im.transpose((2,0,1)) 72 | im = np.expand_dims(im, axis=0) 73 | 74 | # Test pretrained model 75 | model = VGG_19('vgg19_weights.h5') 76 | sgd = SGD(lr=0.1, decay=1e-6, momentum=0.9, nesterov=True) 77 | model.compile(optimizer=sgd, loss='categorical_crossentropy') 78 | out = model.predict(im) 79 | print np.argmax(out) 80 | -------------------------------------------------------------------------------- /openface/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/openface/__init__.py -------------------------------------------------------------------------------- /openface/maps/6-people-map.txt: -------------------------------------------------------------------------------- 1 | ZhaoWei 趙薇 赵薇 person-1 2 | YuChengCing 庾澄慶 庾澄庆 person-2 3 | WangFong 汪峰 汪峰 person-3 4 | NaYing 那英 那英 person-4 5 | TongDaWei 佟大為 佟大为 person-5 6 | ChouJieLun 周杰倫 周杰伦 person-6 7 | 郭采潔 郭采洁 person-7 8 | 郭碧婷 郭碧婷 person-8 9 | 柯震東 柯震东 person-9 10 | 楊冪 杨幂 person-10 11 | -------------------------------------------------------------------------------- /openface/maps/mapping.json: -------------------------------------------------------------------------------- 1 | {"person-1": 0, "person-10": 1, "person-3": 3, "person-4": 4, "person-5": 5, "person-6": 6, "person-7": 7, "person-8": 8, "person-9": 9, "person-2": 2} -------------------------------------------------------------------------------- /openface/oftools.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import logging 4 | import numpy as np 5 | from simdat.core import tools 6 | from simdat.core import plot 7 | from simdat.core import ml 8 | from simdat.core import image 9 | from simdat.core import args 10 | 11 | io = tools.MLIO() 12 | pl = plot.PLOT() 13 | mlr = ml.MLRun() 14 | 15 | 16 | class OFArgs(args.Args): 17 | def _add_args(self): 18 | """Init arguments of openface""" 19 | self._add_of_args() 20 | 21 | def _add_of_args(self): 22 | """Add additional arguments for OpenFace""" 23 | 24 | self.pathOF = os.path.join(os.getenv("HOME"), 'openface') 25 | self.pathdlib = os.path.join(os.getenv("HOME"), 26 | 'src', 'dlib-18.16', 27 | 'python_examples') 28 | self.parentModel = 'models' 29 | self.parentdlibModel = 'dlib' 30 | self.fdlibFaceMean = 'mean.csv' 31 | self.fdlibPredictor = 'shape_predictor_68_face_landmarks.dat' 32 | self.parentOFModel = 'openface' 33 | self.fmodel = 'nn4.small2.v1.t7' 34 | self.imgDim = 96 35 | # tightcrop/affine/perspective/homography 36 | self.align_method = 'affine' 37 | self.cuda = True 38 | self.outf = './result.json' 39 | 40 | self.pathdlibMean = None 41 | self.dlibFacePredictor = None 42 | self.networkModel = None 43 | 44 | 45 | class OFTools(object): 46 | def __init__(self): 47 | pass 48 | 49 | def pick_reps(self, dbs, dir_path=None, l=2): 50 | """Pick entries which matched the images existing in 51 | a specified directory from multiple db json files 52 | 53 | @param dbs: list of the input db 54 | 55 | Keyword arguments: 56 | dir_path: parent directory of the images 57 | l: level of path suffix (default: 2) 58 | 59 | """ 60 | import pandas as pd 61 | im = image.IMAGE() 62 | img_sufs = im.find_images(dir_path=dir_path) 63 | img_sufs = [im.path_suffix(x, level=l) for x in img_sufs] 64 | df = io.read_jsons_to_df(dbs, orient='index') 65 | df['path_suf'] = df['path'].apply(lambda x: im.path_suffix(x, level=l)) 66 | df = df[df['path_suf'].isin(img_sufs)] 67 | io.write_df_json(df, fname='./picked_rep.json') 68 | return df 69 | 70 | def read_df(self, inf, dtype='test', mpf='./mapping.json', 71 | group=False, selclass=None, conv=True): 72 | """Read results as Pandas DataFrame 73 | 74 | @param inf: input file path to be read or a read df 75 | 76 | Keyword arguments: 77 | dtype -- data type, train or test (default: test) 78 | mpf -- file name of the mapping (default: ./mapping.json) 79 | group -- true to group data by path (default: False) 80 | conv -- true to convert class to int according to mpf 81 | 82 | @return results after reading the input db file 83 | if group: 84 | result['data'] = [list[data_from_image_1], 85 | list[data_from_image_2],.. etc] 86 | else: 87 | result['data'] = [data_from_image_1, 88 | data_from_image_2, .. etc] 89 | same for 'pos' and 'target' 90 | result['path'] = list[paths of images] 91 | result['target_names'] = keys of the mapping file 92 | 93 | """ 94 | if type(inf) is str: 95 | df = io.read_json_to_df(inf, orient='index', np=False) 96 | else: 97 | df = inf 98 | _target = 'class' 99 | 100 | if dtype == 'train': 101 | mapping = self.map_cats_int(df, groupby=_target) 102 | print("Map of target - int is written to %s" % mpf) 103 | io.write_json(mapping, fname=mpf) 104 | if conv: 105 | df[_target] = df[_target].apply(lambda x: mapping[x]) 106 | elif dtype == 'test': 107 | mapping = io.parse_json(mpf) 108 | if conv: 109 | df[_target] = df[_target].apply(lambda x: mapping[str(x)]) 110 | 111 | if conv and type(selclass) is int: 112 | df = df[df['class'] == selclass] 113 | res = {'data': [], 'target': [], 'pos': [], 114 | 'path': [], 'mapping': mapping} 115 | if group: 116 | grouped = df.groupby('path') 117 | for name, group in grouped: 118 | gdf = grouped.get_group(name) 119 | res['data'].append(gdf['rep'].tolist()) 120 | res['pos'].append(gdf['pos'].tolist()) 121 | res['target'].append(gdf[_target].tolist()) 122 | res['path'].append(gdf['path'][0]) 123 | else: 124 | res['data'] = df['rep'].tolist() 125 | res['pos'] = df['pos'].tolist() 126 | res['target'] = df[_target].tolist() 127 | res['path'] = df['path'].tolist() 128 | res['target_names'] = self.mapping_keys(mapping) 129 | return res 130 | 131 | def mapping_keys(self, mapping): 132 | """Sort mapping dictionaty and get the keys""" 133 | 134 | from operator import itemgetter 135 | _labels = sorted(mapping.items(), key=itemgetter(1)) 136 | return [i[0] for i in _labels] 137 | 138 | def map_cats_int(self, df, groupby='class'): 139 | """Create a mapping for the categories to integers 140 | 141 | @param df: dataframe to map 142 | 143 | Keyword arguments: 144 | groupby -- keyword of the class to be mapped 145 | 146 | """ 147 | cats = df.groupby(groupby).count().index.tolist() 148 | return dict(zip(cats, range(0, len(cats)))) 149 | 150 | 151 | class OpenFace(OFTools): 152 | def __init__(self, pfs, method='SVC'): 153 | """Init function of OpenFace""" 154 | 155 | self.args = OFArgs(pfs=pfs) 156 | self.set_paths() 157 | self.of_init() 158 | 159 | def of_init(self): 160 | """Init function for child class""" 161 | 162 | pass 163 | 164 | def set_paths(self): 165 | """Check paths used by openface""" 166 | 167 | _model_parent = os.path.join(self.args.pathOF, 168 | self.args.parentModel) 169 | if self.args.pathdlibMean is None: 170 | self.args.pathdlibMean = os.path.join(self.args.pathOF, 171 | "./models/dlib/", 172 | self.args.fdlibFaceMean) 173 | if self.args.dlibFacePredictor is None: 174 | self.args.dlibFacePredictor = os.path.join( 175 | _model_parent, 176 | self.args.parentdlibModel, 177 | self.args.fdlibPredictor 178 | ) 179 | self.args.dlibFacePredictor = str(self.args.dlibFacePredictor) 180 | if self.args.networkModel is None: 181 | self.args.networkModel = os.path.join(_model_parent, 182 | self.args.parentOFModel, 183 | self.args.fmodel) 184 | for attr in self.args.__dict__.keys(): 185 | if attr[:4] == 'path': 186 | io.check_exist(getattr(self.args, attr)) 187 | sys.path.append(self.args.pathdlib) 188 | return 189 | 190 | def get_rep(self, imgPath, net=None, 191 | output=False, class_kwd='person-'): 192 | """Get facenet representation of a image 193 | 194 | @param imgPath: path of the input image 195 | 196 | Keyword arguments: 197 | net -- existing net model 198 | (default: None, re-gen from self.get_net()) 199 | output -- true to output the results (default: False) 200 | * This is different from self.get_reps 201 | class_kwd -- keyword to identify the image class 202 | from path (default: person-) 203 | 204 | """ 205 | print("[oftools] Calculating rep for %s" % imgPath) 206 | io.check_exist(imgPath) 207 | alignedFaces = self.align(imgPath) 208 | if alignedFaces is None: 209 | return alignedFaces 210 | result = {} 211 | for face in alignedFaces: 212 | rep = self.cal_rep(face[0], net=net) 213 | key = io.gen_md5(rep) 214 | result[key] = {'path': imgPath, 'rep': rep, 215 | 'dim': self.args.imgDim, 216 | 'pos': face[1], 217 | 'class': mlr.get_class_from_path(imgPath, 218 | class_kwd)} 219 | if output: 220 | io.check_parent(self.args.outf) 221 | io.write_json(result, fname=self.args.outf) 222 | return result 223 | 224 | def get_reps(self, imgs, net=None, 225 | output=True, class_kwd='person-'): 226 | """Get face representations of multuple images 227 | 228 | @param imgs: a list input image paths 229 | 230 | Keyword arguments: 231 | net -- existing net model 232 | (default: None, re-gen from self.get_net()) 233 | output -- true to output the results (default: True) 234 | class_kwd -- keyword to identify the image class 235 | from path (default: person-) 236 | """ 237 | results = {} 238 | if net is None: 239 | net = self.get_net() 240 | for img in imgs: 241 | r = self.get_rep(img, net=net, output=output, 242 | class_kwd=class_kwd) 243 | if r is not None: 244 | results.update(r) 245 | if output: 246 | io.check_parent(self.args.outf) 247 | io.write_json(results, fname=self.args.outf) 248 | return results 249 | 250 | def cal_distance(self, rep1, rep2): 251 | """ Calculate distance between two representations """ 252 | 253 | d = rep1 - rep2 254 | return np.dot(d, d) 255 | 256 | def compare(self, item1, item2, thre=1.1): 257 | """ Actual function to compare two rep items 258 | 259 | @param item1: rep item of the first image returned by get_reps 260 | @param item2: rep item of the second image returned by get_reps 261 | 262 | Keyword Arguments: 263 | thre -- distance threthold to decide whether two faces are alike 264 | (default: 1.1 which was suggested in the facenet paper) 265 | 266 | @return bsim (True if the two are similar), d (face distance) 267 | 268 | """ 269 | 270 | d = self.cal_distance(item1['rep'], item2['rep']) 271 | bsim = True if d < thre else False 272 | sim = 'LIKELY to be same person' if bsim else 'NOT SIMILAR' 273 | p1 = os.path.basename(item1['path']) 274 | p2 = os.path.basename(item2['path']) 275 | print('[oftools] %s and %s are %s (distance = %.2f)' 276 | % (p1, p2, sim, d)) 277 | return bsim, d 278 | 279 | def align(self, imgPath, write_out=False): 280 | """Get aligned face(s) of a image 281 | 282 | @param imgPath: input image path 283 | 284 | Keyword Arguments: 285 | write_out -- write out aligned faces (default: False) 286 | 287 | """ 288 | import dlib 289 | import cv2 290 | import openface 291 | from openface import AlignDlib 292 | 293 | align = AlignDlib(self.args.dlibFacePredictor) 294 | img = cv2.imread(imgPath) 295 | if img is None: 296 | print("Fail to read image: {}".format(imgPath)) 297 | return None 298 | img = cv2.resize(img, (400, 300)) #TAMMY 299 | 300 | logging.debug(" + Original size: {}".format(img.shape)) 301 | bbs = align.getAllFaceBoundingBoxes(img) 302 | if bbs is None: 303 | print("Fail to detect faces in image: {}".format(imgPath)) 304 | return None 305 | 306 | alignedFaces = [] 307 | logging.debug("Align the face using %s method" 308 | % self.args.align_method) 309 | for bb in bbs: 310 | alignedFace = align.align( 311 | self.args.imgDim, img, bb, 312 | landmarkIndices=openface.AlignDlib.OUTER_EYES_AND_NOSE) 313 | if alignedFace is None: 314 | continue 315 | alignedFaces.append([alignedFace, [bb.left(), bb.top(), 316 | bb.right(), bb.bottom()]]) 317 | 318 | if write_out: 319 | _fname = os.path.basename(imgPath) 320 | fname = _fname.replace('.', '_cut.') 321 | cv2.imwrite(fname, alignedFace) 322 | 323 | if len(alignedFace) < 1: 324 | print("Fail to align image: {}".format(imgPath)) 325 | return None 326 | 327 | return alignedFaces 328 | 329 | def get_net(self): 330 | """Open the pre-trained net""" 331 | 332 | import openface 333 | return openface.TorchNeuralNet(self.args.networkModel, 334 | imgDim=self.args.imgDim, 335 | cuda=self.args.cuda) 336 | 337 | def cal_rep(self, alignedFace, net=None): 338 | """Calculate facenet representation for an aligned face 339 | 340 | @param alignedFace: aligned face 341 | 342 | Keyword arguments: 343 | net -- pre-opened net 344 | 345 | """ 346 | if net is None: 347 | net = self.get_net() 348 | rep = net.forward(alignedFace) 349 | logging.debug("Representation:") 350 | logging.debug(rep) 351 | logging.debug("-----\n") 352 | return rep 353 | -------------------------------------------------------------------------------- /setdevenv: -------------------------------------------------------------------------------- 1 | export PYTHONPATH=$PWD:$PYTHONPATH 2 | 3 | -------------------------------------------------------------------------------- /simdat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tammyyang/simdat/e53233b7e07d08ff30668fec240a1604b10eea55/simdat.jpg -------------------------------------------------------------------------------- /third-party/google-images-download.py: -------------------------------------------------------------------------------- 1 | #Searching and Downloading Google Images/Image Links 2 | 3 | #Import Libraries 4 | 5 | import time #Importing the time library to check the time of code execution 6 | import sys #Importing the System Library 7 | 8 | 9 | 10 | ########### Edit From Here ########### 11 | 12 | #This list is used to search keywords. You can edit this list to search for google images of your choice. You can simply add and remove elements of the list. 13 | search_keyword = ['Australia', 'Pyramid of Giza'] 14 | 15 | #This list is used to further add suffix to your search term. Each element of the list will help you download 100 images. First element is blank which denotes that no suffix is added to the search keyword of the above list. You can edit the list by adding/deleting elements from it.So if the first element of the search_keyword is 'Australia' and the second element of keywords is 'high resolution', then it will search for 'Australia High Resolution' 16 | keywords = ['',' high resolution',' paintings',' at night',' from top'] 17 | 18 | ########### End of Editing ########### 19 | 20 | 21 | 22 | 23 | #Downloading entire Web Document (Raw Page Content) 24 | def download_page(url): 25 | version = (3,0) 26 | cur_version = sys.version_info 27 | if cur_version >= version: #If the Current Version of Python is 3.0 or above 28 | import urllib.request #urllib library for Extracting web pages 29 | try: 30 | headers = {} 31 | headers['User-Agent'] = "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.27 Safari/537.17" 32 | req = urllib.request.Request(url, headers = headers) 33 | resp = urllib.request.urlopen(req) 34 | respData = str(resp.read()) 35 | return respData 36 | except Exception as e: 37 | print(str(e)) 38 | else: #If the Current Version of Python is 2.x 39 | import urllib2 40 | try: 41 | headers = {} 42 | headers['User-Agent'] = "Mozilla/5.0 (X11; Linux i686) AppleWebKit/537.17 (KHTML, like Gecko) Chrome/24.0.1312.27 Safari/537.17" 43 | req = urllib2.Request(url, headers = headers) 44 | response = urllib2.urlopen(req) 45 | page = response.read() 46 | return page 47 | except: 48 | return"Page Not found" 49 | 50 | 51 | #Finding 'Next Image' from the given raw page 52 | def _images_get_next_item(s): 53 | start_line = s.find('rg_di') 54 | if start_line == -1: #If no links are found then give an error! 55 | end_quote = 0 56 | link = "no_links" 57 | return link, end_quote 58 | else: 59 | start_line = s.find('"class="rg_di"') 60 | start_content = s.find('imgurl=',start_line+1) 61 | end_content = s.find('&',start_content+1) 62 | content_raw = str(s[start_content+7:end_content]) 63 | return content_raw, end_content 64 | 65 | 66 | #Getting all links with the help of '_images_get_next_image' 67 | def _images_get_all_items(page): 68 | items = [] 69 | while True: 70 | item, end_content = _images_get_next_item(page) 71 | if item == "no_links": 72 | break 73 | else: 74 | items.append(item) #Append all the links in the list named 'Links' 75 | #time.sleep(0.1) #Timer could be used to slow down the request for image downloads 76 | page = page[end_content:] 77 | return items 78 | 79 | 80 | ############## Main Program ############ 81 | t0 = time.time() #start the timer 82 | 83 | #Download Image Links 84 | i= 0 85 | while i" + " Item name = " + str(search_keyword[i]) 88 | print (iteration) 89 | search_keywords = search_keyword[i] 90 | search = search_keywords.replace(' ','%20') 91 | j = 0 92 | while j 0: 14 | ip = ''.join(["http://", args[0], ":8088/"]) 15 | else: 16 | ip = os.getcwd() 17 | 18 | if len(args) > 1: 19 | parent = args[1] 20 | else: 21 | parent = os.getcwd() 22 | print("Looking for images in %s" % parent) 23 | 24 | temp = '/home/tammy/SOURCES/simdat/tools/html_plots.template' 25 | if len(args) > 2: 26 | temp = args[2] 27 | 28 | outf = parent + '/images.html' 29 | title = 'Images' 30 | imgs = imtl.find_images(dir_path=parent) 31 | imgs.sort() 32 | args = {'TITLE': 'Images', 33 | 'ip': ip, 34 | 'imgs': imgs} 35 | content = imtl.read_template(temp, args) 36 | with open(outf, 'w') as f: 37 | print('HTML contents are written to %s' % outf) 38 | f.write(content) 39 | -------------------------------------------------------------------------------- /tools/html_creator_gc.py: -------------------------------------------------------------------------------- 1 | # This is an example to create a html for displaying images 2 | # $python html_creator.py IP PARENT TEMPLATE 3 | # PARENT: parent folder of the images (default $PWD) 4 | # TEMPLATE: jinja template file 5 | # (default: simdat/examples/html_plots.template) 6 | import os 7 | import sys 8 | from simdat.core import image 9 | 10 | imtl = image.IMAGE() 11 | 12 | args = sys.argv[1:] 13 | if len(args) > 0: 14 | ip = ''.join(["http://", args[0], "/~"]) 15 | else: 16 | ip = os.getcwd() 17 | print(ip) 18 | 19 | if len(args) > 1: 20 | parent = args[1] 21 | else: 22 | parent = os.getcwd() 23 | print("Looking for images in %s" % parent) 24 | 25 | temp = '/home/tammy/SOURCES/simdat/tools/html_plots.template' 26 | if len(args) > 2: 27 | temp = args[2] 28 | 29 | outf = parent + '/images.html' 30 | title = 'Images' 31 | imgs = imtl.find_images(dir_path=parent) 32 | imgs.sort() 33 | ip = ip + parent.replace('/home/', '').replace('public_html', '') 34 | args = {'TITLE': 'Images', 35 | 'ip': ip, 36 | 'imgs': imgs} 37 | content = imtl.read_template(temp, args) 38 | with open(outf, 'w') as f: 39 | print('HTML contents are written to %s' % outf) 40 | f.write(content) 41 | -------------------------------------------------------------------------------- /tools/html_plots.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | {{ TITLE }} 4 | 5 | 6 | 7 | 8 | {% for img in imgs %} 9 | {% set f = img.split('/')[-1].split('.')[0] %} 10 | {% set fname = img.split('/')[-1] %} 11 | {% if loop.index %4 == 1 %}{% endif %} 12 | 16 | {% if loop.index %4 == 4 %}{% endif %} 17 | {% endfor %} 18 | {% if imgs | length %4 != 4 %}{% endif %} 19 |
{{ f }}
13 |
20 | 21 | {% for img in imgs %} 22 | {% set f = img.split('/')[-1].split('.')[0] %} 23 | {% set fname = img.split('/')[-1] %} 24 | 25 | 27 | {% endfor %} 28 | -------------------------------------------------------------------------------- /tools/image_downloader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | ''' 4 | This is a simple script to download images from Bing. 5 | One can also replace BingImageCrawler by other crawler easily, 6 | just go to https://pypi.python.org/pypi/icrawler/0.1.5 7 | and you should find easily how to achieve it. 8 | 9 | Usage: 10 | 0. Install icrawler 11 | $pip3 install icrawler 12 | 1. Create download_args.json to contain keywords you want to use: 13 | { 14 | "search_for": { 15 | "apple": ["fruit", "pie"], 16 | "banana": [] 17 | } 18 | } 19 | 2. Execute the script 20 | $./image_downloader.py -n 10 -o 100 21 | 22 | For more details, use ./image_downloader.py --help 23 | 24 | ''' 25 | 26 | import time 27 | import os 28 | import sys 29 | import json 30 | import argparse 31 | from icrawler.builtin import BingImageCrawler 32 | 33 | 34 | def parse_json(fname): 35 | """Parse the input profile 36 | 37 | @param fname: input profile path 38 | @return data: a dictionary with user-defined data for training 39 | 40 | """ 41 | with open(fname) as data_file: 42 | data = json.load(data_file) 43 | return data 44 | 45 | data = parse_json('download_args.json') 46 | search_for = data['search_for'] 47 | 48 | 49 | def check_dir(dirpath): 50 | """Check if a directory exists, create one elsewise.""" 51 | if not os.path.exists(dirpath): 52 | print("Creating %s" % dirpath) 53 | os.makedirs(dirpath) 54 | 55 | 56 | def main(): 57 | parser = argparse.ArgumentParser( 58 | description="Simple tool to download images via Google Search." 59 | ) 60 | parser.add_argument( 61 | "-t", "--test", action='store_true' 62 | ) 63 | parser.add_argument( 64 | "-p", "--path", type=str, default=os.getcwd(), 65 | help="Path to output images" 66 | ) 67 | parser.add_argument( 68 | "-n", "--num", type=int, default=100, 69 | help="How many images do you need." 70 | ) 71 | parser.add_argument( 72 | "--threads", type=int, default=4, 73 | help="Number of threads to run." 74 | ) 75 | parser.add_argument( 76 | "-o", "--offset", type=int, default=0, 77 | help="Offset." 78 | ) 79 | parser.add_argument( 80 | "--min", type=int, default=None, 81 | help="Minimum size of the image." 82 | ) 83 | parser.add_argument( 84 | "--max", type=int, default=None, 85 | help="Maximum size of the image." 86 | ) 87 | 88 | args = parser.parse_args() 89 | 90 | t0 = time.time() 91 | check_dir(args.path) 92 | for kwd in search_for: 93 | subdir = os.path.join(args.path, kwd) 94 | check_dir(subdir) 95 | print(" Item name = ", kwd) 96 | if len(search_for[kwd]) == 0: 97 | bing_crawler = BingImageCrawler(subdir) 98 | bing_crawler.crawl( 99 | keyword=kwd, offset=args.offset, max_num=args.num, 100 | feeder_thr_num=1, parser_thr_num=1, 101 | downloader_thr_num=args.threads, 102 | min_size=args.min, max_size=args.max) 103 | else: 104 | for j in range(0, len(search_for[kwd])): 105 | print(" : %s" % search_for[kwd][j]) 106 | ssubdir = os.path.join(subdir, search_for[kwd][j]) 107 | check_dir(ssubdir) 108 | pure_keyword = '%20' + search_for[kwd][j] 109 | pure_keyword = kwd + pure_keyword.replace(' ', '%20') 110 | bing_crawler = BingImageCrawler(storage={'root_dir': ssubdir}) 111 | bing_crawler.crawl( 112 | keyword=pure_keyword, offset=args.offset, 113 | max_num=args.num, 114 | min_size=args.min, max_size=args.max) 115 | 116 | if __name__ == '__main__': 117 | main() 118 | -------------------------------------------------------------------------------- /tools/pttcrawler.py: -------------------------------------------------------------------------------- 1 | #coding=utf-8 2 | 3 | ''' 4 | Original source from https://github.com/wy36101299/PTTcrawler 5 | 6 | Usage: 7 | 8 | python pttcrawler.py movie 3 9 | ''' 10 | 11 | import re 12 | import sys 13 | import json 14 | import requests 15 | import io 16 | import random 17 | from time import sleep 18 | from datetime import datetime 19 | from bs4 import BeautifulSoup 20 | requests.packages.urllib3.disable_warnings() 21 | 22 | PttName="" 23 | load={ 24 | 'from':'/bbs/'+PttName+'/index.html', 25 | 'yes':'yes' 26 | } 27 | 28 | rs=requests.session() 29 | res=rs.post('https://www.ptt.cc/ask/over18',verify=False,data=load) 30 | FILENAME="" 31 | 32 | def PageCount(PttName): 33 | res=rs.get('https://www.ptt.cc/bbs/'+PttName+'/index.html',verify=False) 34 | soup=BeautifulSoup(res.text,'html.parser') 35 | ALLpageURL = soup.select('.btn.wide')[1]['href'] 36 | ALLpage=int(getPageNumber(ALLpageURL))+1 37 | return ALLpage 38 | 39 | def crawler(PttName,ParsingPage): 40 | ALLpage=PageCount(PttName) 41 | g_id = 0; 42 | 43 | for number in range(ALLpage, ALLpage-int(ParsingPage),-1): 44 | res=rs.get('https://www.ptt.cc/bbs/'+PttName+'/index'+str(number)+'.html',verify=False) 45 | soup = BeautifulSoup(res.text,'html.parser') 46 | for tag in soup.select('div.title'): 47 | try: 48 | atag=tag.find('a') 49 | time=random.uniform(0, 1)/5 50 | #print 'time:',time 51 | sleep(time) 52 | if(atag): 53 | URL=atag['href'] 54 | link='https://www.ptt.cc'+URL 55 | #print link 56 | g_id = g_id+1 57 | parseGos(link,g_id) 58 | except: 59 | print 'error:',URL 60 | 61 | def parseGos(link , g_id): 62 | res=rs.get(link,verify=False) 63 | soup = BeautifulSoup(res.text,'html.parser') 64 | # author 65 | author = soup.select('.article-meta-value')[0].text 66 | #author = soup.find("span", {'class': 'article-meta-value'}).text 67 | #print 'author:',author 68 | # title 69 | title = soup.select('.article-meta-value')[2].text 70 | #print 'title:',title 71 | # date 72 | date = soup.select('.article-meta-value')[3].text 73 | #print 'date:',date 74 | # ip 75 | try: 76 | targetIP=u'※ 發信站: 批踢踢實業坊' 77 | ip = soup.find(string = re.compile(targetIP)) 78 | ip = re.search(r"[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*",ip).group() 79 | except: 80 | ip = "ip is not find" 81 | #print 'ip:',ip 82 | 83 | # content 84 | content = soup.find(id="main-content").text 85 | target_content=u'※ 發信站: 批踢踢實業坊(ptt.cc),' 86 | content = content.split(target_content) 87 | content = content[0].split(date) 88 | main_content = content[1].replace('\n', ' ').replace('\t', ' ') 89 | #print 'content:',main_content 90 | 91 | # message 92 | num , g , b , n ,message = 0,0,0,0,{} 93 | for tag in soup.select('div.push'): 94 | num += 1 95 | push_tag = tag.find("span", {'class': 'push-tag'}).text 96 | #print "push_tag:",push_tag 97 | push_userid = tag.find("span", {'class': 'push-userid'}).text 98 | #print "push_userid:",push_userid 99 | push_content = tag.find("span", {'class': 'push-content'}).text 100 | push_content = push_content[1:] 101 | #print "push_content:",push_content 102 | push_ipdatetime = tag.find("span", {'class': 'push-ipdatetime'}).text 103 | push_ipdatetime = remove(push_ipdatetime, '\n') 104 | #print "push-ipdatetime:",push_ipdatetime 105 | 106 | message[num]={"狀態":push_tag.encode('utf-8'),"留言者":push_userid.encode('utf-8'), 107 | "留言內容":push_content.encode('utf-8'),"留言時間":push_ipdatetime.encode('utf-8')} 108 | if push_tag == u'推 ': 109 | g += 1 110 | elif push_tag == u'噓 ': 111 | b += 1 112 | else: 113 | n += 1 114 | 115 | messageNum = {"g":g,"b":b,"n":n,"all":num} 116 | # json-data type(d) dict 117 | 118 | d={ "a_ID":g_id , "b_作者":author.encode('utf-8'), "c_標題":title.encode('utf-8'), "d_日期":date.encode('utf-8'), 119 | "e_ip":ip.encode('utf-8'), "f_內文":main_content.encode('utf-8'), "g_推文":message,"h_推文總數":messageNum} 120 | json_data = json.dumps(d,ensure_ascii=False,indent=4,sort_keys=True)+',' 121 | store(json_data) 122 | 123 | def store(data): 124 | with open(FILENAME, 'a') as f: 125 | f.write(data) 126 | 127 | def remove(value, deletechars): 128 | for c in deletechars: 129 | value = value.replace(c,'') 130 | return value.rstrip(); 131 | 132 | 133 | def getPageNumber(content) : 134 | startIndex = content.find('index') 135 | endIndex = content.find('.html') 136 | pageNumber = content[startIndex+5 : endIndex] 137 | return pageNumber 138 | 139 | if __name__ == "__main__": 140 | PttName = str(sys.argv[1]) 141 | ParsingPage = int(sys.argv[2]) 142 | FILENAME='data-'+PttName+'-'+datetime.now().strftime('%Y-%m-%d-%H-%M-%S')+'.json' 143 | store('[') 144 | print 'Start parsing [',PttName,']....' 145 | crawler(PttName,ParsingPage) 146 | store(']') 147 | 148 | 149 | with open(FILENAME, 'r') as f: 150 | p = f.read() 151 | with open(FILENAME, 'w') as f: 152 | #f.write(p.replace(',]',']')) 153 | f.write(p[:-2]+']') 154 | 155 | -------------------------------------------------------------------------------- /tools/rename_img_numerical.sh: -------------------------------------------------------------------------------- 1 | a=1 2 | for img in *.jpg; do 3 | new=$(printf "%04d.jpg" "$a") #04 pad to length of 4 4 | mv -i -- "$img" "$new" 5 | echo $img $new 6 | let a=a+1 7 | done 8 | -------------------------------------------------------------------------------- /tools/tf/download_and_preprocess_imagenet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2016 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # ============================================================================== 16 | 17 | # Script to download and preprocess ImageNet Challenge 2012 18 | # training and validation data set. 19 | # 20 | # The final output of this script are sharded TFRecord files containing 21 | # serialized Example protocol buffers. See build_imagenet_data.py for 22 | # details of how the Example protocol buffers contain the ImageNet data. 23 | # 24 | # The final output of this script appears as such: 25 | # 26 | # data_dir/train-00000-of-01024 27 | # data_dir/train-00001-of-01024 28 | # ... 29 | # data_dir/train-00127-of-01024 30 | # 31 | # and 32 | # 33 | # data_dir/validation-00000-of-00128 34 | # data_dir/validation-00001-of-00128 35 | # ... 36 | # data_dir/validation-00127-of-00128 37 | # 38 | # Note that this script may take several hours to run to completion. The 39 | # conversion of the ImageNet data to TFRecords alone takes 2-3 hours depending 40 | # on the speed of your machine. Please be patient. 41 | # 42 | # **IMPORTANT** 43 | # To download the raw images, the user must create an account with image-net.org 44 | # and generate a username and access_key. The latter two are required for 45 | # downloading the raw images. 46 | # 47 | # usage: 48 | # ./download_and_preprocess_imagenet.sh [data-dir] 49 | 50 | DATA_DIR="/home/tammy/imagenet-data/tfdata/" 51 | WORK_DIR="/home/tammy/SOURCES/models/inception/inception/" 52 | LABELS_FILE="${WORK_DIR}/data/imagenet_lsvrc_2015_synsets.txt" 53 | 54 | # Create the output and temporary directories. 55 | SCRATCH_DIR="/home/tammy/imagenet-data/" 56 | 57 | # Note the locations of the train and validation data. 58 | TRAIN_DIRECTORY="${SCRATCH_DIR}train/" 59 | VALIDATION_DIRECTORY="${SCRATCH_DIR}validation/" 60 | 61 | # Preprocess the validation data by moving the images into the appropriate 62 | # sub-directory based on the label (synset) of the image. 63 | echo "Organizing the validation data into sub-directories." 64 | PREPROCESS_VAL_SCRIPT="${WORK_DIR}/data/preprocess_imagenet_validation_data.py" 65 | VAL_LABELS_FILE="${WORK_DIR}/data/imagenet_2012_validation_synset_labels.txt" 66 | 67 | python ${PREPROCESS_VAL_SCRIPT} ${VALIDATION_DIRECTORY} ${VAL_LABELS_FILE} 68 | 69 | # Convert the XML files for bounding box annotations into a single CSV. 70 | echo "Extracting bounding box information from XML." 71 | BOUNDING_BOX_SCRIPT="${WORK_DIR}/data/process_bounding_boxes.py" 72 | BOUNDING_BOX_FILE="${SCRATCH_DIR}/imagenet_2012_bounding_boxes.csv" 73 | BOUNDING_BOX_DIR="${SCRATCH_DIR}bounding_boxes/" 74 | 75 | "${BOUNDING_BOX_SCRIPT}" "${BOUNDING_BOX_DIR}" "${LABELS_FILE}" \ 76 | | sort >"${BOUNDING_BOX_FILE}" 77 | echo "Finished downloading and preprocessing the ImageNet data." 78 | 79 | # Build the TFRecords version of the ImageNet data. 80 | BUILD_SCRIPT="${WORK_DIR}/data/build_imagenet_data.py" 81 | OUTPUT_DIRECTORY="${DATA_DIR}" 82 | IMAGENET_METADATA_FILE="${WORK_DIR}/data/imagenet_metadata.txt" 83 | 84 | python ${BUILD_SCRIPT} \ 85 | --train_directory="${TRAIN_DIRECTORY}" \ 86 | --validation_directory="${VALIDATION_DIRECTORY}" \ 87 | --output_directory="${OUTPUT_DIRECTORY}" \ 88 | --imagenet_metadata_file="${IMAGENET_METADATA_FILE}" \ 89 | --labels_file="${LABELS_FILE}" \ 90 | --bounding_box_file="${BOUNDING_BOX_FILE}" 91 | -------------------------------------------------------------------------------- /tools/tf/download_imagenet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2016 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # ============================================================================== 16 | 17 | # ./download_imagenet.sh [dirname] 18 | set -e 19 | 20 | OUTDIR="/home/tammy/imagenet-data/" 21 | SYNSETS_FILE="/home/tammy/SOURCES/models/inception/inception/data/imagenet_2012_validation_synset_labels.txt" 22 | 23 | CURRENT_DIR=$(pwd) 24 | BBOX_DIR="${OUTDIR}bounding_boxes" 25 | cd "${OUTDIR}" 26 | 27 | # See here for details: http://www.image-net.org/download-bboxes 28 | BBOX_TAR_BALL="${BBOX_DIR}/ILSVRC2012_bbox_train_v2.tar.gz" 29 | tar xzf "${BBOX_TAR_BALL}" -C "${BBOX_DIR}" 30 | 31 | LABELS_ANNOTATED="${BBOX_DIR}/*" 32 | NUM_XML=$(ls -1 ${LABELS_ANNOTATED} | wc -l) 33 | echo "Identified ${NUM_XML} bounding box annotations." 34 | 35 | # Download and uncompress all images from the ImageNet 2012 validation dataset. 36 | # VALIDATION_TARBALL="${OUTDIR}ILSVRC2012_img_val.tar" 37 | # OUTPUT_PATH="${OUTDIR}validation/" 38 | # mkdir -p "${OUTPUT_PATH}" 39 | # tar xf "${VALIDATION_TARBALL}" -C "${OUTPUT_PATH}" 40 | 41 | # Download all images from the ImageNet 2012 train dataset. 42 | # TRAIN_TARBALL="${OUTDIR}ILSVRC2012_img_train.tar" 43 | OUTPUT_PATH="${OUTDIR}train/" 44 | # Un-compress the individual tar-files within the train tar-file. 45 | while read SYNSET; do 46 | # echo "Processing: ${SYNSET}" 47 | FILE="/home/tammy/imagenet-data/ILSVRC2012_img_train/${SYNSET}.tar" 48 | if [ -f $FILE ]; 49 | then 50 | mkdir -p "${OUTPUT_PATH}/${SYNSET}" 51 | rm -rf "${OUTPUT_PATH}/${SYNSET}/*" 52 | 53 | tar xf $FILE -C "${OUTPUT_PATH}/${SYNSET}/" 54 | else 55 | echo "$FILE does not exist." 56 | fi 57 | # echo "Finished processing: ${SYNSET}" 58 | done < "${SYNSETS_FILE}" 59 | -------------------------------------------------------------------------------- /tools/tf/dump_inception_v3_filters.py: -------------------------------------------------------------------------------- 1 | ''' 2 | This is a simple script to convert inception v3 weights 3 | from tensorflow checkpoint files to hdf5. 4 | 5 | Original source from https://github.com/Moodstocks/inception-v3.torch 6 | ''' 7 | import os.path 8 | import re 9 | import sys 10 | import tarfile 11 | 12 | # pylint: disable=unused-import,g-bad-import-order 13 | import tensorflow.python.platform 14 | from six.moves import urllib 15 | import numpy as np 16 | import tensorflow as tf 17 | # pylint: enable=unused-import,g-bad-import-order 18 | 19 | from tensorflow.python.platform import gfile 20 | import h5py 21 | import math 22 | 23 | paddings = {"VALID": [0, 0], "SAME": [1, 1]} 24 | 25 | FLAGS = tf.app.flags.FLAGS 26 | 27 | # classify_image_graph_def.pb: 28 | # Binary representation of the GraphDef protocol buffer. 29 | # imagenet_synset_to_human_label_map.txt: 30 | # Map from synset ID to a human readable string. 31 | # imagenet_2012_challenge_label_map_proto.pbtxt: 32 | # Text representation of a protocol buffer mapping a label to synset ID. 33 | tf.app.flags.DEFINE_string( 34 | 'model_dir', '/home/shared/model_zoo/inception-v3/', 35 | """Path to classify_image_graph_def.pb, """ 36 | """imagenet_synset_to_human_label_map.txt, and """ 37 | """imagenet_2012_challenge_label_map_proto.pbtxt.""") 38 | tf.app.flags.DEFINE_string('image_file', '', 39 | """Absolute path to image file.""") 40 | tf.app.flags.DEFINE_integer('num_top_predictions', 5, 41 | """Display this many predictions.""") 42 | 43 | # pylint: disable=line-too-long 44 | DATA_URL = 'http://download.tensorflow.org/models/image/imagenet/inception-v3-2016-03-01.tar.gz' 45 | # pylint: enable=line-too-long 46 | 47 | 48 | 49 | def create_graph(): 50 | """"Creates a graph from saved GraphDef file and returns a saver.""" 51 | # Creates graph from saved graph_def.pb. 52 | with gfile.FastGFile(os.path.join( 53 | FLAGS.model_dir, 'classify_image_graph_def.pb'), 'r') as f: 54 | graph_def = tf.GraphDef() 55 | graph_def.ParseFromString(f.read()) 56 | _ = tf.import_graph_def(graph_def, name='') 57 | 58 | 59 | def make_padding(padding_name, conv_shape): 60 | if padding_name == "VALID": 61 | return [0, 0] 62 | elif padding_name == "SAME": 63 | return [int(math.ceil(conv_shape[0]/2)), int(math.ceil(conv_shape[1]/2))] 64 | else: 65 | sys.exit('Invalid padding name '+padding_name) 66 | 67 | 68 | def dump_convbn(sess, gname): 69 | conv = sess.graph.get_operation_by_name(gname + '/Conv2D') 70 | 71 | weights = sess.graph.get_tensor_by_name(gname + '/conv2d_params:0').eval() 72 | padding = make_padding(conv.get_attr("padding"), weights.shape) 73 | strides = conv.get_attr("strides") 74 | 75 | beta = sess.graph.get_tensor_by_name(gname + '/batchnorm/beta:0').eval() 76 | gamma = sess.graph.get_tensor_by_name(gname + '/batchnorm/gamma:0').eval() 77 | mean = sess.graph.get_tensor_by_name(gname + '/batchnorm/moving_mean:0').eval() 78 | std = sess.graph.get_tensor_by_name(gname + '/batchnorm/moving_variance:0').eval() 79 | 80 | gname = gname.replace("/", "_") 81 | h5f = h5py.File('dump/'+gname+'.h5', 'w') 82 | h5f.create_dataset("weights", data=weights) 83 | h5f.create_dataset("strides", data=strides) 84 | h5f.create_dataset("padding", data=padding) 85 | h5f.create_dataset("beta", data=beta) 86 | h5f.create_dataset("gamma", data=gamma) 87 | h5f.create_dataset("mean", data=mean) 88 | h5f.create_dataset("std", data=std) 89 | h5f.close() 90 | 91 | def dump_pool(sess, gname): 92 | pool = sess.graph.get_operation_by_name(gname) 93 | ismax = pool.type=='MaxPool' and 1 or 0 94 | ksize = pool.get_attr("ksize") 95 | padding = make_padding(pool.get_attr("padding"), ksize[1:3]) 96 | strides = pool.get_attr("strides") 97 | 98 | gname = gname.replace("/", "_") 99 | h5f = h5py.File('dump/'+gname+'.h5', 'w') 100 | h5f.create_dataset("ismax", data=[ismax]) 101 | h5f.create_dataset("ksize", data=ksize) 102 | h5f.create_dataset("padding", data=padding) 103 | h5f.create_dataset("strides", data=strides) 104 | h5f.close() 105 | 106 | def dump_softmax(sess): 107 | softmax_w = sess.graph.get_tensor_by_name('softmax/weights:0').eval() 108 | softmax_b = sess.graph.get_tensor_by_name('softmax/biases:0').eval() 109 | h5f = h5py.File('dump/softmax.h5', 'w') 110 | h5f.create_dataset("weights", data=softmax_w) 111 | h5f.create_dataset("biases", data=softmax_b) 112 | h5f.close() 113 | 114 | 115 | 116 | def run_inference_on_image(image): 117 | if not gfile.Exists(image): 118 | tf.logging.fatal('File does not exist %s', image) 119 | image_data = gfile.FastGFile(image).read() 120 | 121 | # Creates graph from saved GraphDef. 122 | create_graph() 123 | 124 | with tf.Session() as sess: 125 | 126 | # Run the graph until softmax 127 | softmax_tensor = sess.graph.get_tensor_by_name('softmax:0') 128 | predictions = sess.run(softmax_tensor, 129 | {'DecodeJpeg/contents:0': image_data}) 130 | # print predictions indices and values 131 | predictions = np.squeeze(predictions) 132 | top_k = predictions.argsort()[-FLAGS.num_top_predictions:][::-1] 133 | for p in top_k: 134 | print(p, predictions[p]) 135 | 136 | if not os.path.exists("dump"): 137 | os.makedirs("dump") 138 | 139 | # dump the filters 140 | dump_convbn(sess, 'conv') 141 | dump_convbn(sess, 'conv_1') 142 | dump_convbn(sess, 'conv_2') 143 | dump_pool(sess, 'pool') 144 | dump_convbn(sess, 'conv_3') 145 | dump_convbn(sess, 'conv_4') 146 | dump_pool(sess, 'pool_1') 147 | 148 | # inceptions with 1x1, 3x3, 5x5 convolutions 149 | dump_convbn(sess, 'mixed/conv') 150 | dump_convbn(sess, 'mixed/tower/conv') 151 | dump_convbn(sess, 'mixed/tower/conv_1') 152 | dump_convbn(sess, 'mixed/tower_1/conv') 153 | dump_convbn(sess, 'mixed/tower_1/conv_1') 154 | dump_convbn(sess, 'mixed/tower_1/conv_2') 155 | dump_pool(sess, 'mixed/tower_2/pool') 156 | dump_convbn(sess, 'mixed/tower_2/conv') 157 | 158 | dump_convbn(sess, 'mixed_1/conv') 159 | dump_convbn(sess, 'mixed_1/tower/conv') 160 | dump_convbn(sess, 'mixed_1/tower/conv_1') 161 | dump_convbn(sess, 'mixed_1/tower_1/conv') 162 | dump_convbn(sess, 'mixed_1/tower_1/conv_1') 163 | dump_convbn(sess, 'mixed_1/tower_1/conv_2') 164 | dump_pool(sess, 'mixed_1/tower_2/pool') 165 | dump_convbn(sess, 'mixed_1/tower_2/conv') 166 | 167 | dump_convbn(sess, 'mixed_2/conv') 168 | dump_convbn(sess, 'mixed_2/tower/conv') 169 | dump_convbn(sess, 'mixed_2/tower/conv_1') 170 | dump_convbn(sess, 'mixed_2/tower_1/conv') 171 | dump_convbn(sess, 'mixed_2/tower_1/conv_1') 172 | dump_convbn(sess, 'mixed_2/tower_1/conv_2') 173 | dump_pool(sess, 'mixed_2/tower_2/pool') 174 | dump_convbn(sess, 'mixed_2/tower_2/conv') 175 | 176 | # inceptions with 1x1, 3x3(in sequence) convolutions 177 | dump_convbn(sess, 'mixed_3/conv') 178 | dump_convbn(sess, 'mixed_3/tower/conv') 179 | dump_convbn(sess, 'mixed_3/tower/conv_1') 180 | dump_convbn(sess, 'mixed_3/tower/conv_2') 181 | dump_pool(sess, 'mixed_3/pool') 182 | 183 | # inceptions with 1x1, 7x1, 1x7 convolutions 184 | dump_convbn(sess, 'mixed_4/conv') 185 | dump_convbn(sess, 'mixed_4/tower/conv') 186 | dump_convbn(sess, 'mixed_4/tower/conv_1') 187 | dump_convbn(sess, 'mixed_4/tower/conv_2') 188 | dump_convbn(sess, 'mixed_4/tower_1/conv') 189 | dump_convbn(sess, 'mixed_4/tower_1/conv_1') 190 | dump_convbn(sess, 'mixed_4/tower_1/conv_2') 191 | dump_convbn(sess, 'mixed_4/tower_1/conv_3') 192 | dump_convbn(sess, 'mixed_4/tower_1/conv_4') 193 | dump_pool(sess, 'mixed_4/tower_2/pool') 194 | dump_convbn(sess, 'mixed_4/tower_2/conv') 195 | 196 | dump_convbn(sess, 'mixed_5/conv') 197 | dump_convbn(sess, 'mixed_5/tower/conv') 198 | dump_convbn(sess, 'mixed_5/tower/conv_1') 199 | dump_convbn(sess, 'mixed_5/tower/conv_2') 200 | dump_convbn(sess, 'mixed_5/tower_1/conv') 201 | dump_convbn(sess, 'mixed_5/tower_1/conv_1') 202 | dump_convbn(sess, 'mixed_5/tower_1/conv_2') 203 | dump_convbn(sess, 'mixed_5/tower_1/conv_3') 204 | dump_convbn(sess, 'mixed_5/tower_1/conv_4') 205 | dump_pool(sess, 'mixed_5/tower_2/pool') 206 | dump_convbn(sess, 'mixed_5/tower_2/conv') 207 | 208 | dump_convbn(sess, 'mixed_6/conv') 209 | dump_convbn(sess, 'mixed_6/tower/conv') 210 | dump_convbn(sess, 'mixed_6/tower/conv_1') 211 | dump_convbn(sess, 'mixed_6/tower/conv_2') 212 | dump_convbn(sess, 'mixed_6/tower_1/conv') 213 | dump_convbn(sess, 'mixed_6/tower_1/conv_1') 214 | dump_convbn(sess, 'mixed_6/tower_1/conv_2') 215 | dump_convbn(sess, 'mixed_6/tower_1/conv_3') 216 | dump_convbn(sess, 'mixed_6/tower_1/conv_4') 217 | dump_pool(sess, 'mixed_6/tower_2/pool') 218 | dump_convbn(sess, 'mixed_6/tower_2/conv') 219 | 220 | dump_convbn(sess, 'mixed_7/conv') 221 | dump_convbn(sess, 'mixed_7/tower/conv') 222 | dump_convbn(sess, 'mixed_7/tower/conv_1') 223 | dump_convbn(sess, 'mixed_7/tower/conv_2') 224 | dump_convbn(sess, 'mixed_7/tower_1/conv') 225 | dump_convbn(sess, 'mixed_7/tower_1/conv_1') 226 | dump_convbn(sess, 'mixed_7/tower_1/conv_2') 227 | dump_convbn(sess, 'mixed_7/tower_1/conv_3') 228 | dump_convbn(sess, 'mixed_7/tower_1/conv_4') 229 | dump_pool(sess, 'mixed_7/tower_2/pool') 230 | dump_convbn(sess, 'mixed_7/tower_2/conv') 231 | 232 | # inceptions with 1x1, 3x3, 1x7, 7x1 filters 233 | dump_convbn(sess, 'mixed_8/tower/conv') 234 | dump_convbn(sess, 'mixed_8/tower/conv_1') 235 | dump_convbn(sess, 'mixed_8/tower_1/conv') 236 | dump_convbn(sess, 'mixed_8/tower_1/conv_1') 237 | dump_convbn(sess, 'mixed_8/tower_1/conv_2') 238 | dump_convbn(sess, 'mixed_8/tower_1/conv_3') 239 | dump_pool(sess, 'mixed_8/pool') 240 | 241 | dump_convbn(sess, 'mixed_9/conv') 242 | dump_convbn(sess, 'mixed_9/tower/conv') 243 | dump_convbn(sess, 'mixed_9/tower/mixed/conv') 244 | dump_convbn(sess, 'mixed_9/tower/mixed/conv_1') 245 | dump_convbn(sess, 'mixed_9/tower_1/conv') 246 | dump_convbn(sess, 'mixed_9/tower_1/conv_1') 247 | dump_convbn(sess, 'mixed_9/tower_1/mixed/conv') 248 | dump_convbn(sess, 'mixed_9/tower_1/mixed/conv_1') 249 | dump_pool(sess, 'mixed_9/tower_2/pool') 250 | dump_convbn(sess, 'mixed_9/tower_2/conv') 251 | 252 | dump_convbn(sess, 'mixed_10/conv') 253 | dump_convbn(sess, 'mixed_10/tower/conv') 254 | dump_convbn(sess, 'mixed_10/tower/mixed/conv') 255 | dump_convbn(sess, 'mixed_10/tower/mixed/conv_1') 256 | dump_convbn(sess, 'mixed_10/tower_1/conv') 257 | dump_convbn(sess, 'mixed_10/tower_1/conv_1') 258 | dump_convbn(sess, 'mixed_10/tower_1/mixed/conv') 259 | dump_convbn(sess, 'mixed_10/tower_1/mixed/conv_1') 260 | dump_pool(sess, 'mixed_10/tower_2/pool') 261 | dump_convbn(sess, 'mixed_10/tower_2/conv') 262 | 263 | dump_pool(sess, "pool_3") 264 | dump_softmax(sess) 265 | 266 | 267 | def maybe_download_and_extract(): 268 | """Download and extract model tar file.""" 269 | dest_directory = FLAGS.model_dir 270 | if not os.path.exists(dest_directory): 271 | os.makedirs(dest_directory) 272 | filename = DATA_URL.split('/')[-1] 273 | filepath = os.path.join(dest_directory, filename) 274 | if not os.path.exists(filepath): 275 | def _progress(count, block_size, total_size): 276 | sys.stdout.write('\r>> Downloading %s %.1f%%' % ( 277 | filename, float(count * block_size) / float(total_size) * 100.0)) 278 | sys.stdout.flush() 279 | filepath, _ = urllib.request.urlretrieve(DATA_URL, filepath, 280 | reporthook=_progress) 281 | print() 282 | statinfo = os.stat(filepath) 283 | print('Succesfully downloaded', filename, statinfo.st_size, 'bytes.') 284 | tarfile.open(filepath, 'r:gz').extractall(dest_directory) 285 | 286 | 287 | def main(_): 288 | maybe_download_and_extract() 289 | image = (FLAGS.image_file if FLAGS.image_file else 290 | os.path.join(FLAGS.model_dir, 'cropped_panda.jpg')) 291 | run_inference_on_image(image) 292 | 293 | if __name__ == '__main__': 294 | tf.app.run() 295 | -------------------------------------------------------------------------------- /tools/untar_imagenet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2016 Google Inc. All Rights Reserved. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | # ============================================================================== 16 | 17 | # ./download_imagenet.sh [dirname] 18 | set -e 19 | 20 | OUTDIR="/home/tammy/imagenet-data/" 21 | SYNSETS_FILE="/home/tammy/SOURCES/models/inception/inception/data/imagenet_2012_validation_synset_labels.txt" 22 | 23 | CURRENT_DIR=$(pwd) 24 | BBOX_DIR="${OUTDIR}bounding_boxes" 25 | cd "${OUTDIR}" 26 | 27 | # See here for details: http://www.image-net.org/download-bboxes 28 | BBOX_TAR_BALL="${BBOX_DIR}/ILSVRC2012_bbox_train_v2.tar.gz" 29 | tar xzf "${BBOX_TAR_BALL}" -C "${BBOX_DIR}" 30 | 31 | LABELS_ANNOTATED="${BBOX_DIR}/*" 32 | NUM_XML=$(ls -1 ${LABELS_ANNOTATED} | wc -l) 33 | echo "Identified ${NUM_XML} bounding box annotations." 34 | 35 | # Download and uncompress all images from the ImageNet 2012 validation dataset. 36 | VALIDATION_TARBALL="${OUTDIR}ILSVRC2012_img_val.tar" 37 | OUTPUT_PATH="${OUTDIR}validation/" 38 | mkdir -p "${OUTPUT_PATH}" 39 | tar xf "${VALIDATION_TARBALL}" -C "${OUTPUT_PATH}" 40 | 41 | # Download all images from the ImageNet 2012 train dataset. 42 | TRAIN_TARBALL="${OUTDIR}ILSVRC2012_img_train.tar" 43 | OUTPUT_PATH="${OUTDIR}train/" 44 | # Un-compress the individual tar-files within the train tar-file. 45 | while read SYNSET; do 46 | # echo "Processing: ${SYNSET}" 47 | FILE="/home/tammy/imagenet-data/ILSVRC2012_img_train/${SYNSET}.tar" 48 | if [ -f $FILE ]; 49 | then 50 | mkdir -p "${OUTPUT_PATH}/${SYNSET}" 51 | rm -rf "${OUTPUT_PATH}/${SYNSET}/*" 52 | 53 | tar xf $FILE -C "${OUTPUT_PATH}/${SYNSET}/" 54 | else 55 | echo "$FILE does not exist." 56 | fi 57 | # echo "Finished processing: ${SYNSET}" 58 | done < "${SYNSETS_FILE}" 59 | --------------------------------------------------------------------------------