├── .gitignore ├── Anchor-Kmeans ├── README.md ├── datasets.py ├── demo.ipynb ├── gen_anchors.py ├── imgs │ └── avgiou.png └── kmeans.py ├── README.md ├── cal_mean_std.py └── wtm ├── find_gt_files.sh └── img_fill.py /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__/datasets.cpython-37.pyc 2 | __pycache__/kmeans.cpython-37.pyc 3 | .vscode/settings.json 4 | .idea/inspectionProfiles/profiles_settings.xml 5 | .idea/vcs.xml 6 | .idea/modules.xml 7 | .idea/misc.xml 8 | .idea/Anchor-Kmeans.iml 9 | .idea/.gitignore 10 | -------------------------------------------------------------------------------- /Anchor-Kmeans/README.md: -------------------------------------------------------------------------------- 1 | # Anchor-Kmeans 2 | Implementation of kmeans clustering on bounding boxes to generate anchors, as mentioned in the [YOLOv2](https://arxiv.org/abs/1612.08242). 3 | 4 | ## Usage 5 | Currently supports three types of annotation file: 6 | - [labelme json file](https://github.com/wkentaro/labelme) 7 | - [VOC xml file](https://pjreddie.com/projects/pascal-voc-dataset-mirror/) 8 | - csv file, each line is a coordinate values separated by a comma, form as `xmin, ymin, xmax, ymax` 9 | 10 | To generate anchors of your own dataset is very simple, just execute the `gen_anchors.py` script with 3 arguments: 11 | 12 | ```bash 13 | python gen_anchors.py -d /path to your/annotations-dir -t [annotation file type, defualt 'xml'] -k [num of clusters, default 5] 14 | ``` 15 | 16 | ## Test 17 | 18 | I have tested it on the VOC2012 dataset, the trend of average iou with k value is shown in the figure below 19 | 20 | ![](./imgs/avgiou.png) 21 | 22 | See the detailed test code in [demo.ipynb](./demo.ipynb) 23 | 24 | -------------------------------------------------------------------------------- /Anchor-Kmeans/datasets.py: -------------------------------------------------------------------------------- 1 | import xml.etree.ElementTree as ET 2 | import numpy as np 3 | import glob 4 | import os 5 | import json 6 | import cv2 7 | 8 | 9 | class AnnotParser(object): 10 | def __init__(self, file_type): 11 | assert file_type in ['csv', 'xml', 'json'], "Unsupported file type." 12 | self.file_type = file_type 13 | 14 | def parse(self, annot_dir): 15 | """ 16 | Parse annotation file, the file type must be csv or xml or json. 17 | 18 | :param annot_dir: directory path of annotation files 19 | :return: 2-d array, shape as (n, 2), each row represents a bbox, and each column 20 | represents the corresponding width and height after normalized 21 | """ 22 | if self.file_type == 'xml': 23 | return self.parse_xml(annot_dir) 24 | elif self.file_type == 'json': 25 | return self.parse_json(annot_dir) 26 | else: 27 | return self.parse_csv(annot_dir) 28 | 29 | @staticmethod 30 | def parse_xml(annot_dir): 31 | """ 32 | Parse xml annotation file in VOC. 33 | """ 34 | boxes = [] 35 | 36 | for xml_file in glob.glob(os.path.join(annot_dir, '*.xml')): 37 | tree = ET.parse(xml_file) 38 | 39 | h_img = int(tree.findtext('./size/height')) 40 | w_img = int(tree.findtext('./size/width')) 41 | 42 | for obj in tree.iter('object'): 43 | xmin = int(round(float(obj.findtext('bndbox/xmin')))) 44 | ymin = int(round(float(obj.findtext('bndbox/ymin')))) 45 | xmax = int(round(float(obj.findtext('bndbox/xmax')))) 46 | ymax = int(round(float(obj.findtext('bndbox/ymax')))) 47 | 48 | w_norm = (xmax - xmin) / w_img 49 | h_norm = (ymax - ymin) / h_img 50 | 51 | boxes.append([w_norm, h_norm]) 52 | 53 | return np.array(boxes) 54 | 55 | @staticmethod 56 | def parse_json(annot_dir): 57 | """ 58 | Parse labelme json annotation file. 59 | """ 60 | boxes = [] 61 | 62 | for js_file in glob.glob(os.path.join(annot_dir, '*.json')): 63 | with open(js_file) as f: 64 | data = json.load(f) 65 | 66 | h_img = data['imageHeight'] 67 | w_img = data['imageWidth'] 68 | 69 | for shape in data['shapes']: 70 | points = shape['points'] 71 | xmin = int(round(points[0][0])) 72 | ymin = int(round(points[0][1])) 73 | xmax = int(round(points[1][0])) 74 | ymax = int(round(points[1][1])) 75 | 76 | w_norm = (xmax - xmin) / w_img 77 | h_norm = (ymax - ymin) / h_img 78 | 79 | boxes.append([w_norm, h_norm]) 80 | 81 | return np.array(boxes) 82 | 83 | @staticmethod 84 | def parse_csv(annot_dir): 85 | """ 86 | Parse csv annotation file. 87 | """ 88 | boxes = [] 89 | 90 | for csv_file in glob.glob(os.path.join(annot_dir, '*.csv')): 91 | with open(csv_file) as f: 92 | lines = f.readlines() 93 | 94 | for line in lines: 95 | items = line.strip().split(',') 96 | img = cv2.imread(items[0]) 97 | h_img, w_img = img.shape[:2] 98 | xmin, ymin, xmax, ymax = list(map(int, items[1:-1])) 99 | 100 | w_norm = (xmax - xmin) / w_img 101 | h_norm = (ymax - ymin) / h_img 102 | 103 | boxes.append([w_norm, h_norm]) 104 | 105 | return np.array(boxes) 106 | -------------------------------------------------------------------------------- /Anchor-Kmeans/demo.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [], 8 | "source": [ 9 | "import numpy as np\n", 10 | "from kmeans import AnchorKmeans\n", 11 | "from datasets import AnnotParser\n", 12 | "from matplotlib import pyplot as plt\n", 13 | "from matplotlib.patches import Rectangle\n", 14 | "%matplotlib inline\n", 15 | "\n", 16 | "plt.style.use('ggplot')" 17 | ] 18 | }, 19 | { 20 | "cell_type": "code", 21 | "execution_count": 2, 22 | "metadata": {}, 23 | "outputs": [ 24 | { 25 | "name": "stdout", 26 | "output_type": "stream", 27 | "text": "[INFO] Load datas\nboxes shape : (40138, 2)\n" 28 | } 29 | ], 30 | "source": [ 31 | "print('[INFO] Load datas')\n", 32 | "annot_dir = \"/PATH TO YOUR/VOCdevkit/VOC2012/Annotations\"\n", 33 | "parser = AnnotParser('xml')\n", 34 | "boxes = parser.parse_xml(annot_dir)\n", 35 | "print('boxes shape : {}'.format(boxes.shape))" 36 | ] 37 | }, 38 | { 39 | "cell_type": "code", 40 | "execution_count": 3, 41 | "metadata": {}, 42 | "outputs": [ 43 | { 44 | "name": "stdout", 45 | "output_type": "stream", 46 | "text": "[INFO] Run anchor k-means with k = 2,3,...,10\nK = 2, Avg IOU = 0.4646\nK = 3, Avg IOU = 0.5391\nK = 4, Avg IOU = 0.5801\nK = 5, Avg IOU = 0.6016\nK = 6, Avg IOU = 0.6252\nK = 7, Avg IOU = 0.6434\nK = 8, Avg IOU = 0.6596\nK = 9, Avg IOU = 0.6732\nK = 10, Avg IOU = 0.6838\n" 47 | } 48 | ], 49 | "source": [ 50 | "print('[INFO] Run anchor k-means with k = 2,3,...,10')\n", 51 | "results = {}\n", 52 | "for k in range(2, 11):\n", 53 | " model = AnchorKmeans(k, random_seed=333)\n", 54 | " model.fit(boxes)\n", 55 | " avg_iou = model.avg_iou()\n", 56 | " results[k] = {'anchors': model.anchors_, 'avg_iou': avg_iou}\n", 57 | " print(\"K = {}, Avg IOU = {:.4f}\".format(k, avg_iou))" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": 4, 63 | "metadata": {}, 64 | "outputs": [ 65 | { 66 | "name": "stdout", 67 | "output_type": "stream", 68 | "text": "[INFO] Plot average IOU curve\n" 69 | }, 70 | { 71 | "data": { 72 | "image/png": "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\n", 73 | "image/svg+xml": "\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n", 74 | "text/plain": "
" 75 | }, 76 | "metadata": { 77 | "needs_background": "light" 78 | }, 79 | "output_type": "display_data" 80 | } 81 | ], 82 | "source": [ 83 | "print('[INFO] Plot average IOU curve')\n", 84 | "plt.figure()\n", 85 | "plt.plot(range(2, 11), [results[k][\"avg_iou\"] for k in range(2, 11)], \"o-\")\n", 86 | "plt.ylabel(\"Avg IOU\")\n", 87 | "plt.xlabel(\"K (#anchors)\")\n", 88 | "plt.show()" 89 | ] 90 | }, 91 | { 92 | "cell_type": "code", 93 | "execution_count": 5, 94 | "metadata": {}, 95 | "outputs": [ 96 | { 97 | "name": "stdout", 98 | "output_type": "stream", 99 | "text": "[INFO] The result anchors:\n[[0.7794355 0.8338808 ]\n [0.33883529 0.68815335]\n [0.61044288 0.40655773]\n [0.19493034 0.35335266]\n [0.07805765 0.13006786]]\n" 100 | } 101 | ], 102 | "source": [ 103 | "print('[INFO] The result anchors:')\n", 104 | "best_k = 5\n", 105 | "anchors = results[best_k]['anchors']\n", 106 | "print(anchors)" 107 | ] 108 | }, 109 | { 110 | "cell_type": "code", 111 | "execution_count": 6, 112 | "metadata": {}, 113 | "outputs": [ 114 | { 115 | "name": "stdout", 116 | "output_type": "stream", 117 | "text": "[INFO] Visualizing anchors\n" 118 | }, 119 | { 120 | "data": { 121 | "image/png": "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\n", 122 | "image/svg+xml": "\r\n\r\n\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n\r\n", 123 | "text/plain": "
" 124 | }, 125 | "metadata": { 126 | "needs_background": "light" 127 | }, 128 | "output_type": "display_data" 129 | } 130 | ], 131 | "source": [ 132 | "print('[INFO] Visualizing anchors')\n", 133 | "w_img, h_img = 600, 600\n", 134 | "\n", 135 | "anchors[:, 0] *= w_img\n", 136 | "anchors[:, 1] *= h_img\n", 137 | "anchors = np.round(anchors).astype(np.int)\n", 138 | "\n", 139 | "rects = np.empty((5, 4), dtype=np.int)\n", 140 | "for i in range(len(anchors)):\n", 141 | " w, h = anchors[i]\n", 142 | " x1, y1 = -(w // 2), -(h // 2)\n", 143 | " rects[i] = [x1, y1, w, h]\n", 144 | "\n", 145 | "fig = plt.figure(figsize=(8, 6))\n", 146 | "ax = fig.add_subplot()\n", 147 | "for rect in rects:\n", 148 | " x1, y1, w, h = rect\n", 149 | " rect1 = Rectangle((x1, y1), w, h, color='royalblue', fill=False, linewidth=2)\n", 150 | " ax.add_patch(rect1)\n", 151 | "plt.xlim([-(w_img // 2), w_img // 2])\n", 152 | "plt.ylim([-(h_img // 2), h_img // 2])\n", 153 | "\n", 154 | "plt.show()" 155 | ] 156 | } 157 | ], 158 | "metadata": { 159 | "kernelspec": { 160 | "display_name": "Python 3", 161 | "language": "python", 162 | "name": "python3" 163 | }, 164 | "language_info": { 165 | "codemirror_mode": { 166 | "name": "ipython", 167 | "version": 3 168 | }, 169 | "file_extension": ".py", 170 | "mimetype": "text/x-python", 171 | "name": "python", 172 | "nbconvert_exporter": "python", 173 | "pygments_lexer": "ipython3", 174 | "version": "3.7.4-final" 175 | }, 176 | "toc": { 177 | "base_numbering": 1, 178 | "nav_menu": {}, 179 | "number_sections": true, 180 | "sideBar": true, 181 | "skip_h1_title": false, 182 | "title_cell": "Table of Contents", 183 | "title_sidebar": "Contents", 184 | "toc_cell": false, 185 | "toc_position": {}, 186 | "toc_section_display": true, 187 | "toc_window_display": false 188 | } 189 | }, 190 | "nbformat": 4, 191 | "nbformat_minor": 2 192 | } -------------------------------------------------------------------------------- /Anchor-Kmeans/gen_anchors.py: -------------------------------------------------------------------------------- 1 | from kmeans import AnchorKmeans 2 | from datasets import AnnotParser 3 | import argparse 4 | 5 | 6 | def main(args): 7 | file_type = args["type"] 8 | k = args["k_clusters"] 9 | annot_dir = args["dir_path"] 10 | parser = AnnotParser(file_type) 11 | 12 | print("[INFO] Load datas from {}".format(annot_dir)) 13 | boxes = parser.parse(annot_dir) 14 | 15 | print("[INFO] Initialize model") 16 | model = AnchorKmeans(k) 17 | 18 | print("[INFO] Training...") 19 | model.fit(boxes) 20 | 21 | anchors = model.anchors_ 22 | print("[INFO] The results anchors:\n{}".format(anchors)) 23 | 24 | 25 | if __name__ == "__main__": 26 | ap = argparse.ArgumentParser() 27 | ap.add_argument("-d", 28 | "--dir_path", 29 | required=True, 30 | help="directory path of annotation files") 31 | ap.add_argument("-t", 32 | "--type", 33 | choices=['xml', 'json', 'csv'], 34 | default='xml', 35 | help="type of annotation file") 36 | ap.add_argument("-k", 37 | "--k_clusters", 38 | type=int, 39 | default=5, 40 | help="the number of clusters") 41 | args = vars(ap.parse_args()) 42 | main(args) 43 | -------------------------------------------------------------------------------- /Anchor-Kmeans/imgs/avgiou.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ybcc2015/DeepLearning-Utils/629bea84be257005dd3c331f14ba390c5ea59065/Anchor-Kmeans/imgs/avgiou.png -------------------------------------------------------------------------------- /Anchor-Kmeans/kmeans.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | class AnchorKmeans(object): 5 | """ 6 | K-means clustering on bounding boxes to generate anchors 7 | """ 8 | def __init__(self, k, max_iter=300, random_seed=None): 9 | self.k = k 10 | self.max_iter = max_iter 11 | self.random_seed = random_seed 12 | self.n_iter = 0 13 | self.anchors_ = None 14 | self.labels_ = None 15 | self.ious_ = None 16 | 17 | def fit(self, boxes): 18 | """ 19 | Run K-means cluster on input boxes. 20 | 21 | :param boxes: 2-d array, shape(n, 2), form as (w, h) 22 | :return: None 23 | """ 24 | assert self.k < len(boxes), "K must be less than the number of data." 25 | 26 | # If the current number of iterations is greater than 0, then reset 27 | if self.n_iter > 0: 28 | self.n_iter = 0 29 | 30 | np.random.seed(self.random_seed) 31 | n = boxes.shape[0] 32 | 33 | # Initialize K cluster centers (i.e., K anchors) 34 | self.anchors_ = boxes[np.random.choice(n, self.k, replace=True)] 35 | 36 | self.labels_ = np.zeros((n,)) 37 | 38 | while True: 39 | self.n_iter += 1 40 | 41 | # If the current number of iterations is greater than max number of iterations , then break 42 | if self.n_iter > self.max_iter: 43 | break 44 | 45 | self.ious_ = self.iou(boxes, self.anchors_) 46 | distances = 1 - self.ious_ 47 | cur_labels = np.argmin(distances, axis=1) 48 | 49 | # If anchors not change any more, then break 50 | if (cur_labels == self.labels_).all(): 51 | break 52 | 53 | # Update K anchors 54 | for i in range(self.k): 55 | self.anchors_[i] = np.mean(boxes[cur_labels == i], axis=0) 56 | 57 | self.labels_ = cur_labels 58 | 59 | @staticmethod 60 | def iou(boxes, anchors): 61 | """ 62 | Calculate the IOU between boxes and anchors. 63 | 64 | :param boxes: 2-d array, shape(n, 2) 65 | :param anchors: 2-d array, shape(k, 2) 66 | :return: 2-d array, shape(n, k) 67 | """ 68 | # Calculate the intersection, 69 | # the new dimension are added to construct shape (n, 1) and shape (1, k), 70 | # so we can get (n, k) shape result by numpy broadcast 71 | w_min = np.minimum(boxes[:, 0, np.newaxis], anchors[np.newaxis, :, 0]) 72 | h_min = np.minimum(boxes[:, 1, np.newaxis], anchors[np.newaxis, :, 1]) 73 | inter = w_min * h_min 74 | 75 | # Calculate the union 76 | box_area = boxes[:, 0] * boxes[:, 1] 77 | anchor_area = anchors[:, 0] * anchors[:, 1] 78 | union = box_area[:, np.newaxis] + anchor_area[np.newaxis] 79 | 80 | return inter / (union - inter) 81 | 82 | def avg_iou(self): 83 | """ 84 | Calculate the average IOU with closest anchor. 85 | 86 | :return: None 87 | """ 88 | return np.mean(self.ious_[np.arange(len(self.labels_)), self.labels_]) 89 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DeepLearning-Utils 2 | This repository contains some commonly ulits in deep learning. 3 | -------------------------------------------------------------------------------- /cal_mean_std.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | from imutils import paths 4 | 5 | 6 | def calculate_mean_std(img_root, channels=3): 7 | """ 8 | Calculate the mean and standard deviation of the training images. 9 | 10 | Arguments: 11 | img_root {str} -- the root directory of training images 12 | channels {int} -- the numbers of channles 13 | 14 | Returns: 15 | mean {1-d numpy array} -- mean value of each channel 16 | std {1-d numpy array} -- standard deviation of each channel 17 | """ 18 | total_pixel = 0 19 | channel_sum = np.zeros(channels) 20 | channel_square_sum = np.zeros(channels) 21 | 22 | for img_path in paths.list_images(img_root): 23 | img = cv2.imread(img_path) 24 | img = img / 255. 25 | channel_sum = np.sum(img, axis=(0, 1)) 26 | channel_square_sum = np.sum(img ** 2, axis=(0, 1)) 27 | total_pixel += img.shape[0] * img.shape[1] 28 | 29 | mean = channel_sum / total_pixel 30 | std = np.sqrt(channel_square_sum / total_pixel - mean ** 2) 31 | 32 | if channels == 3: # bgr -> rgb 33 | mean = mean[::-1] 34 | std = std[::-1] 35 | 36 | return mean, std 37 | -------------------------------------------------------------------------------- /wtm/find_gt_files.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | DIR=$1 4 | find $DIR -name '*_gt.json' | wc -l 5 | 6 | -------------------------------------------------------------------------------- /wtm/img_fill.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import json 4 | 5 | 6 | class ImgFill(object): 7 | def __init__(self, json_file): 8 | self.box = self.get_box(json_file) 9 | 10 | @staticmethod 11 | def get_box(json_file): 12 | """ 13 | 获取json文件中的box_b的坐标 14 | Args: 15 | json_file (str): json文件路径 16 | Returns: 17 | [list]: box_b的坐标,格式为[left, top, right, bottom] 18 | """ 19 | res = [] 20 | 21 | with open("./boxes.json") as f: 22 | json_data = json.load(f) 23 | 24 | for box in json_data["boxes"]: 25 | if box["name"] == "box_b": 26 | print(box["rectangle"]) 27 | res = box["rectangle"]["left_top"] 28 | res.extend(box["rectangle"]["right_bottom"]) 29 | 30 | return res 31 | 32 | def is_box_valid(self, img): 33 | """ 34 | 判断box_b指定的区域是否超出img的边界 35 | Args: 36 | img (numpy array): 目标图像 37 | Returns: 38 | [bool]: ture or false 39 | """ 40 | left, top = self.box[:2] 41 | h = self.box[3] - self.box[1] 42 | w = self.box[2] - self.box[0] 43 | h_img, w_img = img.shape[:2] 44 | 45 | cond1 = left >= 0 and (left + w) <= w_img 46 | cond2 = top >= 0 and (top + h) <= h_img 47 | return cond1 and cond2 48 | 49 | def fill(self, dst_img, src_img, mode="stretch"): 50 | """ 51 | 图像填充函数 52 | Args: 53 | dst_img (numpy array): 目标图像 54 | src_img (numpy array): 源图像 (待填充的图像) 55 | mode (str): 填充模式, "stretch"指拉伸填充, "keep"指保持比例填充 56 | Returns: 57 | [numpy array]: 填充后的图像 58 | """ 59 | ok = self.is_box_valid(dst_img) 60 | if not ok: 61 | return 62 | 63 | # 得到填充区域的左上角顶点, 以及宽和高 64 | left, top = self.box[:2] 65 | h = self.box[3] - self.box[1] 66 | w = self.box[2] - self.box[0] 67 | 68 | assert mode in ["stretch", "keep"], "当前仅支持'stretch'和'keep'填充模式!" 69 | 70 | if mode == "stretch": 71 | src_img = cv2.resize(src_img, (w, h)) 72 | dst_img[top: top + h, left: left + w] = src_img 73 | 74 | if mode == "keep": 75 | # 基于源图的长边得到缩放比例 76 | h_img, w_img = src_img.shape[:2] 77 | ratio = h / h_img if h_img >= w_img else w / w_img 78 | 79 | # 源图等比例缩放 80 | h_new = int(round(h_img * ratio)) 81 | w_new = int(round(w_img * ratio)) 82 | src_img = cv2.resize(src_img, (w_new, h_new)) 83 | 84 | # 如果缩放后的高小于填充区域的高, 则沿y轴方向进行pad 85 | if h_new < h: 86 | pad = h - h_new 87 | pad_size = (pad // 2, pad - pad // 2) 88 | np.pad(src_img, (pad_size, (0, 0))) 89 | h_new = h 90 | 91 | # 如果缩放后的宽小于填充区域的高宽, 则沿x轴方向进行pad 92 | if w_new < w: 93 | pad = w - w_new 94 | pad_size = (pad // 2, pad - pad // 2) 95 | np.pad(src_img, ((0, 0), pad_size)) 96 | w_new = w 97 | 98 | dst_img[top: top + h_new, left: left + w_new] = src_img 99 | 100 | return dst_img 101 | --------------------------------------------------------------------------------