├── __init__.py
├── nets
├── __init__.py
├── NASNet
│ ├── __init__.py
│ ├── nasnet_utils_test.py
│ ├── pnasnet_test.py
│ └── pnasnet.py
└── Inception_ResNet_V2
│ ├── __init__.py
│ └── nets
│ ├── __init__.py
│ ├── mobilenet_v1.png
│ ├── inception.py
│ ├── nets_factory_test.py
│ ├── inception_utils.py
│ ├── lenet.py
│ ├── cyclegan_test.py
│ ├── dcgan_test.py
│ ├── cifarnet.py
│ ├── mobilenet_v1_eval.py
│ ├── overfeat.py
│ ├── alexnet.py
│ ├── pix2pix_test.py
│ ├── nets_factory.py
│ ├── overfeat_test.py
│ ├── alexnet_test.py
│ └── dcgan.py
├── utils
├── __init__.py
└── tools.py
├── augmentation
├── __init__.py
├── rotated_10.png
├── rotated_10.txt
├── data_agumentation.py
└── test.py
├── lanms
├── .gitignore
├── include
│ ├── clipper
│ │ └── clipper.cpp
│ └── pybind11
│ │ ├── typeid.h
│ │ ├── complex.h
│ │ ├── options.h
│ │ ├── functional.h
│ │ ├── eval.h
│ │ ├── buffer_info.h
│ │ ├── chrono.h
│ │ └── embed.h
├── __main__.py
├── Makefile
├── __init__.py
├── adaptor.cpp
├── .ycm_extra_conf.py
└── lanms.h
├── notice_sample
├── .idea
├── markdown-navigator
│ └── profiles_settings.xml
├── vcs.xml
├── misc.xml
├── preferred-vcs.xml
├── inspectionProfiles
│ └── profiles_settings.xml
├── modules.xml
├── deployment.xml
├── webServers.xml
├── EAST-master.iml
└── markdown-navigator.xml
├── requirements.txt
├── static
└── css
│ └── app.css
├── deploy.sh
├── train_flowchart.md
├── test_flowchart.md
├── locality_aware_nms.py
├── .gitignore
├── tools.py
├── data_util.py
├── readme.md
├── run_demo_server.py
├── eval.py
└── cal_IoU_gt_py.py
/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/nets/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/nets/NASNet/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/augmentation/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/lanms/.gitignore:
--------------------------------------------------------------------------------
1 | adaptor.so
2 |
--------------------------------------------------------------------------------
/nets/Inception_ResNet_V2/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/notice_sample:
--------------------------------------------------------------------------------
1 | 10
2 | 17
3 | 32
4 | 43
--------------------------------------------------------------------------------
/nets/Inception_ResNet_V2/nets/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/augmentation/rotated_10.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UpCoder/ICPR_TextDection/HEAD/augmentation/rotated_10.png
--------------------------------------------------------------------------------
/lanms/include/clipper/clipper.cpp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UpCoder/ICPR_TextDection/HEAD/lanms/include/clipper/clipper.cpp
--------------------------------------------------------------------------------
/nets/Inception_ResNet_V2/nets/mobilenet_v1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/UpCoder/ICPR_TextDection/HEAD/nets/Inception_ResNet_V2/nets/mobilenet_v1.png
--------------------------------------------------------------------------------
/.idea/markdown-navigator/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | Shapely==1.5.13
2 | Flask==0.10.1
3 | matplotlib==1.5.1
4 | scipy==0.19.0
5 | plumbum==1.6.2
6 | numpy==1.12.1
7 | ipython==6.1.0
8 | Pillow==4.2.1
9 |
--------------------------------------------------------------------------------
/static/css/app.css:
--------------------------------------------------------------------------------
1 | #app {
2 | padding: 20px;
3 | }
4 |
5 | #result .item {
6 | padding-bottom: 20px;
7 | }
8 |
9 | .form-content-container {
10 | padding-left: 20px;
11 | }
12 |
--------------------------------------------------------------------------------
/deploy.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | mkdir -p server_log
3 | gunicorn -w 3 run_demo_server:app -b 0.0.0.0:8769 -t 120 \
4 | --error-logfile server_log/error.log \
5 | --access-logfile server_log/access.log
6 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/.idea/preferred-vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Git
5 |
6 |
7 |
--------------------------------------------------------------------------------
/train_flowchart.md:
--------------------------------------------------------------------------------
1 | graph TD;
2 | A[输入图像]-->B[基于ResNet的U-Net结构];
3 | A-->G[计算ground truth]
4 | B-->C[使用卷积得到预测的pixel-based的像素信息]
5 | B-->D[使用卷积得到预测的集合信息]
6 | G-->E
7 | C-->E[和ground truth计算balanced cross-entropy loss]
8 | G-->F
9 | D-->F[和ground truth计算geometry loss]
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/lanms/__main__.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 |
3 |
4 | from . import merge_quadrangle_n9
5 |
6 | if __name__ == '__main__':
7 | # unit square with confidence 1
8 | q = np.array([0, 0, 0, 1, 1, 1, 1, 0, 1], dtype='float32')
9 |
10 | print(merge_quadrangle_n9(np.array([q, q + 0.1, q + 2])))
11 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/test_flowchart.md:
--------------------------------------------------------------------------------
1 | graph TD;
2 | A[输入图像]-->B[基于ResNet的U-Net结构];
3 | B-->C[使用卷积得到预测的pixel-based的像素信息]
4 | B-->D[使用卷积得到预测的几何信息]
5 | C-->E["挑选出大于阈值(比如说0.8)的pixel"]
6 | D-->F
7 | E-->F["选择满足阈值条件的pixel的score和几何信息"]
8 | F-->G[针对每个pixel计算得到一个bounding box]
9 | G-->H[针对上述得到的bounding box进行非最大抑制]
10 | H-->I[得到text的bounding box]
--------------------------------------------------------------------------------
/lanms/Makefile:
--------------------------------------------------------------------------------
1 | CXXFLAGS = -I include -std=c++11 -O3 $(shell python2-config --cflags)
2 | LDFLAGS = $(shell python3-config --ldflags)
3 |
4 | DEPS = lanms.h $(shell find include -xtype f)
5 | CXX_SOURCES = adaptor.cpp include/clipper/clipper.cpp
6 |
7 | LIB_SO = adaptor.so
8 |
9 | $(LIB_SO): $(CXX_SOURCES) $(DEPS)
10 | $(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $(CXX_SOURCES) --shared -fPIC
11 |
12 | clean:
13 | rm -rf $(LIB_SO)
14 |
--------------------------------------------------------------------------------
/.idea/deployment.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/webServers.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
14 |
15 |
--------------------------------------------------------------------------------
/lanms/__init__.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 | import os
3 | import numpy as np
4 |
5 | BASE_DIR = os.path.dirname(os.path.realpath(__file__))
6 |
7 | if subprocess.call(['make', '-C', BASE_DIR]) != 0: # return value
8 | raise RuntimeError('Cannot compile lanms: {}'.format(BASE_DIR))
9 |
10 |
11 | def merge_quadrangle_n9(polys, thres=0.3, precision=10000):
12 | from .adaptor import merge_quadrangle_n9 as nms_impl
13 | if len(polys) == 0:
14 | return np.array([], dtype='float32')
15 | p = polys.copy()
16 | p[:,:8] *= precision
17 | ret = np.array(nms_impl(p, thres), dtype='float32')
18 | ret[:,:8] /= precision
19 | return ret
20 |
21 |
--------------------------------------------------------------------------------
/.idea/EAST-master.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/augmentation/rotated_10.txt:
--------------------------------------------------------------------------------
1 | 101,3,101,9,194,9,194,3,###
2 | 109,63,104,47,221,5,221,26,找书:en55@
3 | 0,34,1,52,127,8,121,0,n55@qq.com
4 | 0,84,0,101,72,77,70,60,604682
5 | 171,76,177,94,219,78,214,62,找书:
6 | 42,94,42,116,212,116,212,94,###
7 | 157,132,162,152,221,128,221,110,QQ:29
8 | 5,153,1,137,132,90,139,108,:2956604682
9 | 42,121,42,136,114,136,114,118,###
10 | 99,143,99,157,152,157,152,143,TheLCAO
11 | 101,160,101,174,180,174,180,160,FirstPrincipes
12 | 100,177,100,190,158,190,158,177,Treatment
13 | 99,192,99,209,157,209,157,192,###
14 | 0,190,0,208,125,167,120,152,h55@qq.com
15 | 0,240,3,256,193,191,188,178,找书:en55@qq.com
16 | 7,310,0,289,131,245,140,261,:2956604682
17 | 115,316,115,329,157,329,157,316,Springer
18 | 171,231,179,248,220,234,215,218,找书:
19 | 21,337,48,349,204,291,197,273,QQ:2956604682
20 | 150,346,148,349,190,349,185,336,###
21 | 101,72,101,83,169,83,169,72,R.A.Evarestov
22 | 11,0,11,0,0,0,0,0,###
23 |
--------------------------------------------------------------------------------
/lanms/include/pybind11/typeid.h:
--------------------------------------------------------------------------------
1 | /*
2 | pybind11/typeid.h: Compiler-independent access to type identifiers
3 |
4 | Copyright (c) 2016 Wenzel Jakob
5 |
6 | All rights reserved. Use of this source code is governed by a
7 | BSD-style license that can be found in the LICENSE file.
8 | */
9 |
10 | #pragma once
11 |
12 | #include
13 | #include
14 |
15 | #if defined(__GNUG__)
16 | #include
17 | #endif
18 |
19 | NAMESPACE_BEGIN(pybind11)
20 | NAMESPACE_BEGIN(detail)
21 | /// Erase all occurrences of a substring
22 | inline void erase_all(std::string &string, const std::string &search) {
23 | for (size_t pos = 0;;) {
24 | pos = string.find(search, pos);
25 | if (pos == std::string::npos) break;
26 | string.erase(pos, search.length());
27 | }
28 | }
29 |
30 | PYBIND11_NOINLINE inline void clean_type_id(std::string &name) {
31 | #if defined(__GNUG__)
32 | int status = 0;
33 | std::unique_ptr res {
34 | abi::__cxa_demangle(name.c_str(), nullptr, nullptr, &status), std::free };
35 | if (status == 0)
36 | name = res.get();
37 | #else
38 | detail::erase_all(name, "class ");
39 | detail::erase_all(name, "struct ");
40 | detail::erase_all(name, "enum ");
41 | #endif
42 | detail::erase_all(name, "pybind11::");
43 | }
44 | NAMESPACE_END(detail)
45 |
46 | /// Return a string representation of a C++ type
47 | template static std::string type_id() {
48 | std::string name(typeid(T).name());
49 | detail::clean_type_id(name);
50 | return name;
51 | }
52 |
53 | NAMESPACE_END(pybind11)
54 |
--------------------------------------------------------------------------------
/locality_aware_nms.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from shapely.geometry import Polygon
3 |
4 |
5 | def intersection(g, p):
6 | g = Polygon(g[:8].reshape((4, 2)))
7 | p = Polygon(p[:8].reshape((4, 2)))
8 | if not g.is_valid or not p.is_valid:
9 | return 0
10 | inter = Polygon(g).intersection(Polygon(p)).area
11 | union = g.area + p.area - inter
12 | if union == 0:
13 | return 0
14 | else:
15 | return inter/union
16 |
17 |
18 | def weighted_merge(g, p):
19 | g[:8] = (g[8] * g[:8] + p[8] * p[:8])/(g[8] + p[8])
20 | g[8] = (g[8] + p[8])
21 | return g
22 |
23 |
24 | def standard_nms(S, thres):
25 | order = np.argsort(S[:, 8])[::-1]
26 | keep = []
27 | while order.size > 0:
28 | i = order[0]
29 | keep.append(i)
30 | ovr = np.array([intersection(S[i], S[t]) for t in order[1:]])
31 |
32 | inds = np.where(ovr <= thres)[0]
33 | order = order[inds+1]
34 |
35 | return S[keep]
36 |
37 |
38 | def nms_locality(polys, thres=0.3):
39 | '''
40 | locality aware nms of EAST
41 | :param polys: a N*9 numpy array. first 8 coordinates, then prob
42 | :return: boxes after nms
43 | '''
44 | S = []
45 | p = None
46 | for g in polys:
47 | if p is not None and intersection(g, p) > thres:
48 | p = weighted_merge(g, p)
49 | else:
50 | if p is not None:
51 | S.append(p)
52 | p = g
53 | if p is not None:
54 | S.append(p)
55 |
56 | if len(S) == 0:
57 | return np.array([])
58 | return standard_nms(np.array(S), thres)
59 |
60 |
61 | if __name__ == '__main__':
62 | # 343,350,448,135,474,143,369,359
63 | print(Polygon(np.array([[343, 350], [448, 135],
64 | [474, 143], [369, 359]])).area)
65 |
--------------------------------------------------------------------------------
/nets/Inception_ResNet_V2/nets/inception.py:
--------------------------------------------------------------------------------
1 | # Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | # ==============================================================================
15 | """Brings all inception models under one namespace."""
16 |
17 | from __future__ import absolute_import
18 | from __future__ import division
19 | from __future__ import print_function
20 |
21 | # pylint: disable=unused-import
22 | from nets.inception_resnet_v2 import inception_resnet_v2
23 | from nets.inception_resnet_v2 import inception_resnet_v2_arg_scope
24 | from nets.inception_resnet_v2 import inception_resnet_v2_base
25 | from nets.inception_v1 import inception_v1
26 | from nets.inception_v1 import inception_v1_arg_scope
27 | from nets.inception_v1 import inception_v1_base
28 | from nets.inception_v2 import inception_v2
29 | from nets.inception_v2 import inception_v2_arg_scope
30 | from nets.inception_v2 import inception_v2_base
31 | from nets.inception_v3 import inception_v3
32 | from nets.inception_v3 import inception_v3_arg_scope
33 | from nets.inception_v3 import inception_v3_base
34 | from nets.inception_v4 import inception_v4
35 | from nets.inception_v4 import inception_v4_arg_scope
36 | from nets.inception_v4 import inception_v4_base
37 | # pylint: enable=unused-import
38 |
--------------------------------------------------------------------------------
/lanms/adaptor.cpp:
--------------------------------------------------------------------------------
1 | #include "pybind11/pybind11.h"
2 | #include "pybind11/numpy.h"
3 | #include "pybind11/stl.h"
4 | #include "pybind11/stl_bind.h"
5 |
6 | #include "lanms.h"
7 |
8 | namespace py = pybind11;
9 |
10 |
11 | namespace lanms_adaptor {
12 |
13 | std::vector> polys2floats(const std::vector &polys) {
14 | std::vector> ret;
15 | for (size_t i = 0; i < polys.size(); i ++) {
16 | auto &p = polys[i];
17 | auto &poly = p.poly;
18 | ret.emplace_back(std::vector{
19 | float(poly[0].X), float(poly[0].Y),
20 | float(poly[1].X), float(poly[1].Y),
21 | float(poly[2].X), float(poly[2].Y),
22 | float(poly[3].X), float(poly[3].Y),
23 | float(p.score),
24 | });
25 | }
26 |
27 | return ret;
28 | }
29 |
30 |
31 | /**
32 | *
33 | * \param quad_n9 an n-by-9 numpy array, where first 8 numbers denote the
34 | * quadrangle, and the last one is the score
35 | * \param iou_threshold two quadrangles with iou score above this threshold
36 | * will be merged
37 | *
38 | * \return an n-by-9 numpy array, the merged quadrangles
39 | */
40 | std::vector> merge_quadrangle_n9(
41 | py::array_t quad_n9,
42 | float iou_threshold) {
43 | auto pbuf = quad_n9.request();
44 | if (pbuf.ndim != 2 || pbuf.shape[1] != 9)
45 | throw std::runtime_error("quadrangles must have a shape of (n, 9)");
46 | auto n = pbuf.shape[0];
47 | auto ptr = static_cast(pbuf.ptr);
48 | return polys2floats(lanms::merge_quadrangle_n9(ptr, n, iou_threshold));
49 | }
50 |
51 | }
52 |
53 | PYBIND11_PLUGIN(adaptor) {
54 | py::module m("adaptor", "NMS");
55 |
56 | m.def("merge_quadrangle_n9", &lanms_adaptor::merge_quadrangle_n9,
57 | "merge quadrangels");
58 |
59 | return m.ptr();
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 |
49 | # Translations
50 | *.mo
51 | *.pot
52 |
53 | # Django stuff:
54 | *.log
55 | local_settings.py
56 |
57 | # Flask stuff:
58 | instance/
59 | .webassets-cache
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 |
67 | # PyBuilder
68 | target/
69 |
70 | # Jupyter Notebook
71 | .ipynb_checkpoints
72 |
73 | # pyenv
74 | .python-version
75 |
76 | # celery beat schedule file
77 | celerybeat-schedule
78 |
79 | # SageMath parsed files
80 | *.sage.py
81 |
82 | # dotenv
83 | .env
84 |
85 | # virtualenv
86 | .venv
87 | venv/
88 | ENV/
89 |
90 | # Spyder project settings
91 | .spyderproject
92 | .spyproject
93 |
94 | # Rope project settings
95 | .ropeproject
96 |
97 | # mkdocs documentation
98 | /site
99 |
100 | # mypy
101 | .mypy_cache/
102 |
103 | # vim swapfile
104 | *.swp
105 |
106 | # result files for demo
107 | static/results
108 |
109 |
110 | # tmp
111 | tmp/*
112 |
113 | demo_images/*
114 | demo_result/*
115 | templates/*
116 | training_samples/*
117 |
118 | east_icdar2015_resnet_v1_50_rbox (1).zip
119 | resnet_v1_50_2016_08_28.tar.gz
120 |
121 | log/*
122 |
123 |
--------------------------------------------------------------------------------
/lanms/include/pybind11/complex.h:
--------------------------------------------------------------------------------
1 | /*
2 | pybind11/complex.h: Complex number support
3 |
4 | Copyright (c) 2016 Wenzel Jakob
5 |
6 | All rights reserved. Use of this source code is governed by a
7 | BSD-style license that can be found in the LICENSE file.
8 | */
9 |
10 | #pragma once
11 |
12 | #include "pybind11.h"
13 | #include
14 |
15 | /// glibc defines I as a macro which breaks things, e.g., boost template names
16 | #ifdef I
17 | # undef I
18 | #endif
19 |
20 | NAMESPACE_BEGIN(pybind11)
21 |
22 | template struct format_descriptor, detail::enable_if_t::value>> {
23 | static constexpr const char c = format_descriptor::c;
24 | static constexpr const char value[3] = { 'Z', c, '\0' };
25 | static std::string format() { return std::string(value); }
26 | };
27 |
28 | template constexpr const char format_descriptor<
29 | std::complex, detail::enable_if_t::value>>::value[3];
30 |
31 | NAMESPACE_BEGIN(detail)
32 |
33 | template struct is_fmt_numeric, detail::enable_if_t::value>> {
34 | static constexpr bool value = true;
35 | static constexpr int index = is_fmt_numeric::index + 3;
36 | };
37 |
38 | template class type_caster> {
39 | public:
40 | bool load(handle src, bool convert) {
41 | if (!src)
42 | return false;
43 | if (!convert && !PyComplex_Check(src.ptr()))
44 | return false;
45 | Py_complex result = PyComplex_AsCComplex(src.ptr());
46 | if (result.real == -1.0 && PyErr_Occurred()) {
47 | PyErr_Clear();
48 | return false;
49 | }
50 | value = std::complex((T) result.real, (T) result.imag);
51 | return true;
52 | }
53 |
54 | static handle cast(const std::complex &src, return_value_policy /* policy */, handle /* parent */) {
55 | return PyComplex_FromDoubles((double) src.real(), (double) src.imag());
56 | }
57 |
58 | PYBIND11_TYPE_CASTER(std::complex, _("complex"));
59 | };
60 | NAMESPACE_END(detail)
61 | NAMESPACE_END(pybind11)
62 |
--------------------------------------------------------------------------------
/lanms/include/pybind11/options.h:
--------------------------------------------------------------------------------
1 | /*
2 | pybind11/options.h: global settings that are configurable at runtime.
3 |
4 | Copyright (c) 2016 Wenzel Jakob
5 |
6 | All rights reserved. Use of this source code is governed by a
7 | BSD-style license that can be found in the LICENSE file.
8 | */
9 |
10 | #pragma once
11 |
12 | #include "common.h"
13 |
14 | NAMESPACE_BEGIN(pybind11)
15 |
16 | class options {
17 | public:
18 |
19 | // Default RAII constructor, which leaves settings as they currently are.
20 | options() : previous_state(global_state()) {}
21 |
22 | // Class is non-copyable.
23 | options(const options&) = delete;
24 | options& operator=(const options&) = delete;
25 |
26 | // Destructor, which restores settings that were in effect before.
27 | ~options() {
28 | global_state() = previous_state;
29 | }
30 |
31 | // Setter methods (affect the global state):
32 |
33 | options& disable_user_defined_docstrings() & { global_state().show_user_defined_docstrings = false; return *this; }
34 |
35 | options& enable_user_defined_docstrings() & { global_state().show_user_defined_docstrings = true; return *this; }
36 |
37 | options& disable_function_signatures() & { global_state().show_function_signatures = false; return *this; }
38 |
39 | options& enable_function_signatures() & { global_state().show_function_signatures = true; return *this; }
40 |
41 | // Getter methods (return the global state):
42 |
43 | static bool show_user_defined_docstrings() { return global_state().show_user_defined_docstrings; }
44 |
45 | static bool show_function_signatures() { return global_state().show_function_signatures; }
46 |
47 | // This type is not meant to be allocated on the heap.
48 | void* operator new(size_t) = delete;
49 |
50 | private:
51 |
52 | struct state {
53 | bool show_user_defined_docstrings = true; //< Include user-supplied texts in docstrings.
54 | bool show_function_signatures = true; //< Include auto-generated function signatures in docstrings.
55 | };
56 |
57 | static state &global_state() {
58 | static state instance;
59 | return instance;
60 | }
61 |
62 | state previous_state;
63 | };
64 |
65 | NAMESPACE_END(pybind11)
66 |
--------------------------------------------------------------------------------
/nets/NASNet/nasnet_utils_test.py:
--------------------------------------------------------------------------------
1 | # Copyright 2017 The TensorFlow Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | # ==============================================================================
15 | """Tests for slim.nets.nasnet.nasnet_utils."""
16 |
17 | from __future__ import absolute_import
18 | from __future__ import division
19 | from __future__ import print_function
20 |
21 | import tensorflow as tf
22 |
23 |
24 | from nets.NASNet import nasnet_utils
25 |
26 |
27 | class NasnetUtilsTest(tf.test.TestCase):
28 |
29 | def testCalcReductionLayers(self):
30 | num_cells = 18
31 | num_reduction_layers = 2
32 | reduction_layers = nasnet_utils.calc_reduction_layers(
33 | num_cells, num_reduction_layers)
34 | self.assertEqual(len(reduction_layers), 2)
35 | self.assertEqual(reduction_layers[0], 6)
36 | self.assertEqual(reduction_layers[1], 12)
37 |
38 | def testGetChannelIndex(self):
39 | data_formats = ['NHWC', 'NCHW']
40 | for data_format in data_formats:
41 | index = nasnet_utils.get_channel_index(data_format)
42 | correct_index = 3 if data_format == 'NHWC' else 1
43 | self.assertEqual(index, correct_index)
44 |
45 | def testGetChannelDim(self):
46 | data_formats = ['NHWC', 'NCHW']
47 | shape = [10, 20, 30, 40]
48 | for data_format in data_formats:
49 | dim = nasnet_utils.get_channel_dim(shape, data_format)
50 | correct_dim = shape[3] if data_format == 'NHWC' else shape[1]
51 | self.assertEqual(dim, correct_dim)
52 |
53 | def testGlobalAvgPool(self):
54 | data_formats = ['NHWC', 'NCHW']
55 | inputs = tf.placeholder(tf.float32, (5, 10, 20, 10))
56 | for data_format in data_formats:
57 | output = nasnet_utils.global_avg_pool(
58 | inputs, data_format)
59 | self.assertEqual(output.shape, [5, 10])
60 |
61 |
62 | if __name__ == '__main__':
63 | tf.test.main()
64 |
--------------------------------------------------------------------------------
/nets/Inception_ResNet_V2/nets/nets_factory_test.py:
--------------------------------------------------------------------------------
1 | # Copyright 2016 Google Inc. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | # ==============================================================================
15 |
16 | """Tests for slim.inception."""
17 |
18 | from __future__ import absolute_import
19 | from __future__ import division
20 | from __future__ import print_function
21 |
22 |
23 | import tensorflow as tf
24 |
25 | from nets import nets_factory
26 |
27 |
28 | class NetworksTest(tf.test.TestCase):
29 |
30 | def testGetNetworkFnFirstHalf(self):
31 | batch_size = 5
32 | num_classes = 1000
33 | for net in list(nets_factory.networks_map.keys())[:10]:
34 | with tf.Graph().as_default() as g, self.test_session(g):
35 | net_fn = nets_factory.get_network_fn(net, num_classes)
36 | # Most networks use 224 as their default_image_size
37 | image_size = getattr(net_fn, 'default_image_size', 224)
38 | inputs = tf.random_uniform((batch_size, image_size, image_size, 3))
39 | logits, end_points = net_fn(inputs)
40 | self.assertTrue(isinstance(logits, tf.Tensor))
41 | self.assertTrue(isinstance(end_points, dict))
42 | self.assertEqual(logits.get_shape().as_list()[0], batch_size)
43 | self.assertEqual(logits.get_shape().as_list()[-1], num_classes)
44 |
45 | def testGetNetworkFnSecondHalf(self):
46 | batch_size = 5
47 | num_classes = 1000
48 | for net in list(nets_factory.networks_map.keys())[10:]:
49 | with tf.Graph().as_default() as g, self.test_session(g):
50 | net_fn = nets_factory.get_network_fn(net, num_classes)
51 | # Most networks use 224 as their default_image_size
52 | image_size = getattr(net_fn, 'default_image_size', 224)
53 | inputs = tf.random_uniform((batch_size, image_size, image_size, 3))
54 | logits, end_points = net_fn(inputs)
55 | self.assertTrue(isinstance(logits, tf.Tensor))
56 | self.assertTrue(isinstance(end_points, dict))
57 | self.assertEqual(logits.get_shape().as_list()[0], batch_size)
58 | self.assertEqual(logits.get_shape().as_list()[-1], num_classes)
59 |
60 | if __name__ == '__main__':
61 | tf.test.main()
62 |
--------------------------------------------------------------------------------
/nets/Inception_ResNet_V2/nets/inception_utils.py:
--------------------------------------------------------------------------------
1 | # Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | # ==============================================================================
15 | """Contains common code shared by all inception models.
16 |
17 | Usage of arg scope:
18 | with slim.arg_scope(inception_arg_scope()):
19 | logits, end_points = inception.inception_v3(images, num_classes,
20 | is_training=is_training)
21 |
22 | """
23 | from __future__ import absolute_import
24 | from __future__ import division
25 | from __future__ import print_function
26 |
27 | import tensorflow as tf
28 |
29 | slim = tf.contrib.slim
30 |
31 |
32 | def inception_arg_scope(weight_decay=0.00004,
33 | use_batch_norm=True,
34 | batch_norm_decay=0.9997,
35 | batch_norm_epsilon=0.001,
36 | activation_fn=tf.nn.relu):
37 | """Defines the default arg scope for inception models.
38 |
39 | Args:
40 | weight_decay: The weight decay to use for regularizing the model.
41 | use_batch_norm: "If `True`, batch_norm is applied after each convolution.
42 | batch_norm_decay: Decay for batch norm moving average.
43 | batch_norm_epsilon: Small float added to variance to avoid dividing by zero
44 | in batch norm.
45 | activation_fn: Activation function for conv2d.
46 |
47 | Returns:
48 | An `arg_scope` to use for the inception models.
49 | """
50 | batch_norm_params = {
51 | # Decay for the moving averages.
52 | 'decay': batch_norm_decay,
53 | # epsilon to prevent 0s in variance.
54 | 'epsilon': batch_norm_epsilon,
55 | # collection containing update_ops.
56 | 'updates_collections': tf.GraphKeys.UPDATE_OPS,
57 | # use fused batch norm if possible.
58 | 'fused': None,
59 | }
60 | if use_batch_norm:
61 | normalizer_fn = slim.batch_norm
62 | normalizer_params = batch_norm_params
63 | else:
64 | normalizer_fn = None
65 | normalizer_params = {}
66 | # Set weight_decay for weights in Conv and FC layers.
67 | with slim.arg_scope([slim.conv2d, slim.fully_connected],
68 | weights_regularizer=slim.l2_regularizer(weight_decay)):
69 | with slim.arg_scope(
70 | [slim.conv2d],
71 | weights_initializer=slim.variance_scaling_initializer(),
72 | activation_fn=activation_fn,
73 | normalizer_fn=normalizer_fn,
74 | normalizer_params=normalizer_params) as sc:
75 | return sc
76 |
--------------------------------------------------------------------------------
/lanms/include/pybind11/functional.h:
--------------------------------------------------------------------------------
1 | /*
2 | pybind11/functional.h: std::function<> support
3 |
4 | Copyright (c) 2016 Wenzel Jakob
5 |
6 | All rights reserved. Use of this source code is governed by a
7 | BSD-style license that can be found in the LICENSE file.
8 | */
9 |
10 | #pragma once
11 |
12 | #include "pybind11.h"
13 | #include
14 |
15 | NAMESPACE_BEGIN(pybind11)
16 | NAMESPACE_BEGIN(detail)
17 |
18 | template
19 | struct type_caster> {
20 | using type = std::function;
21 | using retval_type = conditional_t::value, void_type, Return>;
22 | using function_type = Return (*) (Args...);
23 |
24 | public:
25 | bool load(handle src, bool convert) {
26 | if (src.is_none()) {
27 | // Defer accepting None to other overloads (if we aren't in convert mode):
28 | if (!convert) return false;
29 | return true;
30 | }
31 |
32 | if (!isinstance(src))
33 | return false;
34 |
35 | auto func = reinterpret_borrow(src);
36 |
37 | /*
38 | When passing a C++ function as an argument to another C++
39 | function via Python, every function call would normally involve
40 | a full C++ -> Python -> C++ roundtrip, which can be prohibitive.
41 | Here, we try to at least detect the case where the function is
42 | stateless (i.e. function pointer or lambda function without
43 | captured variables), in which case the roundtrip can be avoided.
44 | */
45 | if (auto cfunc = func.cpp_function()) {
46 | auto c = reinterpret_borrow(PyCFunction_GET_SELF(cfunc.ptr()));
47 | auto rec = (function_record *) c;
48 |
49 | if (rec && rec->is_stateless &&
50 | same_type(typeid(function_type), *reinterpret_cast(rec->data[1]))) {
51 | struct capture { function_type f; };
52 | value = ((capture *) &rec->data)->f;
53 | return true;
54 | }
55 | }
56 |
57 | value = [func](Args... args) -> Return {
58 | gil_scoped_acquire acq;
59 | object retval(func(std::forward(args)...));
60 | /* Visual studio 2015 parser issue: need parentheses around this expression */
61 | return (retval.template cast());
62 | };
63 | return true;
64 | }
65 |
66 | template
67 | static handle cast(Func &&f_, return_value_policy policy, handle /* parent */) {
68 | if (!f_)
69 | return none().inc_ref();
70 |
71 | auto result = f_.template target();
72 | if (result)
73 | return cpp_function(*result, policy).release();
74 | else
75 | return cpp_function(std::forward(f_), policy).release();
76 | }
77 |
78 | PYBIND11_TYPE_CASTER(type, _("Callable[[") +
79 | argument_loader::arg_names() + _("], ") +
80 | make_caster::name() +
81 | _("]"));
82 | };
83 |
84 | NAMESPACE_END(detail)
85 | NAMESPACE_END(pybind11)
86 |
--------------------------------------------------------------------------------
/tools.py:
--------------------------------------------------------------------------------
1 | # -*- coding=utf-8 -*-
2 | from PIL import Image
3 | import numpy as np
4 | import cv2
5 | import sys
6 | from utils.tools import draw_rect, order_points
7 | from icdar import expand_poly
8 | sys.setrecursionlimit(300000000)
9 |
10 |
11 | def show_image(image_arr):
12 | img = Image.fromarray(image_arr)
13 | img.show()
14 |
15 | def find_connected(score_map, threshold=0.7):
16 | binary_map = (score_map > threshold).astype(np.uint8)
17 | connectivity = 8
18 | output = cv2.connectedComponentsWithStats(binary_map, connectivity=connectivity, ltype=cv2.CV_32S)
19 | label_map = output[1]
20 | # show_image(np.asarray(label_map * 100.0, np.uint8))
21 | return np.max(label_map), label_map
22 |
23 |
24 | def calculate_boundingbox_score(score_map, threshold=0.7):
25 | # score_map = score_map[::-1, :]
26 | score_map[score_map < threshold] = 0.0
27 | h, w = np.shape(score_map)
28 | # show_image(np.asarray(score_map * 255, np.uint8))
29 | flag = np.zeros([h, w])
30 | boundingboxs = []
31 | rects = []
32 | count_connecter, label_map = find_connected(score_map, threshold)
33 | label_map = np.array(label_map)
34 | bbox_image = np.zeros(np.shape(label_map), np.uint8)
35 | expand_image = np.zeros(np.shape(label_map), np.uint8)
36 | for idx in range(1, count_connecter+1):
37 | connected = np.array(np.where(label_map == idx)).transpose((1, 0))
38 | rect = cv2.minAreaRect(np.array(connected))
39 | rects.append(rect)
40 | bbox = order_points(cv2.boxPoints(rect)[:, ::-1])
41 | r = [None, None, None, None]
42 | for i in range(4):
43 | r[i] = min(np.linalg.norm(bbox[i] - bbox[(i + 1) % 4]),
44 | np.linalg.norm(bbox[i] - bbox[(i - 1) % 4]))
45 | expand_bbox = expand_poly(bbox.copy(), r).astype(np.int32)
46 | boundingboxs.append(expand_bbox)
47 | cur_points = []
48 | expand_points = []
49 | for i in range(4):
50 | for j in range(2):
51 | cur_points.append(bbox[i, j])
52 | expand_points.append(expand_bbox[i, j])
53 | expand_image = draw_rect(expand_image, expand_points)
54 | bbox_image = draw_rect(bbox_image, cur_points)
55 |
56 | for i in range(len(rects)):
57 | for j in range(len(rects)):
58 | if i == j:
59 | continue
60 | rect1 = rects[i]
61 | rect2 = rects[j]
62 | theta1 = rect1[2]
63 | theta2 = rect2[2]
64 | if abs(theta1 - theta2) < 5:
65 | center1 = rect1[0]
66 | center2 = rect2[1]
67 | center_distance = (center1[0] - center2[0])**2 + (center1[1] - center2[1])**2
68 | # dis_sub_width = center_distance - rect1[1][]
69 | # print 'ok'
70 | points = []
71 | for bbox in boundingboxs:
72 | cur_points = []
73 | for i in range(4):
74 | for j in range(2):
75 | cur_points.append(bbox[i, j])
76 | points.append(cur_points)
77 | return np.array(points)
78 |
79 | if __name__ == '__main__':
80 | test = np.zeros([100, 100])
81 | test[10:21, 10:81] = 1.0
82 |
83 | test[30:40, 10:81] = 1.0
84 |
85 | test[42:50, 10:81] = 1.0
86 |
87 | test[62:70, 10:81] = 1.0
88 |
89 | test[82:90, 10:81] = 1.0
90 | find_connected(test)
91 | show_image(np.asarray(test * 255, np.uint8))
92 | # xys = np.argwhere(test != 0)
93 | # rect = cv2.minAreaRect(xys)
94 | # print rect
--------------------------------------------------------------------------------
/nets/Inception_ResNet_V2/nets/lenet.py:
--------------------------------------------------------------------------------
1 | # Copyright 2016 The TensorFlow Authors. All Rights Reserved.
2 | #
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 | # ==============================================================================
15 | """Contains a variant of the LeNet model definition."""
16 |
17 | from __future__ import absolute_import
18 | from __future__ import division
19 | from __future__ import print_function
20 |
21 | import tensorflow as tf
22 |
23 | slim = tf.contrib.slim
24 |
25 |
26 | def lenet(images, num_classes=10, is_training=False,
27 | dropout_keep_prob=0.5,
28 | prediction_fn=slim.softmax,
29 | scope='LeNet'):
30 | """Creates a variant of the LeNet model.
31 |
32 | Note that since the output is a set of 'logits', the values fall in the
33 | interval of (-infinity, infinity). Consequently, to convert the outputs to a
34 | probability distribution over the characters, one will need to convert them
35 | using the softmax function:
36 |
37 | logits = lenet.lenet(images, is_training=False)
38 | probabilities = tf.nn.softmax(logits)
39 | predictions = tf.argmax(logits, 1)
40 |
41 | Args:
42 | images: A batch of `Tensors` of size [batch_size, height, width, channels].
43 | num_classes: the number of classes in the dataset. If 0 or None, the logits
44 | layer is omitted and the input features to the logits layer are returned
45 | instead.
46 | is_training: specifies whether or not we're currently training the model.
47 | This variable will determine the behaviour of the dropout layer.
48 | dropout_keep_prob: the percentage of activation values that are retained.
49 | prediction_fn: a function to get predictions out of logits.
50 | scope: Optional variable_scope.
51 |
52 | Returns:
53 | net: a 2D Tensor with the logits (pre-softmax activations) if num_classes
54 | is a non-zero integer, or the inon-dropped-out nput to the logits layer
55 | if num_classes is 0 or None.
56 | end_points: a dictionary from components of the network to the corresponding
57 | activation.
58 | """
59 | end_points = {}
60 |
61 | with tf.variable_scope(scope, 'LeNet', [images]):
62 | net = end_points['conv1'] = slim.conv2d(images, 32, [5, 5], scope='conv1')
63 | net = end_points['pool1'] = slim.max_pool2d(net, [2, 2], 2, scope='pool1')
64 | net = end_points['conv2'] = slim.conv2d(net, 64, [5, 5], scope='conv2')
65 | net = end_points['pool2'] = slim.max_pool2d(net, [2, 2], 2, scope='pool2')
66 | net = slim.flatten(net)
67 | end_points['Flatten'] = net
68 |
69 | net = end_points['fc3'] = slim.fully_connected(net, 1024, scope='fc3')
70 | if not num_classes:
71 | return net, end_points
72 | net = end_points['dropout3'] = slim.dropout(
73 | net, dropout_keep_prob, is_training=is_training, scope='dropout3')
74 | logits = end_points['Logits'] = slim.fully_connected(
75 | net, num_classes, activation_fn=None, scope='fc4')
76 |
77 | end_points['Predictions'] = prediction_fn(logits, scope='Predictions')
78 |
79 | return logits, end_points
80 | lenet.default_image_size = 28
81 |
82 |
83 | def lenet_arg_scope(weight_decay=0.0):
84 | """Defines the default lenet argument scope.
85 |
86 | Args:
87 | weight_decay: The weight decay to use for regularizing the model.
88 |
89 | Returns:
90 | An `arg_scope` to use for the inception v3 model.
91 | """
92 | with slim.arg_scope(
93 | [slim.conv2d, slim.fully_connected],
94 | weights_regularizer=slim.l2_regularizer(weight_decay),
95 | weights_initializer=tf.truncated_normal_initializer(stddev=0.1),
96 | activation_fn=tf.nn.relu) as sc:
97 | return sc
98 |
--------------------------------------------------------------------------------
/.idea/markdown-navigator.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/lanms/include/pybind11/eval.h:
--------------------------------------------------------------------------------
1 | /*
2 | pybind11/exec.h: Support for evaluating Python expressions and statements
3 | from strings and files
4 |
5 | Copyright (c) 2016 Klemens Morgenstern and
6 | Wenzel Jakob
7 |
8 | All rights reserved. Use of this source code is governed by a
9 | BSD-style license that can be found in the LICENSE file.
10 | */
11 |
12 | #pragma once
13 |
14 | #include "pybind11.h"
15 |
16 | NAMESPACE_BEGIN(pybind11)
17 |
18 | enum eval_mode {
19 | /// Evaluate a string containing an isolated expression
20 | eval_expr,
21 |
22 | /// Evaluate a string containing a single statement. Returns \c none
23 | eval_single_statement,
24 |
25 | /// Evaluate a string containing a sequence of statement. Returns \c none
26 | eval_statements
27 | };
28 |
29 | template
30 | object eval(str expr, object global = globals(), object local = object()) {
31 | if (!local)
32 | local = global;
33 |
34 | /* PyRun_String does not accept a PyObject / encoding specifier,
35 | this seems to be the only alternative */
36 | std::string buffer = "# -*- coding: utf-8 -*-\n" + (std::string) expr;
37 |
38 | int start;
39 | switch (mode) {
40 | case eval_expr: start = Py_eval_input; break;
41 | case eval_single_statement: start = Py_single_input; break;
42 | case eval_statements: start = Py_file_input; break;
43 | default: pybind11_fail("invalid evaluation mode");
44 | }
45 |
46 | PyObject *result = PyRun_String(buffer.c_str(), start, global.ptr(), local.ptr());
47 | if (!result)
48 | throw error_already_set();
49 | return reinterpret_steal