Commited minutiae
This commit is contained in:
@@ -0,0 +1,294 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Testing CoarseNet\n",
|
||||
"Code for FineNet in paper \"Robust Minutiae Extractor: Integrating Deep Networks and Fingerprint Domain Knowledge\" at ICB 2018: https://arxiv.org/pdf/1712.09401.pdf\n",
|
||||
"\n",
|
||||
"If you use whole or partial function in this code, please cite paper:\n",
|
||||
"\n",
|
||||
" @inproceedings{Nguyen_MinutiaeNet,\n",
|
||||
"\tauthor = {Dinh-Luan Nguyen and Kai Cao and Anil K. Jain},\n",
|
||||
"\ttitle = {Robust Minutiae Extractor: Integrating Deep Networks and Fingerprint Domain Knowledge},\n",
|
||||
"\tbooktitle = {The 11th International Conference on Biometrics, 2018},\n",
|
||||
"\tyear = {2018},\n",
|
||||
"\t}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"To run this script, you need to prepare dataset as follows:\n",
|
||||
"`path/to/dataset/`:\n",
|
||||
" - img_files/*.bmp\n",
|
||||
"\n",
|
||||
"If using groundtruth mask instead of mask generated by CoarseNet:\n",
|
||||
" - seg_files/*.bmp\n",
|
||||
" \n",
|
||||
"## CoarseNet can run with any image size\n",
|
||||
"See [CoarseNet_run.py](https://github.com/luannd/MinutiaeNet/blob/master/CoarseNet/CoarseNet_run.py) if running from command line.\n",
|
||||
"\n",
|
||||
"CoarseNet can be improved by:\n",
|
||||
"- Train on new dataset instead of FVC\n",
|
||||
"- Correct the orientation\n",
|
||||
"- Tune threshold for different dataset\n",
|
||||
"\n",
|
||||
"## CoarseNet can provides:\n",
|
||||
"- Orientation field estimation\n",
|
||||
"- Mask for fingerprint area\n",
|
||||
"- Minutiae location and orientation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Using TensorFlow backend.\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from __future__ import absolute_import\n",
|
||||
"from __future__ import division\n",
|
||||
"\n",
|
||||
"import sys, os\n",
|
||||
"sys.path.append(os.path.realpath('../CoarseNet'))\n",
|
||||
"\n",
|
||||
"os.environ[\"CUDA_VISIBLE_DEVICES\"] = '1'\n",
|
||||
"os.environ['KERAS_BACKEND'] = 'tensorflow'\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"from keras import backend as K\n",
|
||||
"\n",
|
||||
"from MinutiaeNet_utils import *\n",
|
||||
"from CoarseNet_utils import *\n",
|
||||
"from CoarseNet_model import *\n",
|
||||
"import argparse\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"config = K.tf.ConfigProto(gpu_options=K.tf.GPUOptions(allow_growth=True))\n",
|
||||
"sess = K.tf.Session(config=config)\n",
|
||||
"K.set_session(sess)\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"# Prepare dataset for testing. \n",
|
||||
"inference_set = ['../Dataset/CoarseNet_test/',]\n",
|
||||
"\n",
|
||||
"CoarseNet_path = '../Models/CoarseNet.h5'\n",
|
||||
"\n",
|
||||
"output_dir = '../output_CoarseNet/'+datetime.now().strftime('%Y%m%d-%H%M%S')\n",
|
||||
"\n",
|
||||
"FineNet_path = '../Models/FineNet.h5'\n",
|
||||
"\n",
|
||||
"logging = init_log(output_dir)\n",
|
||||
"\n",
|
||||
"# If use FineNet to refine, set into True\n",
|
||||
"isHavingFineNet = False"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"This can test with different folders.\n",
|
||||
"\n",
|
||||
"Threshold for each image is automatically chosen"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"scrolled": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"for i, deploy_set in enumerate(inference_set):\n",
|
||||
" set_name = deploy_set.split('/')[-2]\n",
|
||||
"\n",
|
||||
" # Read image and GT\n",
|
||||
" img_name, folder_name, img_size = get_maximum_img_size_and_names(deploy_set)\n",
|
||||
"\n",
|
||||
" mkdir(output_dir + '/'+ set_name + '/')\n",
|
||||
" mkdir(output_dir + '/' + set_name + '/mnt_results/')\n",
|
||||
" mkdir(output_dir + '/'+ set_name + '/seg_results/')\n",
|
||||
" mkdir(output_dir + '/' + set_name + '/OF_results/')\n",
|
||||
"\n",
|
||||
" logging.info(\"Predicting \\\"%s\\\":\" % (set_name))\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" main_net_model = CoarseNetmodel((None, None, 1), CoarseNet_path, mode='deploy')\n",
|
||||
"\n",
|
||||
" # ====== Load FineNet to verify\n",
|
||||
" if isHavingFineNet == True:\n",
|
||||
" model_FineNet = FineNetmodel(num_classes=2,\n",
|
||||
" pretrained_path=FineNet_path,\n",
|
||||
" input_shape=(224,224,3))\n",
|
||||
"\n",
|
||||
" model_FineNet.compile(loss='categorical_crossentropy',\n",
|
||||
" optimizer=Adam(lr=0),\n",
|
||||
" metrics=['accuracy'])\n",
|
||||
"\n",
|
||||
" for i in xrange(0, len(img_name)):\n",
|
||||
" \n",
|
||||
" logging.info(\"\\\"%s\\\" %d / %d: %s\" % (set_name, i + 1, len(img_name), img_name[i]))\n",
|
||||
"\n",
|
||||
" image = misc.imread(deploy_set + 'img_files/' + img_name[i] + '.bmp', mode='L')# / 255.0\n",
|
||||
"\n",
|
||||
" img_size = image.shape\n",
|
||||
" img_size = np.array(img_size, dtype=np.int32) // 8 * 8\n",
|
||||
" image = image[:img_size[0], :img_size[1]]\n",
|
||||
"\n",
|
||||
" original_image = image.copy()\n",
|
||||
"\n",
|
||||
" # Generate OF\n",
|
||||
" texture_img = FastEnhanceTexture(image, sigma=2.5, show=False)\n",
|
||||
" dir_map, fre_map = get_maps_STFT(texture_img, patch_size=64, block_size=16, preprocess=True)\n",
|
||||
" \n",
|
||||
" image = np.reshape(image, [1, image.shape[0], image.shape[1], 1])\n",
|
||||
"\n",
|
||||
" enh_img, enh_img_imag, enhance_img, ori_out_1, ori_out_2, seg_out, mnt_o_out, mnt_w_out, mnt_h_out, mnt_s_out \\\n",
|
||||
" = main_net_model.predict(image)\n",
|
||||
"\n",
|
||||
" # Use for output mask\n",
|
||||
" round_seg = np.round(np.squeeze(seg_out))\n",
|
||||
" seg_out = 1 - round_seg\n",
|
||||
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 10))\n",
|
||||
" seg_out = cv2.morphologyEx(seg_out, cv2.MORPH_CLOSE, kernel)\n",
|
||||
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7))\n",
|
||||
" seg_out = cv2.morphologyEx(seg_out, cv2.MORPH_OPEN, kernel)\n",
|
||||
" kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))\n",
|
||||
" seg_out = cv2.dilate(seg_out, kernel)\n",
|
||||
"\n",
|
||||
" #========== Adaptive threshold ==================\n",
|
||||
" final_minutiae_score_threashold = 0.45\n",
|
||||
" early_minutiae_thres = final_minutiae_score_threashold + 0.05\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" # In cases of small amount of minutiae given, try adaptive threshold\n",
|
||||
" while final_minutiae_score_threashold >= 0:\n",
|
||||
" mnt = label2mnt(np.squeeze(mnt_s_out) * np.round(np.squeeze(seg_out)), mnt_w_out, mnt_h_out, mnt_o_out,\n",
|
||||
" thresh=early_minutiae_thres)\n",
|
||||
"\n",
|
||||
" mnt_nms_1 = py_cpu_nms(mnt, 0.5)\n",
|
||||
" mnt_nms_2 = nms(mnt)\n",
|
||||
" # Make sure good result is given\n",
|
||||
" if mnt_nms_1.shape[0] > 4 and mnt_nms_2.shape[0] > 4:\n",
|
||||
" break\n",
|
||||
" else:\n",
|
||||
" final_minutiae_score_threashold = final_minutiae_score_threashold - 0.05\n",
|
||||
" early_minutiae_thres = early_minutiae_thres - 0.05\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" mnt_nms = fuse_nms(mnt_nms_1, mnt_nms_2)\n",
|
||||
"\n",
|
||||
" mnt_nms = mnt_nms[mnt_nms[:, 3] > early_minutiae_thres, :]\n",
|
||||
" mnt_refined = []\n",
|
||||
"\n",
|
||||
" if isHavingFineNet == True:\n",
|
||||
" # ======= Verify using FineNet ============\n",
|
||||
" patch_minu_radio = 22\n",
|
||||
" if FineNet_path != None:\n",
|
||||
" for idx_minu in range(mnt_nms.shape[0]):\n",
|
||||
" try:\n",
|
||||
" # Extract patch from image\n",
|
||||
" x_begin = int(mnt_nms[idx_minu, 1]) - patch_minu_radio\n",
|
||||
" y_begin = int(mnt_nms[idx_minu, 0]) - patch_minu_radio\n",
|
||||
" patch_minu = original_image[x_begin:x_begin + 2 * patch_minu_radio,\n",
|
||||
" y_begin:y_begin + 2 * patch_minu_radio]\n",
|
||||
"\n",
|
||||
" patch_minu = cv2.resize(patch_minu, dsize=(224, 224), interpolation=cv2.INTER_NEAREST)\n",
|
||||
"\n",
|
||||
" ret = np.empty((patch_minu.shape[0], patch_minu.shape[1], 3), dtype=np.uint8)\n",
|
||||
" ret[:, :, 0] = patch_minu\n",
|
||||
" ret[:, :, 1] = patch_minu\n",
|
||||
" ret[:, :, 2] = patch_minu\n",
|
||||
" patch_minu = ret\n",
|
||||
" patch_minu = np.expand_dims(patch_minu, axis=0)\n",
|
||||
"\n",
|
||||
" # # Can use class as hard decision\n",
|
||||
" # # 0: minu 1: non-minu\n",
|
||||
" # [class_Minutiae] = np.argmax(model_FineNet.predict(patch_minu), axis=1)\n",
|
||||
" #\n",
|
||||
" # if class_Minutiae == 0:\n",
|
||||
" # mnt_refined.append(mnt_nms[idx_minu,:])\n",
|
||||
"\n",
|
||||
" # Use soft decision: merge FineNet score with CoarseNet score\n",
|
||||
" [isMinutiaeProb] = model_FineNet.predict(patch_minu)\n",
|
||||
" isMinutiaeProb = isMinutiaeProb[0]\n",
|
||||
" # print isMinutiaeProb\n",
|
||||
" tmp_mnt = mnt_nms[idx_minu, :].copy()\n",
|
||||
" tmp_mnt[3] = (4*tmp_mnt[3] + isMinutiaeProb) / 5\n",
|
||||
" mnt_refined.append(tmp_mnt)\n",
|
||||
"\n",
|
||||
" except:\n",
|
||||
" mnt_refined.append(mnt_nms[idx_minu, :])\n",
|
||||
" else:\n",
|
||||
" mnt_refined = mnt_nms\n",
|
||||
"\n",
|
||||
" mnt_nms_backup = mnt_nms.copy()\n",
|
||||
" mnt_nms = np.array(mnt_refined)\n",
|
||||
"\n",
|
||||
" if mnt_nms.shape[0] > 0:\n",
|
||||
" mnt_nms = mnt_nms[mnt_nms[:, 3] > final_minutiae_score_threashold, :]\n",
|
||||
" \n",
|
||||
" final_mask = ndimage.zoom(np.round(np.squeeze(seg_out)), [8, 8], order=0)\n",
|
||||
" # Show the orientation\n",
|
||||
" show_orientation_field(original_image, dir_map + np.pi, mask=final_mask, fname=\"%s/%s/OF_results/%s_OF.jpg\" % (output_dir, set_name, img_name[i]))\n",
|
||||
"\n",
|
||||
" fuse_minu_orientation(dir_map, mnt_nms, mode=3)\n",
|
||||
"\n",
|
||||
" time_afterpost = time()\n",
|
||||
" mnt_writer(mnt_nms, img_name[i], img_size, \"%s/%s/mnt_results/%s.mnt\"%(output_dir, set_name, img_name[i]))\n",
|
||||
" draw_minutiae(original_image, mnt_nms, \"%s/%s/%s_minu.jpg\"%(output_dir, set_name, img_name[i]),saveimage=True)\n",
|
||||
"\n",
|
||||
" misc.imsave(\"%s/%s/seg_results/%s_seg.jpg\" % (output_dir, set_name, img_name[i]), final_mask)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.15"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,131 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Training CoarseNet\n",
|
||||
"Code for FineNet in paper \"Robust Minutiae Extractor: Integrating Deep Networks and Fingerprint Domain Knowledge\" at ICB 2018: https://arxiv.org/pdf/1712.09401.pdf\n",
|
||||
"\n",
|
||||
"If you use whole or partial function in this code, please cite paper:\n",
|
||||
"\n",
|
||||
" @inproceedings{Nguyen_MinutiaeNet,\n",
|
||||
"\tauthor = {Dinh-Luan Nguyen and Kai Cao and Anil K. Jain},\n",
|
||||
"\ttitle = {Robust Minutiae Extractor: Integrating Deep Networks and Fingerprint Domain Knowledge},\n",
|
||||
"\tbooktitle = {The 11th International Conference on Biometrics, 2018},\n",
|
||||
"\tyear = {2018},\n",
|
||||
"\t}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"To run this script, you need to prepare dataset as follows:\n",
|
||||
"`path/to/dataset/`:\n",
|
||||
"```Shell\n",
|
||||
" - img_files/*.bmp\n",
|
||||
" - mnt_files/*.mnt\n",
|
||||
" - seg_files/*.jpg\n",
|
||||
"```\n",
|
||||
"See example at `Dataset/CoarseNet_train/` (these images are example from NIST SD27)\n",
|
||||
" \n",
|
||||
"## CoarseNet can run with any image size\n",
|
||||
"See [CoarseNet_train.py](https://github.com/luannd/MinutiaeNet/blob/master/CoarseNet/CoarseNet_train.py) if running from command line.\n",
|
||||
"\n",
|
||||
"Log files, tensorboard, minutiae models can be seen from `output_CoarseNet` folder"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"from __future__ import absolute_import\n",
|
||||
"from __future__ import division\n",
|
||||
"\n",
|
||||
"import sys, os\n",
|
||||
"sys.path.append(os.path.realpath('../CoarseNet'))\n",
|
||||
"\n",
|
||||
"os.environ['KERAS_BACKEND'] = 'tensorflow'\n",
|
||||
"\n",
|
||||
"from datetime import datetime\n",
|
||||
"from MinutiaeNet_utils import *\n",
|
||||
"\n",
|
||||
"from keras import backend as K\n",
|
||||
"from keras.optimizers import SGD, Adam\n",
|
||||
"\n",
|
||||
"from CoarseNet_utils import *\n",
|
||||
"from CoarseNet_model import *\n",
|
||||
"\n",
|
||||
"lr = 0.005\n",
|
||||
"\n",
|
||||
"os.environ[\"CUDA_VISIBLE_DEVICES\"] = '0'\n",
|
||||
"\n",
|
||||
"config = K.tf.ConfigProto(gpu_options=K.tf.GPUOptions(allow_growth=True))\n",
|
||||
"sess = K.tf.Session(config=config)\n",
|
||||
"K.set_session(sess)\n",
|
||||
"\n",
|
||||
"batch_size = 2\n",
|
||||
"use_multiprocessing = False\n",
|
||||
"input_size = 400\n",
|
||||
"\n",
|
||||
"# Can use multiple folders for training\n",
|
||||
"train_set = ['../Dataset/CoarseNet_train/',]\n",
|
||||
"validate_set = ['../path/to/your/data/',]\n",
|
||||
"\n",
|
||||
"pretrain_dir = '../Models/CoarseNet.h5'\n",
|
||||
"output_dir = '../output_CoarseNet/'+datetime.now().strftime('%Y%m%d-%H%M%S')\n",
|
||||
"FineNet_dir = '../Models/FineNet.h5'\n",
|
||||
"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"\n",
|
||||
"output_dir = '../output_CoarseNet/trainResults/' + datetime.now().strftime('%Y%m%d-%H%M%S')\n",
|
||||
"logging = init_log(output_dir)\n",
|
||||
"logging.info(\"Learning rate = %s\", lr)\n",
|
||||
"logging.info(\"Pretrain dir = %s\", pretrain_dir)\n",
|
||||
"\n",
|
||||
"train(input_shape=(input_size, input_size), train_set=train_set, output_dir=output_dir,\n",
|
||||
" pretrain_dir=pretrain_dir, batch_size=batch_size, test_set=validate_set,\n",
|
||||
" learning_config=Adam(lr=float(lr), beta_1=0.9, beta_2=0.999, epsilon=1e-08, clipnorm=0.9),\n",
|
||||
" logging=logging)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.15"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
@@ -0,0 +1,221 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {},
|
||||
"source": [
|
||||
"# Training FineNet\n",
|
||||
"Code for FineNet in paper \"Robust Minutiae Extractor: Integrating Deep Networks and Fingerprint Domain Knowledge\" at ICB 2018: https://arxiv.org/pdf/1712.09401.pdf\n",
|
||||
"\n",
|
||||
"If you use whole or partial function in this code, please cite paper:\n",
|
||||
"\n",
|
||||
" @inproceedings{Nguyen_MinutiaeNet,\n",
|
||||
"\tauthor = {Dinh-Luan Nguyen and Kai Cao and Anil K. Jain},\n",
|
||||
"\ttitle = {Robust Minutiae Extractor: Integrating Deep Networks and Fingerprint Domain Knowledge},\n",
|
||||
"\tbooktitle = {The 11th International Conference on Biometrics, 2018},\n",
|
||||
"\tyear = {2018},\n",
|
||||
"\t}\n",
|
||||
"\n",
|
||||
"Prepare your data as follows:\n",
|
||||
"- Prepare minutiae and non-minutiae image patches with any sizes. I suggest to use `44x44` size\n",
|
||||
"- Put all images in corresponding folers (`minu`, `non_minu`) in \n",
|
||||
" - `Dataset/train`,\n",
|
||||
" - `Dataset/test`,\n",
|
||||
" - `Dataset/validate`.\n",
|
||||
"- Run following code\n",
|
||||
"\n",
|
||||
"Beside running in this notebook, you can run via command line with file [FineNet_train.py](../FineNet/FineNet_train.py)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"collapsed": true
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import sys,os\n",
|
||||
"sys.path.append(os.path.realpath('../FineNet'))\n",
|
||||
"\n",
|
||||
"from keras.optimizers import Adam\n",
|
||||
"from keras.callbacks import ModelCheckpoint, LearningRateScheduler, TensorBoard\n",
|
||||
"from keras.callbacks import ReduceLROnPlateau\n",
|
||||
"from keras.preprocessing.image import ImageDataGenerator\n",
|
||||
"from FineNet_model import FineNetmodel, plot_confusion_matrix\n",
|
||||
"\n",
|
||||
"import numpy as np\n",
|
||||
"import os\n",
|
||||
"from sklearn.metrics import confusion_matrix\n",
|
||||
"from datetime import datetime\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"os.environ[\"CUDA_VISIBLE_DEVICES\"] = '2'\n",
|
||||
"os.environ['KERAS_BACKEND'] = 'tensorflow'\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"output_dir = '../output_FineNet/'+datetime.now().strftime('%Y%m%d-%H%M%S')\n",
|
||||
"\n",
|
||||
"# Prepare model model saving directory.\n",
|
||||
"save_dir = os.path.join(os.getcwd(), output_dir)\n",
|
||||
"log_dir = os.path.join(os.getcwd(), output_dir + '/logs')\n",
|
||||
"\n",
|
||||
"# Training parameters\n",
|
||||
"batch_size = 32\n",
|
||||
"epochs = 200\n",
|
||||
"num_classes = 2\n",
|
||||
"\n",
|
||||
"# Subtracting pixel mean improves accuracy\n",
|
||||
"subtract_pixel_mean = True\n",
|
||||
"\n",
|
||||
"# Model size, patch\n",
|
||||
"model_type = 'patch224batch32'\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# =============== DATA loading ========================\n",
|
||||
"\n",
|
||||
"train_path = '../Dataset/train/'\n",
|
||||
"test_path = '../Dataset/validate/'\n",
|
||||
"\n",
|
||||
"input_shape = (224, 224, 3)\n",
|
||||
"\n",
|
||||
"# Using data augmentation technique for training\n",
|
||||
"datagen = ImageDataGenerator(\n",
|
||||
" # set input mean to 0 over the dataset\n",
|
||||
" featurewise_center=False,\n",
|
||||
" # set each sample mean to 0\n",
|
||||
" samplewise_center=False,\n",
|
||||
" # divide inputs by std of dataset\n",
|
||||
" featurewise_std_normalization=False,\n",
|
||||
" # divide each input by its std\n",
|
||||
" samplewise_std_normalization=False,\n",
|
||||
" # apply ZCA whitening\n",
|
||||
" zca_whitening=False,\n",
|
||||
" # randomly rotate images in the range (deg 0 to 180)\n",
|
||||
" rotation_range=180,\n",
|
||||
" # randomly shift images horizontally\n",
|
||||
" width_shift_range=0.5,\n",
|
||||
" # randomly shift images vertically\n",
|
||||
" height_shift_range=0.5,\n",
|
||||
" # randomly flip images\n",
|
||||
" horizontal_flip=True,\n",
|
||||
" # randomly flip images\n",
|
||||
" vertical_flip=True)\n",
|
||||
"\n",
|
||||
"train_batches = datagen.flow_from_directory(train_path, target_size=(input_shape[0], input_shape[1]), classes=['minu', 'non_minu'], batch_size=batch_size)\n",
|
||||
"# Feed data from directory into batches\n",
|
||||
"test_gen = ImageDataGenerator()\n",
|
||||
"test_batches = test_gen.flow_from_directory(test_path, target_size=(input_shape[0], input_shape[1]), classes=['minu', 'non_minu'], batch_size=batch_size)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# =============== end DATA loading ========================\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"def lr_schedule(epoch):\n",
|
||||
" \"\"\"Learning Rate Schedule\n",
|
||||
" \"\"\"\n",
|
||||
" lr = 0.5e-2\n",
|
||||
" if epoch > 180:\n",
|
||||
" lr *= 0.5e-3\n",
|
||||
" elif epoch > 150:\n",
|
||||
" lr *= 1e-3\n",
|
||||
" elif epoch > 60:\n",
|
||||
" lr *= 5e-2\n",
|
||||
" elif epoch > 30:\n",
|
||||
" lr *= 5e-1\n",
|
||||
" print('Learning rate: ', lr)\n",
|
||||
" return lr\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#============== Define model ==================\n",
|
||||
"\n",
|
||||
"model = FineNetmodel(num_classes = num_classes,\n",
|
||||
" pretrained_path = '../Models/FineNet.h5',\n",
|
||||
" input_shape=input_shape)\n",
|
||||
"\n",
|
||||
"# Save model architecture\n",
|
||||
"#plot_model(model, to_file='./modelFineNet.pdf',show_shapes=True)\n",
|
||||
"\n",
|
||||
"model.compile(loss='categorical_crossentropy',\n",
|
||||
" optimizer=Adam(lr=lr_schedule(0)),\n",
|
||||
" metrics=['accuracy'])\n",
|
||||
"#model.summary()\n",
|
||||
"\n",
|
||||
"#============== End define model ==============\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"#============== Other stuffs for loging and parameters ==================\n",
|
||||
"model_name = 'FineNet_%s_model.{epoch:03d}.h5' % model_type\n",
|
||||
"if not os.path.isdir(save_dir):\n",
|
||||
" os.makedirs(save_dir)\n",
|
||||
"if not os.path.isdir(log_dir):\n",
|
||||
" os.makedirs(log_dir)\n",
|
||||
"\n",
|
||||
"filepath = os.path.join(save_dir, model_name)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Show in tensorboard\n",
|
||||
"tensorboard = TensorBoard(log_dir=log_dir, histogram_freq=0, write_graph=True, write_images=False)\n",
|
||||
"\n",
|
||||
"# Prepare callbacks for model saving and for learning rate adjustment.\n",
|
||||
"checkpoint = ModelCheckpoint(filepath=filepath,\n",
|
||||
" monitor='val_acc',\n",
|
||||
" verbose=1,\n",
|
||||
" save_best_only=True)\n",
|
||||
"\n",
|
||||
"lr_scheduler = LearningRateScheduler(lr_schedule)\n",
|
||||
"\n",
|
||||
"lr_reducer = ReduceLROnPlateau(factor=np.sqrt(0.1),\n",
|
||||
" cooldown=0,\n",
|
||||
" patience=5,\n",
|
||||
" min_lr=0.5e-6)\n",
|
||||
"\n",
|
||||
"callbacks = [checkpoint, lr_reducer, lr_scheduler, tensorboard]\n",
|
||||
"\n",
|
||||
"#============== End other stuffs ==================\n",
|
||||
"\n",
|
||||
"# Begin training\n",
|
||||
"model.fit_generator(train_batches,\n",
|
||||
" validation_data=test_batches,\n",
|
||||
" epochs=epochs, verbose=1,\n",
|
||||
" callbacks=callbacks)\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
"# Plot confusion matrix\n",
|
||||
"score = model.evaluate_generator(test_batches)\n",
|
||||
"print 'Test accuracy:', score[1]\n",
|
||||
"predictions = model.predict_generator(test_batches)\n",
|
||||
"test_labels = test_batches.classes[test_batches.index_array]\n",
|
||||
"\n",
|
||||
"cm = confusion_matrix(test_labels, np.argmax(predictions,axis=1))\n",
|
||||
"cm_plot_labels = ['minu','non_minu']\n",
|
||||
"plot_confusion_matrix(cm, cm_plot_labels, title='Confusion Matrix')"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 2",
|
||||
"language": "python",
|
||||
"name": "python2"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 2
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython2",
|
||||
"version": "2.7.14"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 2
|
||||
}
|
||||
Reference in New Issue
Block a user