Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
wangsen
paddle_dbnet
Commits
2814d997
Commit
2814d997
authored
Jun 23, 2020
by
zhangxin
Browse files
Merge remote-tracking branch 'upstream/develop' into zxdev
parents
9717944c
dcd0ed64
Changes
37
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
8732 additions
and
13 deletions
+8732
-13
README.md
README.md
+8
-1
doc/paddlehelp.jpg
doc/paddlehelp.jpg
+0
-0
ppocr/data/det/db_process.py
ppocr/data/det/db_process.py
+2
-2
ppocr/data/det/east_process.py
ppocr/data/det/east_process.py
+29
-6
ppocr/data/rec/img_tools.py
ppocr/data/rec/img_tools.py
+2
-2
ppocr/modeling/heads/det_east_head.py
ppocr/modeling/heads/det_east_head.py
+2
-1
ppocr/postprocess/east_postprocess.py
ppocr/postprocess/east_postprocess.py
+16
-1
ppocr/postprocess/lanms/.gitignore
ppocr/postprocess/lanms/.gitignore
+1
-0
ppocr/postprocess/lanms/.ycm_extra_conf.py
ppocr/postprocess/lanms/.ycm_extra_conf.py
+140
-0
ppocr/postprocess/lanms/Makefile
ppocr/postprocess/lanms/Makefile
+13
-0
ppocr/postprocess/lanms/__init__.py
ppocr/postprocess/lanms/__init__.py
+20
-0
ppocr/postprocess/lanms/__main__.py
ppocr/postprocess/lanms/__main__.py
+10
-0
ppocr/postprocess/lanms/adaptor.cpp
ppocr/postprocess/lanms/adaptor.cpp
+61
-0
ppocr/postprocess/lanms/include/clipper/clipper.cpp
ppocr/postprocess/lanms/include/clipper/clipper.cpp
+4622
-0
ppocr/postprocess/lanms/include/clipper/clipper.hpp
ppocr/postprocess/lanms/include/clipper/clipper.hpp
+404
-0
ppocr/postprocess/lanms/include/pybind11/attr.h
ppocr/postprocess/lanms/include/pybind11/attr.h
+471
-0
ppocr/postprocess/lanms/include/pybind11/buffer_info.h
ppocr/postprocess/lanms/include/pybind11/buffer_info.h
+108
-0
ppocr/postprocess/lanms/include/pybind11/cast.h
ppocr/postprocess/lanms/include/pybind11/cast.h
+2058
-0
ppocr/postprocess/lanms/include/pybind11/chrono.h
ppocr/postprocess/lanms/include/pybind11/chrono.h
+162
-0
ppocr/postprocess/lanms/include/pybind11/class_support.h
ppocr/postprocess/lanms/include/pybind11/class_support.h
+603
-0
No files found.
README.md
View file @
2814d997
...
...
@@ -93,6 +93,9 @@ python3 tools/infer/predict_system.py --image_dir="./doc/imgs/11.jpg" --det_mode
-
[
文本识别模型训练/评估/预测
](
./doc/doc_ch/recognition.md
)
-
[
基于预测引擎推理
](
./doc/doc_ch/inference.md
)
-
[
数据集
](
./doc/doc_ch/datasets.md
)
-
[
FAQ
](
#FAQ
)
-
[
联系我们
](
#欢迎加入PaddleOCR技术交流群
)
-
[
参考文献
](
#参考文献
)
## 文本检测算法
...
...
@@ -170,6 +173,7 @@ PaddleOCR文本识别算法的训练和使用请参考文档教程中[文本识


<a
name=
"FAQ"
></a>
## FAQ
1.
**转换attention识别模型时报错:KeyError: 'predict'**
问题已解,请更新到最新代码。
...
...
@@ -185,9 +189,12 @@ PaddleOCR文本识别算法的训练和使用请参考文档教程中[文本识
[
more
](
./doc/doc_ch/FAQ.md
)
<a
name=
"欢迎加入PaddleOCR技术交流群"
></a>
## 欢迎加入PaddleOCR技术交流群
加微信:paddlehelp,备注OCR,小助手拉你进群~
扫描二维码或者加微信:paddlehelp,备注OCR,小助手拉你进群~
<img
src=
"./doc/paddlehelp.jpg"
width =
"200"
height =
"200"
/>
<a
name=
"参考文献"
></a>
## 参考文献
```
1. EAST:
...
...
doc/paddlehelp.jpg
0 → 100644
View file @
2814d997
39.5 KB
ppocr/data/det/db_process.py
View file @
2814d997
...
...
@@ -125,8 +125,8 @@ class DBProcessTest(object):
def
__init__
(
self
,
params
):
super
(
DBProcessTest
,
self
).
__init__
()
self
.
resize_type
=
0
if
'
de
t_image_shape'
in
params
:
self
.
image_shape
=
params
[
'
de
t_image_shape'
]
if
'
tes
t_image_shape'
in
params
:
self
.
image_shape
=
params
[
'
tes
t_image_shape'
]
# print(self.image_shape)
self
.
resize_type
=
1
if
'max_side_len'
in
params
:
...
...
ppocr/data/det/east_process.py
View file @
2814d997
...
...
@@ -455,17 +455,23 @@ class EASTProcessTrain(object):
class
EASTProcessTest
(
object
):
def
__init__
(
self
,
params
):
super
(
EASTProcessTest
,
self
).
__init__
()
self
.
resize_type
=
0
if
'test_image_shape'
in
params
:
self
.
image_shape
=
params
[
'test_image_shape'
]
# print(self.image_shape)
self
.
resize_type
=
1
if
'max_side_len'
in
params
:
self
.
max_side_len
=
params
[
'max_side_len'
]
else
:
self
.
max_side_len
=
2400
def
resize_image
(
self
,
im
):
def
resize_image
_type0
(
self
,
im
):
"""
resize image to a size multiple of 32 which is required by the network
:param im: the resized image
:param max_side_len: limit of max image size to avoid out of memory in gpu
:return: the resized image and the resize ratio
args:
img(array): array with shape [h, w, c]
return(tuple):
img, (ratio_h, ratio_w)
"""
max_side_len
=
self
.
max_side_len
h
,
w
,
_
=
im
.
shape
...
...
@@ -495,13 +501,30 @@ class EASTProcessTest(object):
resize_w
=
32
else
:
resize_w
=
(
resize_w
//
32
-
1
)
*
32
im
=
cv2
.
resize
(
im
,
(
int
(
resize_w
),
int
(
resize_h
)))
try
:
if
int
(
resize_w
)
<=
0
or
int
(
resize_h
)
<=
0
:
return
None
,
(
None
,
None
)
im
=
cv2
.
resize
(
im
,
(
int
(
resize_w
),
int
(
resize_h
)))
except
:
print
(
im
.
shape
,
resize_w
,
resize_h
)
sys
.
exit
(
0
)
ratio_h
=
resize_h
/
float
(
h
)
ratio_w
=
resize_w
/
float
(
w
)
return
im
,
(
ratio_h
,
ratio_w
)
def
resize_image_type1
(
self
,
im
):
resize_h
,
resize_w
=
self
.
image_shape
ori_h
,
ori_w
=
im
.
shape
[:
2
]
# (h, w, c)
im
=
cv2
.
resize
(
im
,
(
int
(
resize_w
),
int
(
resize_h
)))
ratio_h
=
float
(
resize_h
)
/
ori_h
ratio_w
=
float
(
resize_w
)
/
ori_w
return
im
,
(
ratio_h
,
ratio_w
)
def
__call__
(
self
,
im
):
im
,
(
ratio_h
,
ratio_w
)
=
self
.
resize_image
(
im
)
if
self
.
resize_type
==
0
:
im
,
(
ratio_h
,
ratio_w
)
=
self
.
resize_image_type0
(
im
)
else
:
im
,
(
ratio_h
,
ratio_w
)
=
self
.
resize_image_type1
(
im
)
img_mean
=
[
0.485
,
0.456
,
0.406
]
img_std
=
[
0.229
,
0.224
,
0.225
]
im
=
im
[:,
:,
::
-
1
].
astype
(
np
.
float32
)
...
...
ppocr/data/rec/img_tools.py
View file @
2814d997
...
...
@@ -108,8 +108,8 @@ def process_image(img,
if
len
(
text
)
==
0
or
len
(
text
)
>
max_text_length
:
logger
.
info
(
"Warning in ppocr/data/rec/img_tools.py:line106: Wrong data type."
"Excepted string with length between
0
and {}, but "
"got '{}'
"
.
format
(
max_text_length
,
label
))
"Excepted string with length between
1
and {}, but "
"got '{}'
. Label is '{}'
"
.
format
(
max_text_length
,
len
(
text
),
label
))
return
None
else
:
if
loss_type
==
"ctc"
:
...
...
ppocr/modeling/heads/det_east_head.py
View file @
2814d997
...
...
@@ -18,6 +18,7 @@ from __future__ import print_function
import
paddle.fluid
as
fluid
from
..common_functions
import
conv_bn_layer
,
deconv_bn_layer
from
collections
import
OrderedDict
class
EASTHead
(
object
):
...
...
@@ -110,7 +111,7 @@ class EASTHead(object):
def
__call__
(
self
,
inputs
):
f_common
=
self
.
unet_fusion
(
inputs
)
f_score
,
f_geo
=
self
.
detector_header
(
f_common
)
predicts
=
{}
predicts
=
OrderedDict
()
predicts
[
'f_score'
]
=
f_score
predicts
[
'f_geo'
]
=
f_geo
return
predicts
ppocr/postprocess/east_postprocess.py
View file @
2814d997
...
...
@@ -20,6 +20,12 @@ import numpy as np
from
.locality_aware_nms
import
nms_locality
import
cv2
import
os
import
sys
__dir__
=
os
.
path
.
dirname
(
__file__
)
sys
.
path
.
append
(
__dir__
)
sys
.
path
.
append
(
os
.
path
.
join
(
__dir__
,
'..'
))
class
EASTPostPocess
(
object
):
"""
...
...
@@ -30,6 +36,11 @@ class EASTPostPocess(object):
self
.
score_thresh
=
params
[
'score_thresh'
]
self
.
cover_thresh
=
params
[
'cover_thresh'
]
self
.
nms_thresh
=
params
[
'nms_thresh'
]
# c++ la-nms is faster, but only support python 3.5
self
.
is_python35
=
False
if
sys
.
version_info
.
major
==
3
and
sys
.
version_info
.
minor
==
5
:
self
.
is_python35
=
True
def
restore_rectangle_quad
(
self
,
origin
,
geometry
):
"""
...
...
@@ -66,7 +77,11 @@ class EASTPostPocess(object):
boxes
=
np
.
zeros
((
text_box_restored
.
shape
[
0
],
9
),
dtype
=
np
.
float32
)
boxes
[:,
:
8
]
=
text_box_restored
.
reshape
((
-
1
,
8
))
boxes
[:,
8
]
=
score_map
[
xy_text
[:,
0
],
xy_text
[:,
1
]]
boxes
=
nms_locality
(
boxes
.
astype
(
np
.
float64
),
nms_thresh
)
if
self
.
is_python35
:
import
lanms
boxes
=
lanms
.
merge_quadrangle_n9
(
boxes
,
nms_thresh
)
else
:
boxes
=
nms_locality
(
boxes
.
astype
(
np
.
float64
),
nms_thresh
)
if
boxes
.
shape
[
0
]
==
0
:
return
[]
# Here we filter some low score boxes by the average score map,
...
...
ppocr/postprocess/lanms/.gitignore
0 → 100644
View file @
2814d997
adaptor.so
ppocr/postprocess/lanms/.ycm_extra_conf.py
0 → 100644
View file @
2814d997
#!/usr/bin/env python
#
# Copyright (C) 2014 Google Inc.
#
# This file is part of YouCompleteMe.
#
# YouCompleteMe is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# YouCompleteMe is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
import
os
import
sys
import
glob
import
ycm_core
# These are the compilation flags that will be used in case there's no
# compilation database set (by default, one is not set).
# CHANGE THIS LIST OF FLAGS. YES, THIS IS THE DROID YOU HAVE BEEN LOOKING FOR.
sys
.
path
.
append
(
os
.
path
.
dirname
(
__file__
))
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
from
plumbum.cmd
import
python_config
flags
=
[
'-Wall'
,
'-Wextra'
,
'-Wnon-virtual-dtor'
,
'-Winvalid-pch'
,
'-Wno-unused-local-typedefs'
,
'-std=c++11'
,
'-x'
,
'c++'
,
'-Iinclude'
,
]
+
python_config
(
'--cflags'
).
split
()
# Set this to the absolute path to the folder (NOT the file!) containing the
# compile_commands.json file to use that instead of 'flags'. See here for
# more details: http://clang.llvm.org/docs/JSONCompilationDatabase.html
#
# Most projects will NOT need to set this to anything; you can just change the
# 'flags' list of compilation flags.
compilation_database_folder
=
''
if
os
.
path
.
exists
(
compilation_database_folder
):
database
=
ycm_core
.
CompilationDatabase
(
compilation_database_folder
)
else
:
database
=
None
SOURCE_EXTENSIONS
=
[
'.cpp'
,
'.cxx'
,
'.cc'
,
'.c'
,
'.m'
,
'.mm'
]
def
DirectoryOfThisScript
():
return
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
)
)
def
MakeRelativePathsInFlagsAbsolute
(
flags
,
working_directory
):
if
not
working_directory
:
return
list
(
flags
)
new_flags
=
[]
make_next_absolute
=
False
path_flags
=
[
'-isystem'
,
'-I'
,
'-iquote'
,
'--sysroot='
]
for
flag
in
flags
:
new_flag
=
flag
if
make_next_absolute
:
make_next_absolute
=
False
if
not
flag
.
startswith
(
'/'
):
new_flag
=
os
.
path
.
join
(
working_directory
,
flag
)
for
path_flag
in
path_flags
:
if
flag
==
path_flag
:
make_next_absolute
=
True
break
if
flag
.
startswith
(
path_flag
):
path
=
flag
[
len
(
path_flag
):
]
new_flag
=
path_flag
+
os
.
path
.
join
(
working_directory
,
path
)
break
if
new_flag
:
new_flags
.
append
(
new_flag
)
return
new_flags
def
IsHeaderFile
(
filename
):
extension
=
os
.
path
.
splitext
(
filename
)[
1
]
return
extension
in
[
'.h'
,
'.hxx'
,
'.hpp'
,
'.hh'
]
def
GetCompilationInfoForFile
(
filename
):
# The compilation_commands.json file generated by CMake does not have entries
# for header files. So we do our best by asking the db for flags for a
# corresponding source file, if any. If one exists, the flags for that file
# should be good enough.
if
IsHeaderFile
(
filename
):
basename
=
os
.
path
.
splitext
(
filename
)[
0
]
for
extension
in
SOURCE_EXTENSIONS
:
replacement_file
=
basename
+
extension
if
os
.
path
.
exists
(
replacement_file
):
compilation_info
=
database
.
GetCompilationInfoForFile
(
replacement_file
)
if
compilation_info
.
compiler_flags_
:
return
compilation_info
return
None
return
database
.
GetCompilationInfoForFile
(
filename
)
# This is the entry point; this function is called by ycmd to produce flags for
# a file.
def
FlagsForFile
(
filename
,
**
kwargs
):
if
database
:
# Bear in mind that compilation_info.compiler_flags_ does NOT return a
# python list, but a "list-like" StringVec object
compilation_info
=
GetCompilationInfoForFile
(
filename
)
if
not
compilation_info
:
return
None
final_flags
=
MakeRelativePathsInFlagsAbsolute
(
compilation_info
.
compiler_flags_
,
compilation_info
.
compiler_working_dir_
)
else
:
relative_to
=
DirectoryOfThisScript
()
final_flags
=
MakeRelativePathsInFlagsAbsolute
(
flags
,
relative_to
)
return
{
'flags'
:
final_flags
,
'do_cache'
:
True
}
ppocr/postprocess/lanms/Makefile
0 → 100644
View file @
2814d997
CXXFLAGS
=
-I
include
-std
=
c++11
-O3
$(
shell
python3-config
--cflags
)
LDFLAGS
=
$(
shell
python3-config
--ldflags
)
DEPS
=
lanms.h
$(
shell
find include
-xtype
f
)
CXX_SOURCES
=
adaptor.cpp include/clipper/clipper.cpp
LIB_SO
=
adaptor.so
$(LIB_SO)
:
$(CXX_SOURCES) $(DEPS)
$(CXX)
-o
$@
$(CXXFLAGS)
$(LDFLAGS)
$(CXX_SOURCES)
--shared
-fPIC
clean
:
rm
-rf
$(LIB_SO)
ppocr/postprocess/lanms/__init__.py
0 → 100644
View file @
2814d997
import
subprocess
import
os
import
numpy
as
np
BASE_DIR
=
os
.
path
.
dirname
(
os
.
path
.
realpath
(
__file__
))
if
subprocess
.
call
([
'make'
,
'-C'
,
BASE_DIR
])
!=
0
:
# return value
raise
RuntimeError
(
'Cannot compile lanms: {}'
.
format
(
BASE_DIR
))
def
merge_quadrangle_n9
(
polys
,
thres
=
0.3
,
precision
=
10000
):
from
.adaptor
import
merge_quadrangle_n9
as
nms_impl
if
len
(
polys
)
==
0
:
return
np
.
array
([],
dtype
=
'float32'
)
p
=
polys
.
copy
()
p
[:,:
8
]
*=
precision
ret
=
np
.
array
(
nms_impl
(
p
,
thres
),
dtype
=
'float32'
)
ret
[:,:
8
]
/=
precision
return
ret
ppocr/postprocess/lanms/__main__.py
0 → 100644
View file @
2814d997
import
numpy
as
np
from
.
import
merge_quadrangle_n9
if
__name__
==
'__main__'
:
# unit square with confidence 1
q
=
np
.
array
([
0
,
0
,
0
,
1
,
1
,
1
,
1
,
0
,
1
],
dtype
=
'float32'
)
print
(
merge_quadrangle_n9
(
np
.
array
([
q
,
q
+
0.1
,
q
+
2
])))
ppocr/postprocess/lanms/adaptor.cpp
0 → 100644
View file @
2814d997
#include "pybind11/pybind11.h"
#include "pybind11/numpy.h"
#include "pybind11/stl.h"
#include "pybind11/stl_bind.h"
#include "lanms.h"
namespace
py
=
pybind11
;
namespace
lanms_adaptor
{
std
::
vector
<
std
::
vector
<
float
>>
polys2floats
(
const
std
::
vector
<
lanms
::
Polygon
>
&
polys
)
{
std
::
vector
<
std
::
vector
<
float
>>
ret
;
for
(
size_t
i
=
0
;
i
<
polys
.
size
();
i
++
)
{
auto
&
p
=
polys
[
i
];
auto
&
poly
=
p
.
poly
;
ret
.
emplace_back
(
std
::
vector
<
float
>
{
float
(
poly
[
0
].
X
),
float
(
poly
[
0
].
Y
),
float
(
poly
[
1
].
X
),
float
(
poly
[
1
].
Y
),
float
(
poly
[
2
].
X
),
float
(
poly
[
2
].
Y
),
float
(
poly
[
3
].
X
),
float
(
poly
[
3
].
Y
),
float
(
p
.
score
),
});
}
return
ret
;
}
/**
*
* \param quad_n9 an n-by-9 numpy array, where first 8 numbers denote the
* quadrangle, and the last one is the score
* \param iou_threshold two quadrangles with iou score above this threshold
* will be merged
*
* \return an n-by-9 numpy array, the merged quadrangles
*/
std
::
vector
<
std
::
vector
<
float
>>
merge_quadrangle_n9
(
py
::
array_t
<
float
,
py
::
array
::
c_style
|
py
::
array
::
forcecast
>
quad_n9
,
float
iou_threshold
)
{
auto
pbuf
=
quad_n9
.
request
();
if
(
pbuf
.
ndim
!=
2
||
pbuf
.
shape
[
1
]
!=
9
)
throw
std
::
runtime_error
(
"quadrangles must have a shape of (n, 9)"
);
auto
n
=
pbuf
.
shape
[
0
];
auto
ptr
=
static_cast
<
float
*>
(
pbuf
.
ptr
);
return
polys2floats
(
lanms
::
merge_quadrangle_n9
(
ptr
,
n
,
iou_threshold
));
}
}
PYBIND11_PLUGIN
(
adaptor
)
{
py
::
module
m
(
"adaptor"
,
"NMS"
);
m
.
def
(
"merge_quadrangle_n9"
,
&
lanms_adaptor
::
merge_quadrangle_n9
,
"merge quadrangels"
);
return
m
.
ptr
();
}
ppocr/postprocess/lanms/include/clipper/clipper.cpp
0 → 100644
View file @
2814d997
This diff is collapsed.
Click to expand it.
ppocr/postprocess/lanms/include/clipper/clipper.hpp
0 → 100644
View file @
2814d997
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 6.4.0 *
* Date : 2 July 2015 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2015 *
* *
* License: *
* Use, modification & distribution is subject to Boost Software License Ver 1. *
* http://www.boost.org/LICENSE_1_0.txt *
* *
* Attributions: *
* The code in this library is an extension of Bala Vatti's clipping algorithm: *
* "A generic solution to polygon clipping" *
* Communications of the ACM, Vol 35, Issue 7 (July 1992) pp 56-63. *
* http://portal.acm.org/citation.cfm?id=129906 *
* *
* Computer graphics and geometric modeling: implementation and algorithms *
* By Max K. Agoston *
* Springer; 1 edition (January 4, 2005) *
* http://books.google.com/books?q=vatti+clipping+agoston *
* *
* See also: *
* "Polygon Offsetting by Computing Winding Numbers" *
* Paper no. DETC2005-85513 pp. 565-575 *
* ASME 2005 International Design Engineering Technical Conferences *
* and Computers and Information in Engineering Conference (IDETC/CIE2005) *
* September 24-28, 2005 , Long Beach, California, USA *
* http://www.me.berkeley.edu/~mcmains/pubs/DAC05OffsetPolygon.pdf *
* *
*******************************************************************************/
#ifndef clipper_hpp
#define clipper_hpp
#define CLIPPER_VERSION "6.2.6"
//use_int32: When enabled 32bit ints are used instead of 64bit ints. This
//improve performance but coordinate values are limited to the range +/- 46340
//#define use_int32
//use_xyz: adds a Z member to IntPoint. Adds a minor cost to perfomance.
//#define use_xyz
//use_lines: Enables line clipping. Adds a very minor cost to performance.
#define use_lines
//use_deprecated: Enables temporary support for the obsolete functions
//#define use_deprecated
#include <vector>
#include <list>
#include <set>
#include <stdexcept>
#include <cstring>
#include <cstdlib>
#include <ostream>
#include <functional>
#include <queue>
namespace
ClipperLib
{
enum
ClipType
{
ctIntersection
,
ctUnion
,
ctDifference
,
ctXor
};
enum
PolyType
{
ptSubject
,
ptClip
};
//By far the most widely used winding rules for polygon filling are
//EvenOdd & NonZero (GDI, GDI+, XLib, OpenGL, Cairo, AGG, Quartz, SVG, Gr32)
//Others rules include Positive, Negative and ABS_GTR_EQ_TWO (only in OpenGL)
//see http://glprogramming.com/red/chapter11.html
enum
PolyFillType
{
pftEvenOdd
,
pftNonZero
,
pftPositive
,
pftNegative
};
#ifdef use_int32
typedef
int
cInt
;
static
cInt
const
loRange
=
0x7FFF
;
static
cInt
const
hiRange
=
0x7FFF
;
#else
typedef
signed
long
long
cInt
;
static
cInt
const
loRange
=
0x3FFFFFFF
;
static
cInt
const
hiRange
=
0x3FFFFFFFFFFFFFFFLL
;
typedef
signed
long
long
long64
;
//used by Int128 class
typedef
unsigned
long
long
ulong64
;
#endif
struct
IntPoint
{
cInt
X
;
cInt
Y
;
#ifdef use_xyz
cInt
Z
;
IntPoint
(
cInt
x
=
0
,
cInt
y
=
0
,
cInt
z
=
0
)
:
X
(
x
),
Y
(
y
),
Z
(
z
)
{};
#else
IntPoint
(
cInt
x
=
0
,
cInt
y
=
0
)
:
X
(
x
),
Y
(
y
)
{};
#endif
friend
inline
bool
operator
==
(
const
IntPoint
&
a
,
const
IntPoint
&
b
)
{
return
a
.
X
==
b
.
X
&&
a
.
Y
==
b
.
Y
;
}
friend
inline
bool
operator
!=
(
const
IntPoint
&
a
,
const
IntPoint
&
b
)
{
return
a
.
X
!=
b
.
X
||
a
.
Y
!=
b
.
Y
;
}
};
//------------------------------------------------------------------------------
typedef
std
::
vector
<
IntPoint
>
Path
;
typedef
std
::
vector
<
Path
>
Paths
;
inline
Path
&
operator
<<
(
Path
&
poly
,
const
IntPoint
&
p
)
{
poly
.
push_back
(
p
);
return
poly
;}
inline
Paths
&
operator
<<
(
Paths
&
polys
,
const
Path
&
p
)
{
polys
.
push_back
(
p
);
return
polys
;}
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
IntPoint
&
p
);
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
Path
&
p
);
std
::
ostream
&
operator
<<
(
std
::
ostream
&
s
,
const
Paths
&
p
);
struct
DoublePoint
{
double
X
;
double
Y
;
DoublePoint
(
double
x
=
0
,
double
y
=
0
)
:
X
(
x
),
Y
(
y
)
{}
DoublePoint
(
IntPoint
ip
)
:
X
((
double
)
ip
.
X
),
Y
((
double
)
ip
.
Y
)
{}
};
//------------------------------------------------------------------------------
#ifdef use_xyz
typedef
void
(
*
ZFillCallback
)(
IntPoint
&
e1bot
,
IntPoint
&
e1top
,
IntPoint
&
e2bot
,
IntPoint
&
e2top
,
IntPoint
&
pt
);
#endif
enum
InitOptions
{
ioReverseSolution
=
1
,
ioStrictlySimple
=
2
,
ioPreserveCollinear
=
4
};
enum
JoinType
{
jtSquare
,
jtRound
,
jtMiter
};
enum
EndType
{
etClosedPolygon
,
etClosedLine
,
etOpenButt
,
etOpenSquare
,
etOpenRound
};
class
PolyNode
;
typedef
std
::
vector
<
PolyNode
*
>
PolyNodes
;
class
PolyNode
{
public:
PolyNode
();
virtual
~
PolyNode
(){};
Path
Contour
;
PolyNodes
Childs
;
PolyNode
*
Parent
;
PolyNode
*
GetNext
()
const
;
bool
IsHole
()
const
;
bool
IsOpen
()
const
;
int
ChildCount
()
const
;
private:
unsigned
Index
;
//node index in Parent.Childs
bool
m_IsOpen
;
JoinType
m_jointype
;
EndType
m_endtype
;
PolyNode
*
GetNextSiblingUp
()
const
;
void
AddChild
(
PolyNode
&
child
);
friend
class
Clipper
;
//to access Index
friend
class
ClipperOffset
;
};
class
PolyTree
:
public
PolyNode
{
public:
~
PolyTree
(){
Clear
();};
PolyNode
*
GetFirst
()
const
;
void
Clear
();
int
Total
()
const
;
private:
PolyNodes
AllNodes
;
friend
class
Clipper
;
//to access AllNodes
};
bool
Orientation
(
const
Path
&
poly
);
double
Area
(
const
Path
&
poly
);
int
PointInPolygon
(
const
IntPoint
&
pt
,
const
Path
&
path
);
void
SimplifyPolygon
(
const
Path
&
in_poly
,
Paths
&
out_polys
,
PolyFillType
fillType
=
pftEvenOdd
);
void
SimplifyPolygons
(
const
Paths
&
in_polys
,
Paths
&
out_polys
,
PolyFillType
fillType
=
pftEvenOdd
);
void
SimplifyPolygons
(
Paths
&
polys
,
PolyFillType
fillType
=
pftEvenOdd
);
void
CleanPolygon
(
const
Path
&
in_poly
,
Path
&
out_poly
,
double
distance
=
1.415
);
void
CleanPolygon
(
Path
&
poly
,
double
distance
=
1.415
);
void
CleanPolygons
(
const
Paths
&
in_polys
,
Paths
&
out_polys
,
double
distance
=
1.415
);
void
CleanPolygons
(
Paths
&
polys
,
double
distance
=
1.415
);
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Path
&
path
,
Paths
&
solution
,
bool
pathIsClosed
);
void
MinkowskiSum
(
const
Path
&
pattern
,
const
Paths
&
paths
,
Paths
&
solution
,
bool
pathIsClosed
);
void
MinkowskiDiff
(
const
Path
&
poly1
,
const
Path
&
poly2
,
Paths
&
solution
);
void
PolyTreeToPaths
(
const
PolyTree
&
polytree
,
Paths
&
paths
);
void
ClosedPathsFromPolyTree
(
const
PolyTree
&
polytree
,
Paths
&
paths
);
void
OpenPathsFromPolyTree
(
PolyTree
&
polytree
,
Paths
&
paths
);
void
ReversePath
(
Path
&
p
);
void
ReversePaths
(
Paths
&
p
);
struct
IntRect
{
cInt
left
;
cInt
top
;
cInt
right
;
cInt
bottom
;
};
//enums that are used internally ...
enum
EdgeSide
{
esLeft
=
1
,
esRight
=
2
};
//forward declarations (for stuff used internally) ...
struct
TEdge
;
struct
IntersectNode
;
struct
LocalMinimum
;
struct
OutPt
;
struct
OutRec
;
struct
Join
;
typedef
std
::
vector
<
OutRec
*
>
PolyOutList
;
typedef
std
::
vector
<
TEdge
*
>
EdgeList
;
typedef
std
::
vector
<
Join
*
>
JoinList
;
typedef
std
::
vector
<
IntersectNode
*
>
IntersectList
;
//------------------------------------------------------------------------------
//ClipperBase is the ancestor to the Clipper class. It should not be
//instantiated directly. This class simply abstracts the conversion of sets of
//polygon coordinates into edge objects that are stored in a LocalMinima list.
class
ClipperBase
{
public:
ClipperBase
();
virtual
~
ClipperBase
();
virtual
bool
AddPath
(
const
Path
&
pg
,
PolyType
PolyTyp
,
bool
Closed
);
bool
AddPaths
(
const
Paths
&
ppg
,
PolyType
PolyTyp
,
bool
Closed
);
virtual
void
Clear
();
IntRect
GetBounds
();
bool
PreserveCollinear
()
{
return
m_PreserveCollinear
;};
void
PreserveCollinear
(
bool
value
)
{
m_PreserveCollinear
=
value
;};
protected:
void
DisposeLocalMinimaList
();
TEdge
*
AddBoundsToLML
(
TEdge
*
e
,
bool
IsClosed
);
virtual
void
Reset
();
TEdge
*
ProcessBound
(
TEdge
*
E
,
bool
IsClockwise
);
void
InsertScanbeam
(
const
cInt
Y
);
bool
PopScanbeam
(
cInt
&
Y
);
bool
LocalMinimaPending
();
bool
PopLocalMinima
(
cInt
Y
,
const
LocalMinimum
*&
locMin
);
OutRec
*
CreateOutRec
();
void
DisposeAllOutRecs
();
void
DisposeOutRec
(
PolyOutList
::
size_type
index
);
void
SwapPositionsInAEL
(
TEdge
*
edge1
,
TEdge
*
edge2
);
void
DeleteFromAEL
(
TEdge
*
e
);
void
UpdateEdgeIntoAEL
(
TEdge
*&
e
);
typedef
std
::
vector
<
LocalMinimum
>
MinimaList
;
MinimaList
::
iterator
m_CurrentLM
;
MinimaList
m_MinimaList
;
bool
m_UseFullRange
;
EdgeList
m_edges
;
bool
m_PreserveCollinear
;
bool
m_HasOpenPaths
;
PolyOutList
m_PolyOuts
;
TEdge
*
m_ActiveEdges
;
typedef
std
::
priority_queue
<
cInt
>
ScanbeamList
;
ScanbeamList
m_Scanbeam
;
};
//------------------------------------------------------------------------------
class
Clipper
:
public
virtual
ClipperBase
{
public:
Clipper
(
int
initOptions
=
0
);
bool
Execute
(
ClipType
clipType
,
Paths
&
solution
,
PolyFillType
fillType
=
pftEvenOdd
);
bool
Execute
(
ClipType
clipType
,
Paths
&
solution
,
PolyFillType
subjFillType
,
PolyFillType
clipFillType
);
bool
Execute
(
ClipType
clipType
,
PolyTree
&
polytree
,
PolyFillType
fillType
=
pftEvenOdd
);
bool
Execute
(
ClipType
clipType
,
PolyTree
&
polytree
,
PolyFillType
subjFillType
,
PolyFillType
clipFillType
);
bool
ReverseSolution
()
{
return
m_ReverseOutput
;
};
void
ReverseSolution
(
bool
value
)
{
m_ReverseOutput
=
value
;};
bool
StrictlySimple
()
{
return
m_StrictSimple
;};
void
StrictlySimple
(
bool
value
)
{
m_StrictSimple
=
value
;};
//set the callback function for z value filling on intersections (otherwise Z is 0)
#ifdef use_xyz
void
ZFillFunction
(
ZFillCallback
zFillFunc
);
#endif
protected:
virtual
bool
ExecuteInternal
();
private:
JoinList
m_Joins
;
JoinList
m_GhostJoins
;
IntersectList
m_IntersectList
;
ClipType
m_ClipType
;
typedef
std
::
list
<
cInt
>
MaximaList
;
MaximaList
m_Maxima
;
TEdge
*
m_SortedEdges
;
bool
m_ExecuteLocked
;
PolyFillType
m_ClipFillType
;
PolyFillType
m_SubjFillType
;
bool
m_ReverseOutput
;
bool
m_UsingPolyTree
;
bool
m_StrictSimple
;
#ifdef use_xyz
ZFillCallback
m_ZFill
;
//custom callback
#endif
void
SetWindingCount
(
TEdge
&
edge
);
bool
IsEvenOddFillType
(
const
TEdge
&
edge
)
const
;
bool
IsEvenOddAltFillType
(
const
TEdge
&
edge
)
const
;
void
InsertLocalMinimaIntoAEL
(
const
cInt
botY
);
void
InsertEdgeIntoAEL
(
TEdge
*
edge
,
TEdge
*
startEdge
);
void
AddEdgeToSEL
(
TEdge
*
edge
);
bool
PopEdgeFromSEL
(
TEdge
*&
edge
);
void
CopyAELToSEL
();
void
DeleteFromSEL
(
TEdge
*
e
);
void
SwapPositionsInSEL
(
TEdge
*
edge1
,
TEdge
*
edge2
);
bool
IsContributing
(
const
TEdge
&
edge
)
const
;
bool
IsTopHorz
(
const
cInt
XPos
);
void
DoMaxima
(
TEdge
*
e
);
void
ProcessHorizontals
();
void
ProcessHorizontal
(
TEdge
*
horzEdge
);
void
AddLocalMaxPoly
(
TEdge
*
e1
,
TEdge
*
e2
,
const
IntPoint
&
pt
);
OutPt
*
AddLocalMinPoly
(
TEdge
*
e1
,
TEdge
*
e2
,
const
IntPoint
&
pt
);
OutRec
*
GetOutRec
(
int
idx
);
void
AppendPolygon
(
TEdge
*
e1
,
TEdge
*
e2
);
void
IntersectEdges
(
TEdge
*
e1
,
TEdge
*
e2
,
IntPoint
&
pt
);
OutPt
*
AddOutPt
(
TEdge
*
e
,
const
IntPoint
&
pt
);
OutPt
*
GetLastOutPt
(
TEdge
*
e
);
bool
ProcessIntersections
(
const
cInt
topY
);
void
BuildIntersectList
(
const
cInt
topY
);
void
ProcessIntersectList
();
void
ProcessEdgesAtTopOfScanbeam
(
const
cInt
topY
);
void
BuildResult
(
Paths
&
polys
);
void
BuildResult2
(
PolyTree
&
polytree
);
void
SetHoleState
(
TEdge
*
e
,
OutRec
*
outrec
);
void
DisposeIntersectNodes
();
bool
FixupIntersectionOrder
();
void
FixupOutPolygon
(
OutRec
&
outrec
);
void
FixupOutPolyline
(
OutRec
&
outrec
);
bool
IsHole
(
TEdge
*
e
);
bool
FindOwnerFromSplitRecs
(
OutRec
&
outRec
,
OutRec
*&
currOrfl
);
void
FixHoleLinkage
(
OutRec
&
outrec
);
void
AddJoin
(
OutPt
*
op1
,
OutPt
*
op2
,
const
IntPoint
offPt
);
void
ClearJoins
();
void
ClearGhostJoins
();
void
AddGhostJoin
(
OutPt
*
op
,
const
IntPoint
offPt
);
bool
JoinPoints
(
Join
*
j
,
OutRec
*
outRec1
,
OutRec
*
outRec2
);
void
JoinCommonEdges
();
void
DoSimplePolygons
();
void
FixupFirstLefts1
(
OutRec
*
OldOutRec
,
OutRec
*
NewOutRec
);
void
FixupFirstLefts2
(
OutRec
*
InnerOutRec
,
OutRec
*
OuterOutRec
);
void
FixupFirstLefts3
(
OutRec
*
OldOutRec
,
OutRec
*
NewOutRec
);
#ifdef use_xyz
void
SetZ
(
IntPoint
&
pt
,
TEdge
&
e1
,
TEdge
&
e2
);
#endif
};
//------------------------------------------------------------------------------
class
ClipperOffset
{
public:
ClipperOffset
(
double
miterLimit
=
2.0
,
double
roundPrecision
=
0.25
);
~
ClipperOffset
();
void
AddPath
(
const
Path
&
path
,
JoinType
joinType
,
EndType
endType
);
void
AddPaths
(
const
Paths
&
paths
,
JoinType
joinType
,
EndType
endType
);
void
Execute
(
Paths
&
solution
,
double
delta
);
void
Execute
(
PolyTree
&
solution
,
double
delta
);
void
Clear
();
double
MiterLimit
;
double
ArcTolerance
;
private:
Paths
m_destPolys
;
Path
m_srcPoly
;
Path
m_destPoly
;
std
::
vector
<
DoublePoint
>
m_normals
;
double
m_delta
,
m_sinA
,
m_sin
,
m_cos
;
double
m_miterLim
,
m_StepsPerRad
;
IntPoint
m_lowest
;
PolyNode
m_polyNodes
;
void
FixOrientations
();
void
DoOffset
(
double
delta
);
void
OffsetPoint
(
int
j
,
int
&
k
,
JoinType
jointype
);
void
DoSquare
(
int
j
,
int
k
);
void
DoMiter
(
int
j
,
int
k
,
double
r
);
void
DoRound
(
int
j
,
int
k
);
};
//------------------------------------------------------------------------------
class
clipperException
:
public
std
::
exception
{
public:
clipperException
(
const
char
*
description
)
:
m_descr
(
description
)
{}
virtual
~
clipperException
()
throw
()
{}
virtual
const
char
*
what
()
const
throw
()
{
return
m_descr
.
c_str
();}
private:
std
::
string
m_descr
;
};
//------------------------------------------------------------------------------
}
//ClipperLib namespace
#endif //clipper_hpp
ppocr/postprocess/lanms/include/pybind11/attr.h
0 → 100644
View file @
2814d997
/*
pybind11/attr.h: Infrastructure for processing custom
type and function attributes
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#pragma once
#include "cast.h"
NAMESPACE_BEGIN
(
pybind11
)
/// \addtogroup annotations
/// @{
/// Annotation for methods
struct
is_method
{
handle
class_
;
is_method
(
const
handle
&
c
)
:
class_
(
c
)
{
}
};
/// Annotation for operators
struct
is_operator
{
};
/// Annotation for parent scope
struct
scope
{
handle
value
;
scope
(
const
handle
&
s
)
:
value
(
s
)
{
}
};
/// Annotation for documentation
struct
doc
{
const
char
*
value
;
doc
(
const
char
*
value
)
:
value
(
value
)
{
}
};
/// Annotation for function names
struct
name
{
const
char
*
value
;
name
(
const
char
*
value
)
:
value
(
value
)
{
}
};
/// Annotation indicating that a function is an overload associated with a given "sibling"
struct
sibling
{
handle
value
;
sibling
(
const
handle
&
value
)
:
value
(
value
.
ptr
())
{
}
};
/// Annotation indicating that a class derives from another given type
template
<
typename
T
>
struct
base
{
PYBIND11_DEPRECATED
(
"base<T>() was deprecated in favor of specifying 'T' as a template argument to class_"
)
base
()
{
}
};
/// Keep patient alive while nurse lives
template
<
size_t
Nurse
,
size_t
Patient
>
struct
keep_alive
{
};
/// Annotation indicating that a class is involved in a multiple inheritance relationship
struct
multiple_inheritance
{
};
/// Annotation which enables dynamic attributes, i.e. adds `__dict__` to a class
struct
dynamic_attr
{
};
/// Annotation which enables the buffer protocol for a type
struct
buffer_protocol
{
};
/// Annotation which requests that a special metaclass is created for a type
struct
metaclass
{
handle
value
;
PYBIND11_DEPRECATED
(
"py::metaclass() is no longer required. It's turned on by default now."
)
metaclass
()
{}
/// Override pybind11's default metaclass
explicit
metaclass
(
handle
value
)
:
value
(
value
)
{
}
};
/// Annotation to mark enums as an arithmetic type
struct
arithmetic
{
};
/** \rst
A call policy which places one or more guard variables (``Ts...``) around the function call.
For example, this definition:
.. code-block:: cpp
m.def("foo", foo, py::call_guard<T>());
is equivalent to the following pseudocode:
.. code-block:: cpp
m.def("foo", [](args...) {
T scope_guard;
return foo(args...); // forwarded arguments
});
\endrst */
template
<
typename
...
Ts
>
struct
call_guard
;
template
<
>
struct
call_guard
<>
{
using
type
=
detail
::
void_type
;
};
template
<
typename
T
>
struct
call_guard
<
T
>
{
static_assert
(
std
::
is_default_constructible
<
T
>::
value
,
"The guard type must be default constructible"
);
using
type
=
T
;
};
template
<
typename
T
,
typename
...
Ts
>
struct
call_guard
<
T
,
Ts
...
>
{
struct
type
{
T
guard
{};
// Compose multiple guard types with left-to-right default-constructor order
typename
call_guard
<
Ts
...
>::
type
next
{};
};
};
/// @} annotations
NAMESPACE_BEGIN
(
detail
)
/* Forward declarations */
enum
op_id
:
int
;
enum
op_type
:
int
;
struct
undefined_t
;
template
<
op_id
id
,
op_type
ot
,
typename
L
=
undefined_t
,
typename
R
=
undefined_t
>
struct
op_
;
template
<
typename
...
Args
>
struct
init
;
template
<
typename
...
Args
>
struct
init_alias
;
inline
void
keep_alive_impl
(
size_t
Nurse
,
size_t
Patient
,
function_call
&
call
,
handle
ret
);
/// Internal data structure which holds metadata about a keyword argument
struct
argument_record
{
const
char
*
name
;
///< Argument name
const
char
*
descr
;
///< Human-readable version of the argument value
handle
value
;
///< Associated Python object
bool
convert
:
1
;
///< True if the argument is allowed to convert when loading
bool
none
:
1
;
///< True if None is allowed when loading
argument_record
(
const
char
*
name
,
const
char
*
descr
,
handle
value
,
bool
convert
,
bool
none
)
:
name
(
name
),
descr
(
descr
),
value
(
value
),
convert
(
convert
),
none
(
none
)
{
}
};
/// Internal data structure which holds metadata about a bound function (signature, overloads, etc.)
struct
function_record
{
function_record
()
:
is_constructor
(
false
),
is_stateless
(
false
),
is_operator
(
false
),
has_args
(
false
),
has_kwargs
(
false
),
is_method
(
false
)
{
}
/// Function name
char
*
name
=
nullptr
;
/* why no C++ strings? They generate heavier code.. */
// User-specified documentation string
char
*
doc
=
nullptr
;
/// Human-readable version of the function signature
char
*
signature
=
nullptr
;
/// List of registered keyword arguments
std
::
vector
<
argument_record
>
args
;
/// Pointer to lambda function which converts arguments and performs the actual call
handle
(
*
impl
)
(
function_call
&
)
=
nullptr
;
/// Storage for the wrapped function pointer and captured data, if any
void
*
data
[
3
]
=
{
};
/// Pointer to custom destructor for 'data' (if needed)
void
(
*
free_data
)
(
function_record
*
ptr
)
=
nullptr
;
/// Return value policy associated with this function
return_value_policy
policy
=
return_value_policy
::
automatic
;
/// True if name == '__init__'
bool
is_constructor
:
1
;
/// True if this is a stateless function pointer
bool
is_stateless
:
1
;
/// True if this is an operator (__add__), etc.
bool
is_operator
:
1
;
/// True if the function has a '*args' argument
bool
has_args
:
1
;
/// True if the function has a '**kwargs' argument
bool
has_kwargs
:
1
;
/// True if this is a method
bool
is_method
:
1
;
/// Number of arguments (including py::args and/or py::kwargs, if present)
std
::
uint16_t
nargs
;
/// Python method object
PyMethodDef
*
def
=
nullptr
;
/// Python handle to the parent scope (a class or a module)
handle
scope
;
/// Python handle to the sibling function representing an overload chain
handle
sibling
;
/// Pointer to next overload
function_record
*
next
=
nullptr
;
};
/// Special data structure which (temporarily) holds metadata about a bound class
struct
type_record
{
PYBIND11_NOINLINE
type_record
()
:
multiple_inheritance
(
false
),
dynamic_attr
(
false
),
buffer_protocol
(
false
)
{
}
/// Handle to the parent scope
handle
scope
;
/// Name of the class
const
char
*
name
=
nullptr
;
// Pointer to RTTI type_info data structure
const
std
::
type_info
*
type
=
nullptr
;
/// How large is the underlying C++ type?
size_t
type_size
=
0
;
/// How large is the type's holder?
size_t
holder_size
=
0
;
/// The global operator new can be overridden with a class-specific variant
void
*
(
*
operator_new
)(
size_t
)
=
::
operator
new
;
/// Function pointer to class_<..>::init_instance
void
(
*
init_instance
)(
instance
*
,
const
void
*
)
=
nullptr
;
/// Function pointer to class_<..>::dealloc
void
(
*
dealloc
)(
const
detail
::
value_and_holder
&
)
=
nullptr
;
/// List of base classes of the newly created type
list
bases
;
/// Optional docstring
const
char
*
doc
=
nullptr
;
/// Custom metaclass (optional)
handle
metaclass
;
/// Multiple inheritance marker
bool
multiple_inheritance
:
1
;
/// Does the class manage a __dict__?
bool
dynamic_attr
:
1
;
/// Does the class implement the buffer protocol?
bool
buffer_protocol
:
1
;
/// Is the default (unique_ptr) holder type used?
bool
default_holder
:
1
;
PYBIND11_NOINLINE
void
add_base
(
const
std
::
type_info
&
base
,
void
*
(
*
caster
)(
void
*
))
{
auto
base_info
=
detail
::
get_type_info
(
base
,
false
);
if
(
!
base_info
)
{
std
::
string
tname
(
base
.
name
());
detail
::
clean_type_id
(
tname
);
pybind11_fail
(
"generic_type: type
\"
"
+
std
::
string
(
name
)
+
"
\"
referenced unknown base type
\"
"
+
tname
+
"
\"
"
);
}
if
(
default_holder
!=
base_info
->
default_holder
)
{
std
::
string
tname
(
base
.
name
());
detail
::
clean_type_id
(
tname
);
pybind11_fail
(
"generic_type: type
\"
"
+
std
::
string
(
name
)
+
"
\"
"
+
(
default_holder
?
"does not have"
:
"has"
)
+
" a non-default holder type while its base
\"
"
+
tname
+
"
\"
"
+
(
base_info
->
default_holder
?
"does not"
:
"does"
));
}
bases
.
append
((
PyObject
*
)
base_info
->
type
);
if
(
base_info
->
type
->
tp_dictoffset
!=
0
)
dynamic_attr
=
true
;
if
(
caster
)
base_info
->
implicit_casts
.
emplace_back
(
type
,
caster
);
}
};
inline
function_call
::
function_call
(
function_record
&
f
,
handle
p
)
:
func
(
f
),
parent
(
p
)
{
args
.
reserve
(
f
.
nargs
);
args_convert
.
reserve
(
f
.
nargs
);
}
/**
* Partial template specializations to process custom attributes provided to
* cpp_function_ and class_. These are either used to initialize the respective
* fields in the type_record and function_record data structures or executed at
* runtime to deal with custom call policies (e.g. keep_alive).
*/
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
process_attribute
;
template
<
typename
T
>
struct
process_attribute_default
{
/// Default implementation: do nothing
static
void
init
(
const
T
&
,
function_record
*
)
{
}
static
void
init
(
const
T
&
,
type_record
*
)
{
}
static
void
precall
(
function_call
&
)
{
}
static
void
postcall
(
function_call
&
,
handle
)
{
}
};
/// Process an attribute specifying the function's name
template
<
>
struct
process_attribute
<
name
>
:
process_attribute_default
<
name
>
{
static
void
init
(
const
name
&
n
,
function_record
*
r
)
{
r
->
name
=
const_cast
<
char
*>
(
n
.
value
);
}
};
/// Process an attribute specifying the function's docstring
template
<
>
struct
process_attribute
<
doc
>
:
process_attribute_default
<
doc
>
{
static
void
init
(
const
doc
&
n
,
function_record
*
r
)
{
r
->
doc
=
const_cast
<
char
*>
(
n
.
value
);
}
};
/// Process an attribute specifying the function's docstring (provided as a C-style string)
template
<
>
struct
process_attribute
<
const
char
*>
:
process_attribute_default
<
const
char
*>
{
static
void
init
(
const
char
*
d
,
function_record
*
r
)
{
r
->
doc
=
const_cast
<
char
*>
(
d
);
}
static
void
init
(
const
char
*
d
,
type_record
*
r
)
{
r
->
doc
=
const_cast
<
char
*>
(
d
);
}
};
template
<
>
struct
process_attribute
<
char
*>
:
process_attribute
<
const
char
*>
{
};
/// Process an attribute indicating the function's return value policy
template
<
>
struct
process_attribute
<
return_value_policy
>
:
process_attribute_default
<
return_value_policy
>
{
static
void
init
(
const
return_value_policy
&
p
,
function_record
*
r
)
{
r
->
policy
=
p
;
}
};
/// Process an attribute which indicates that this is an overloaded function associated with a given sibling
template
<
>
struct
process_attribute
<
sibling
>
:
process_attribute_default
<
sibling
>
{
static
void
init
(
const
sibling
&
s
,
function_record
*
r
)
{
r
->
sibling
=
s
.
value
;
}
};
/// Process an attribute which indicates that this function is a method
template
<
>
struct
process_attribute
<
is_method
>
:
process_attribute_default
<
is_method
>
{
static
void
init
(
const
is_method
&
s
,
function_record
*
r
)
{
r
->
is_method
=
true
;
r
->
scope
=
s
.
class_
;
}
};
/// Process an attribute which indicates the parent scope of a method
template
<
>
struct
process_attribute
<
scope
>
:
process_attribute_default
<
scope
>
{
static
void
init
(
const
scope
&
s
,
function_record
*
r
)
{
r
->
scope
=
s
.
value
;
}
};
/// Process an attribute which indicates that this function is an operator
template
<
>
struct
process_attribute
<
is_operator
>
:
process_attribute_default
<
is_operator
>
{
static
void
init
(
const
is_operator
&
,
function_record
*
r
)
{
r
->
is_operator
=
true
;
}
};
/// Process a keyword argument attribute (*without* a default value)
template
<
>
struct
process_attribute
<
arg
>
:
process_attribute_default
<
arg
>
{
static
void
init
(
const
arg
&
a
,
function_record
*
r
)
{
if
(
r
->
is_method
&&
r
->
args
.
empty
())
r
->
args
.
emplace_back
(
"self"
,
nullptr
,
handle
(),
true
/*convert*/
,
false
/*none not allowed*/
);
r
->
args
.
emplace_back
(
a
.
name
,
nullptr
,
handle
(),
!
a
.
flag_noconvert
,
a
.
flag_none
);
}
};
/// Process a keyword argument attribute (*with* a default value)
template
<
>
struct
process_attribute
<
arg_v
>
:
process_attribute_default
<
arg_v
>
{
static
void
init
(
const
arg_v
&
a
,
function_record
*
r
)
{
if
(
r
->
is_method
&&
r
->
args
.
empty
())
r
->
args
.
emplace_back
(
"self"
,
nullptr
/*descr*/
,
handle
()
/*parent*/
,
true
/*convert*/
,
false
/*none not allowed*/
);
if
(
!
a
.
value
)
{
#if !defined(NDEBUG)
std
::
string
descr
(
"'"
);
if
(
a
.
name
)
descr
+=
std
::
string
(
a
.
name
)
+
": "
;
descr
+=
a
.
type
+
"'"
;
if
(
r
->
is_method
)
{
if
(
r
->
name
)
descr
+=
" in method '"
+
(
std
::
string
)
str
(
r
->
scope
)
+
"."
+
(
std
::
string
)
r
->
name
+
"'"
;
else
descr
+=
" in method of '"
+
(
std
::
string
)
str
(
r
->
scope
)
+
"'"
;
}
else
if
(
r
->
name
)
{
descr
+=
" in function '"
+
(
std
::
string
)
r
->
name
+
"'"
;
}
pybind11_fail
(
"arg(): could not convert default argument "
+
descr
+
" into a Python object (type not registered yet?)"
);
#else
pybind11_fail
(
"arg(): could not convert default argument "
"into a Python object (type not registered yet?). "
"Compile in debug mode for more information."
);
#endif
}
r
->
args
.
emplace_back
(
a
.
name
,
a
.
descr
,
a
.
value
.
inc_ref
(),
!
a
.
flag_noconvert
,
a
.
flag_none
);
}
};
/// Process a parent class attribute. Single inheritance only (class_ itself already guarantees that)
template
<
typename
T
>
struct
process_attribute
<
T
,
enable_if_t
<
is_pyobject
<
T
>::
value
>>
:
process_attribute_default
<
handle
>
{
static
void
init
(
const
handle
&
h
,
type_record
*
r
)
{
r
->
bases
.
append
(
h
);
}
};
/// Process a parent class attribute (deprecated, does not support multiple inheritance)
template
<
typename
T
>
struct
process_attribute
<
base
<
T
>>
:
process_attribute_default
<
base
<
T
>>
{
static
void
init
(
const
base
<
T
>
&
,
type_record
*
r
)
{
r
->
add_base
(
typeid
(
T
),
nullptr
);
}
};
/// Process a multiple inheritance attribute
template
<
>
struct
process_attribute
<
multiple_inheritance
>
:
process_attribute_default
<
multiple_inheritance
>
{
static
void
init
(
const
multiple_inheritance
&
,
type_record
*
r
)
{
r
->
multiple_inheritance
=
true
;
}
};
template
<
>
struct
process_attribute
<
dynamic_attr
>
:
process_attribute_default
<
dynamic_attr
>
{
static
void
init
(
const
dynamic_attr
&
,
type_record
*
r
)
{
r
->
dynamic_attr
=
true
;
}
};
template
<
>
struct
process_attribute
<
buffer_protocol
>
:
process_attribute_default
<
buffer_protocol
>
{
static
void
init
(
const
buffer_protocol
&
,
type_record
*
r
)
{
r
->
buffer_protocol
=
true
;
}
};
template
<
>
struct
process_attribute
<
metaclass
>
:
process_attribute_default
<
metaclass
>
{
static
void
init
(
const
metaclass
&
m
,
type_record
*
r
)
{
r
->
metaclass
=
m
.
value
;
}
};
/// Process an 'arithmetic' attribute for enums (does nothing here)
template
<
>
struct
process_attribute
<
arithmetic
>
:
process_attribute_default
<
arithmetic
>
{};
template
<
typename
...
Ts
>
struct
process_attribute
<
call_guard
<
Ts
...
>>
:
process_attribute_default
<
call_guard
<
Ts
...
>>
{
};
/**
* Process a keep_alive call policy -- invokes keep_alive_impl during the
* pre-call handler if both Nurse, Patient != 0 and use the post-call handler
* otherwise
*/
template
<
size_t
Nurse
,
size_t
Patient
>
struct
process_attribute
<
keep_alive
<
Nurse
,
Patient
>>
:
public
process_attribute_default
<
keep_alive
<
Nurse
,
Patient
>>
{
template
<
size_t
N
=
Nurse
,
size_t
P
=
Patient
,
enable_if_t
<
N
!=
0
&&
P
!=
0
,
int
>
=
0
>
static
void
precall
(
function_call
&
call
)
{
keep_alive_impl
(
Nurse
,
Patient
,
call
,
handle
());
}
template
<
size_t
N
=
Nurse
,
size_t
P
=
Patient
,
enable_if_t
<
N
!=
0
&&
P
!=
0
,
int
>
=
0
>
static
void
postcall
(
function_call
&
,
handle
)
{
}
template
<
size_t
N
=
Nurse
,
size_t
P
=
Patient
,
enable_if_t
<
N
==
0
||
P
==
0
,
int
>
=
0
>
static
void
precall
(
function_call
&
)
{
}
template
<
size_t
N
=
Nurse
,
size_t
P
=
Patient
,
enable_if_t
<
N
==
0
||
P
==
0
,
int
>
=
0
>
static
void
postcall
(
function_call
&
call
,
handle
ret
)
{
keep_alive_impl
(
Nurse
,
Patient
,
call
,
ret
);
}
};
/// Recursively iterate over variadic template arguments
template
<
typename
...
Args
>
struct
process_attributes
{
static
void
init
(
const
Args
&
...
args
,
function_record
*
r
)
{
int
unused
[]
=
{
0
,
(
process_attribute
<
typename
std
::
decay
<
Args
>::
type
>::
init
(
args
,
r
),
0
)
...
};
ignore_unused
(
unused
);
}
static
void
init
(
const
Args
&
...
args
,
type_record
*
r
)
{
int
unused
[]
=
{
0
,
(
process_attribute
<
typename
std
::
decay
<
Args
>::
type
>::
init
(
args
,
r
),
0
)
...
};
ignore_unused
(
unused
);
}
static
void
precall
(
function_call
&
call
)
{
int
unused
[]
=
{
0
,
(
process_attribute
<
typename
std
::
decay
<
Args
>::
type
>::
precall
(
call
),
0
)
...
};
ignore_unused
(
unused
);
}
static
void
postcall
(
function_call
&
call
,
handle
fn_ret
)
{
int
unused
[]
=
{
0
,
(
process_attribute
<
typename
std
::
decay
<
Args
>::
type
>::
postcall
(
call
,
fn_ret
),
0
)
...
};
ignore_unused
(
unused
);
}
};
template
<
typename
T
>
using
is_call_guard
=
is_instantiation
<
call_guard
,
T
>
;
/// Extract the ``type`` from the first `call_guard` in `Extras...` (or `void_type` if none found)
template
<
typename
...
Extra
>
using
extract_guard_t
=
typename
exactly_one_t
<
is_call_guard
,
call_guard
<>
,
Extra
...
>::
type
;
/// Check the number of named arguments at compile time
template
<
typename
...
Extra
,
size_t
named
=
constexpr_sum
(
std
::
is_base_of
<
arg
,
Extra
>
::
value
...),
size_t
self
=
constexpr_sum
(
std
::
is_same
<
is_method
,
Extra
>::
value
...)
>
constexpr
bool
expected_num_args
(
size_t
nargs
,
bool
has_args
,
bool
has_kwargs
)
{
return
named
==
0
||
(
self
+
named
+
has_args
+
has_kwargs
)
==
nargs
;
}
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
pybind11
)
ppocr/postprocess/lanms/include/pybind11/buffer_info.h
0 → 100644
View file @
2814d997
/*
pybind11/buffer_info.h: Python buffer object interface
Copyright (c) 2016 Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#pragma once
#include "common.h"
NAMESPACE_BEGIN
(
pybind11
)
/// Information record describing a Python buffer object
struct
buffer_info
{
void
*
ptr
=
nullptr
;
// Pointer to the underlying storage
ssize_t
itemsize
=
0
;
// Size of individual items in bytes
ssize_t
size
=
0
;
// Total number of entries
std
::
string
format
;
// For homogeneous buffers, this should be set to format_descriptor<T>::format()
ssize_t
ndim
=
0
;
// Number of dimensions
std
::
vector
<
ssize_t
>
shape
;
// Shape of the tensor (1 entry per dimension)
std
::
vector
<
ssize_t
>
strides
;
// Number of entries between adjacent entries (for each per dimension)
buffer_info
()
{
}
buffer_info
(
void
*
ptr
,
ssize_t
itemsize
,
const
std
::
string
&
format
,
ssize_t
ndim
,
detail
::
any_container
<
ssize_t
>
shape_in
,
detail
::
any_container
<
ssize_t
>
strides_in
)
:
ptr
(
ptr
),
itemsize
(
itemsize
),
size
(
1
),
format
(
format
),
ndim
(
ndim
),
shape
(
std
::
move
(
shape_in
)),
strides
(
std
::
move
(
strides_in
))
{
if
(
ndim
!=
(
ssize_t
)
shape
.
size
()
||
ndim
!=
(
ssize_t
)
strides
.
size
())
pybind11_fail
(
"buffer_info: ndim doesn't match shape and/or strides length"
);
for
(
size_t
i
=
0
;
i
<
(
size_t
)
ndim
;
++
i
)
size
*=
shape
[
i
];
}
template
<
typename
T
>
buffer_info
(
T
*
ptr
,
detail
::
any_container
<
ssize_t
>
shape_in
,
detail
::
any_container
<
ssize_t
>
strides_in
)
:
buffer_info
(
private_ctr_tag
(),
ptr
,
sizeof
(
T
),
format_descriptor
<
T
>::
format
(),
static_cast
<
ssize_t
>
(
shape_in
->
size
()),
std
::
move
(
shape_in
),
std
::
move
(
strides_in
))
{
}
buffer_info
(
void
*
ptr
,
ssize_t
itemsize
,
const
std
::
string
&
format
,
ssize_t
size
)
:
buffer_info
(
ptr
,
itemsize
,
format
,
1
,
{
size
},
{
itemsize
})
{
}
template
<
typename
T
>
buffer_info
(
T
*
ptr
,
ssize_t
size
)
:
buffer_info
(
ptr
,
sizeof
(
T
),
format_descriptor
<
T
>::
format
(),
size
)
{
}
explicit
buffer_info
(
Py_buffer
*
view
,
bool
ownview
=
true
)
:
buffer_info
(
view
->
buf
,
view
->
itemsize
,
view
->
format
,
view
->
ndim
,
{
view
->
shape
,
view
->
shape
+
view
->
ndim
},
{
view
->
strides
,
view
->
strides
+
view
->
ndim
})
{
this
->
view
=
view
;
this
->
ownview
=
ownview
;
}
buffer_info
(
const
buffer_info
&
)
=
delete
;
buffer_info
&
operator
=
(
const
buffer_info
&
)
=
delete
;
buffer_info
(
buffer_info
&&
other
)
{
(
*
this
)
=
std
::
move
(
other
);
}
buffer_info
&
operator
=
(
buffer_info
&&
rhs
)
{
ptr
=
rhs
.
ptr
;
itemsize
=
rhs
.
itemsize
;
size
=
rhs
.
size
;
format
=
std
::
move
(
rhs
.
format
);
ndim
=
rhs
.
ndim
;
shape
=
std
::
move
(
rhs
.
shape
);
strides
=
std
::
move
(
rhs
.
strides
);
std
::
swap
(
view
,
rhs
.
view
);
std
::
swap
(
ownview
,
rhs
.
ownview
);
return
*
this
;
}
~
buffer_info
()
{
if
(
view
&&
ownview
)
{
PyBuffer_Release
(
view
);
delete
view
;
}
}
private:
struct
private_ctr_tag
{
};
buffer_info
(
private_ctr_tag
,
void
*
ptr
,
ssize_t
itemsize
,
const
std
::
string
&
format
,
ssize_t
ndim
,
detail
::
any_container
<
ssize_t
>
&&
shape_in
,
detail
::
any_container
<
ssize_t
>
&&
strides_in
)
:
buffer_info
(
ptr
,
itemsize
,
format
,
ndim
,
std
::
move
(
shape_in
),
std
::
move
(
strides_in
))
{
}
Py_buffer
*
view
=
nullptr
;
bool
ownview
=
false
;
};
NAMESPACE_BEGIN
(
detail
)
template
<
typename
T
,
typename
SFINAE
=
void
>
struct
compare_buffer_info
{
static
bool
compare
(
const
buffer_info
&
b
)
{
return
b
.
format
==
format_descriptor
<
T
>::
format
()
&&
b
.
itemsize
==
(
ssize_t
)
sizeof
(
T
);
}
};
template
<
typename
T
>
struct
compare_buffer_info
<
T
,
detail
::
enable_if_t
<
std
::
is_integral
<
T
>::
value
>>
{
static
bool
compare
(
const
buffer_info
&
b
)
{
return
(
size_t
)
b
.
itemsize
==
sizeof
(
T
)
&&
(
b
.
format
==
format_descriptor
<
T
>::
value
||
((
sizeof
(
T
)
==
sizeof
(
long
))
&&
b
.
format
==
(
std
::
is_unsigned
<
T
>::
value
?
"L"
:
"l"
))
||
((
sizeof
(
T
)
==
sizeof
(
size_t
))
&&
b
.
format
==
(
std
::
is_unsigned
<
T
>::
value
?
"N"
:
"n"
)));
}
};
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
pybind11
)
ppocr/postprocess/lanms/include/pybind11/cast.h
0 → 100644
View file @
2814d997
This diff is collapsed.
Click to expand it.
ppocr/postprocess/lanms/include/pybind11/chrono.h
0 → 100644
View file @
2814d997
/*
pybind11/chrono.h: Transparent conversion between std::chrono and python's datetime
Copyright (c) 2016 Trent Houliston <trent@houliston.me> and
Wenzel Jakob <wenzel.jakob@epfl.ch>
All rights reserved. Use of this source code is governed by a
BSD-style license that can be found in the LICENSE file.
*/
#pragma once
#include "pybind11.h"
#include <cmath>
#include <ctime>
#include <chrono>
#include <datetime.h>
// Backport the PyDateTime_DELTA functions from Python3.3 if required
#ifndef PyDateTime_DELTA_GET_DAYS
#define PyDateTime_DELTA_GET_DAYS(o) (((PyDateTime_Delta*)o)->days)
#endif
#ifndef PyDateTime_DELTA_GET_SECONDS
#define PyDateTime_DELTA_GET_SECONDS(o) (((PyDateTime_Delta*)o)->seconds)
#endif
#ifndef PyDateTime_DELTA_GET_MICROSECONDS
#define PyDateTime_DELTA_GET_MICROSECONDS(o) (((PyDateTime_Delta*)o)->microseconds)
#endif
NAMESPACE_BEGIN
(
pybind11
)
NAMESPACE_BEGIN
(
detail
)
template
<
typename
type
>
class
duration_caster
{
public:
typedef
typename
type
::
rep
rep
;
typedef
typename
type
::
period
period
;
typedef
std
::
chrono
::
duration
<
uint_fast32_t
,
std
::
ratio
<
86400
>>
days
;
bool
load
(
handle
src
,
bool
)
{
using
namespace
std
::
chrono
;
// Lazy initialise the PyDateTime import
if
(
!
PyDateTimeAPI
)
{
PyDateTime_IMPORT
;
}
if
(
!
src
)
return
false
;
// If invoked with datetime.delta object
if
(
PyDelta_Check
(
src
.
ptr
()))
{
value
=
type
(
duration_cast
<
duration
<
rep
,
period
>>
(
days
(
PyDateTime_DELTA_GET_DAYS
(
src
.
ptr
()))
+
seconds
(
PyDateTime_DELTA_GET_SECONDS
(
src
.
ptr
()))
+
microseconds
(
PyDateTime_DELTA_GET_MICROSECONDS
(
src
.
ptr
()))));
return
true
;
}
// If invoked with a float we assume it is seconds and convert
else
if
(
PyFloat_Check
(
src
.
ptr
()))
{
value
=
type
(
duration_cast
<
duration
<
rep
,
period
>>
(
duration
<
double
>
(
PyFloat_AsDouble
(
src
.
ptr
()))));
return
true
;
}
else
return
false
;
}
// If this is a duration just return it back
static
const
std
::
chrono
::
duration
<
rep
,
period
>&
get_duration
(
const
std
::
chrono
::
duration
<
rep
,
period
>
&
src
)
{
return
src
;
}
// If this is a time_point get the time_since_epoch
template
<
typename
Clock
>
static
std
::
chrono
::
duration
<
rep
,
period
>
get_duration
(
const
std
::
chrono
::
time_point
<
Clock
,
std
::
chrono
::
duration
<
rep
,
period
>>
&
src
)
{
return
src
.
time_since_epoch
();
}
static
handle
cast
(
const
type
&
src
,
return_value_policy
/* policy */
,
handle
/* parent */
)
{
using
namespace
std
::
chrono
;
// Use overloaded function to get our duration from our source
// Works out if it is a duration or time_point and get the duration
auto
d
=
get_duration
(
src
);
// Lazy initialise the PyDateTime import
if
(
!
PyDateTimeAPI
)
{
PyDateTime_IMPORT
;
}
// Declare these special duration types so the conversions happen with the correct primitive types (int)
using
dd_t
=
duration
<
int
,
std
::
ratio
<
86400
>>
;
using
ss_t
=
duration
<
int
,
std
::
ratio
<
1
>>
;
using
us_t
=
duration
<
int
,
std
::
micro
>
;
auto
dd
=
duration_cast
<
dd_t
>
(
d
);
auto
subd
=
d
-
dd
;
auto
ss
=
duration_cast
<
ss_t
>
(
subd
);
auto
us
=
duration_cast
<
us_t
>
(
subd
-
ss
);
return
PyDelta_FromDSU
(
dd
.
count
(),
ss
.
count
(),
us
.
count
());
}
PYBIND11_TYPE_CASTER
(
type
,
_
(
"datetime.timedelta"
));
};
// This is for casting times on the system clock into datetime.datetime instances
template
<
typename
Duration
>
class
type_caster
<
std
::
chrono
::
time_point
<
std
::
chrono
::
system_clock
,
Duration
>>
{
public:
typedef
std
::
chrono
::
time_point
<
std
::
chrono
::
system_clock
,
Duration
>
type
;
bool
load
(
handle
src
,
bool
)
{
using
namespace
std
::
chrono
;
// Lazy initialise the PyDateTime import
if
(
!
PyDateTimeAPI
)
{
PyDateTime_IMPORT
;
}
if
(
!
src
)
return
false
;
if
(
PyDateTime_Check
(
src
.
ptr
()))
{
std
::
tm
cal
;
cal
.
tm_sec
=
PyDateTime_DATE_GET_SECOND
(
src
.
ptr
());
cal
.
tm_min
=
PyDateTime_DATE_GET_MINUTE
(
src
.
ptr
());
cal
.
tm_hour
=
PyDateTime_DATE_GET_HOUR
(
src
.
ptr
());
cal
.
tm_mday
=
PyDateTime_GET_DAY
(
src
.
ptr
());
cal
.
tm_mon
=
PyDateTime_GET_MONTH
(
src
.
ptr
())
-
1
;
cal
.
tm_year
=
PyDateTime_GET_YEAR
(
src
.
ptr
())
-
1900
;
cal
.
tm_isdst
=
-
1
;
value
=
system_clock
::
from_time_t
(
std
::
mktime
(
&
cal
))
+
microseconds
(
PyDateTime_DATE_GET_MICROSECOND
(
src
.
ptr
()));
return
true
;
}
else
return
false
;
}
static
handle
cast
(
const
std
::
chrono
::
time_point
<
std
::
chrono
::
system_clock
,
Duration
>
&
src
,
return_value_policy
/* policy */
,
handle
/* parent */
)
{
using
namespace
std
::
chrono
;
// Lazy initialise the PyDateTime import
if
(
!
PyDateTimeAPI
)
{
PyDateTime_IMPORT
;
}
std
::
time_t
tt
=
system_clock
::
to_time_t
(
src
);
// this function uses static memory so it's best to copy it out asap just in case
// otherwise other code that is using localtime may break this (not just python code)
std
::
tm
localtime
=
*
std
::
localtime
(
&
tt
);
// Declare these special duration types so the conversions happen with the correct primitive types (int)
using
us_t
=
duration
<
int
,
std
::
micro
>
;
return
PyDateTime_FromDateAndTime
(
localtime
.
tm_year
+
1900
,
localtime
.
tm_mon
+
1
,
localtime
.
tm_mday
,
localtime
.
tm_hour
,
localtime
.
tm_min
,
localtime
.
tm_sec
,
(
duration_cast
<
us_t
>
(
src
.
time_since_epoch
()
%
seconds
(
1
))).
count
());
}
PYBIND11_TYPE_CASTER
(
type
,
_
(
"datetime.datetime"
));
};
// Other clocks that are not the system clock are not measured as datetime.datetime objects
// since they are not measured on calendar time. So instead we just make them timedeltas
// Or if they have passed us a time as a float we convert that
template
<
typename
Clock
,
typename
Duration
>
class
type_caster
<
std
::
chrono
::
time_point
<
Clock
,
Duration
>>
:
public
duration_caster
<
std
::
chrono
::
time_point
<
Clock
,
Duration
>>
{
};
template
<
typename
Rep
,
typename
Period
>
class
type_caster
<
std
::
chrono
::
duration
<
Rep
,
Period
>>
:
public
duration_caster
<
std
::
chrono
::
duration
<
Rep
,
Period
>>
{
};
NAMESPACE_END
(
detail
)
NAMESPACE_END
(
pybind11
)
ppocr/postprocess/lanms/include/pybind11/class_support.h
0 → 100644
View file @
2814d997
This diff is collapsed.
Click to expand it.
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment