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
ffecf106
Commit
ffecf106
authored
Jul 14, 2020
by
lvxiangxiang
Browse files
ios ocr demo
parent
199fd0e0
Changes
27
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
5805 additions
and
0 deletions
+5805
-0
deploy/ios_demo/ocr_demo/pdocr/ocr_clipper.cpp
deploy/ios_demo/ocr_demo/pdocr/ocr_clipper.cpp
+4629
-0
deploy/ios_demo/ocr_demo/pdocr/ocr_clipper.hpp
deploy/ios_demo/ocr_demo/pdocr/ocr_clipper.hpp
+547
-0
deploy/ios_demo/ocr_demo/pdocr/ocr_crnn_process.cpp
deploy/ios_demo/ocr_demo/pdocr/ocr_crnn_process.cpp
+141
-0
deploy/ios_demo/ocr_demo/pdocr/ocr_crnn_process.h
deploy/ios_demo/ocr_demo/pdocr/ocr_crnn_process.h
+19
-0
deploy/ios_demo/ocr_demo/pdocr/ocr_db_post_process.cpp
deploy/ios_demo/ocr_demo/pdocr/ocr_db_post_process.cpp
+372
-0
deploy/ios_demo/ocr_demo/pdocr/ocr_db_post_process.h
deploy/ios_demo/ocr_demo/pdocr/ocr_db_post_process.h
+10
-0
deploy/ios_demo/ocr_demo/timer.h
deploy/ios_demo/ocr_demo/timer.h
+87
-0
No files found.
deploy/ios_demo/ocr_demo/pdocr/ocr_clipper.cpp
0 → 100644
View file @
ffecf106
This diff is collapsed.
Click to expand it.
deploy/ios_demo/ocr_demo/pdocr/ocr_clipper.hpp
0 → 100644
View file @
ffecf106
/*******************************************************************************
* *
* Author : Angus Johnson *
* Version : 6.4.2 *
* Date : 27 February 2017 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2017 *
* *
* 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.4.2"
//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:
//PolyNode& operator =(PolyNode& other);
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:
//PolyTree& operator =(PolyTree& other);
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
deploy/ios_demo/ocr_demo/pdocr/ocr_crnn_process.cpp
0 → 100644
View file @
ffecf106
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "ocr_crnn_process.h"
#include <iostream>
#include <vector>
#include <iostream>
#include <cstring>
#include <fstream>
#include <cmath>
const
std
::
string
CHARACTER_TYPE
=
"ch"
;
const
int
MAX_DICT_LENGTH
=
6624
;
const
std
::
vector
<
int
>
REC_IMAGE_SHAPE
=
{
3
,
32
,
320
};
static
cv
::
Mat
crnn_resize_norm_img
(
cv
::
Mat
img
,
float
wh_ratio
)
{
int
imgC
,
imgH
,
imgW
;
imgC
=
REC_IMAGE_SHAPE
[
0
];
imgW
=
REC_IMAGE_SHAPE
[
2
];
imgH
=
REC_IMAGE_SHAPE
[
1
];
if
(
CHARACTER_TYPE
==
"ch"
)
imgW
=
int
(
32
*
wh_ratio
);
float
ratio
=
float
(
img
.
cols
)
/
float
(
img
.
rows
);
int
resize_w
,
resize_h
;
if
(
ceilf
(
imgH
*
ratio
)
>
imgW
)
resize_w
=
imgW
;
else
resize_w
=
int
(
ceilf
(
imgH
*
ratio
));
cv
::
Mat
resize_img
;
cv
::
resize
(
img
,
resize_img
,
cv
::
Size
(
resize_w
,
imgH
),
0.
f
,
0.
f
,
cv
::
INTER_CUBIC
);
resize_img
.
convertTo
(
resize_img
,
CV_32FC3
,
1
/
255.
f
);
for
(
int
h
=
0
;
h
<
resize_img
.
rows
;
h
++
)
{
for
(
int
w
=
0
;
w
<
resize_img
.
cols
;
w
++
)
{
resize_img
.
at
<
cv
::
Vec3f
>
(
h
,
w
)[
0
]
=
(
resize_img
.
at
<
cv
::
Vec3f
>
(
h
,
w
)[
0
]
-
0.5
)
*
2
;
resize_img
.
at
<
cv
::
Vec3f
>
(
h
,
w
)[
1
]
=
(
resize_img
.
at
<
cv
::
Vec3f
>
(
h
,
w
)[
1
]
-
0.5
)
*
2
;
resize_img
.
at
<
cv
::
Vec3f
>
(
h
,
w
)[
2
]
=
(
resize_img
.
at
<
cv
::
Vec3f
>
(
h
,
w
)[
2
]
-
0.5
)
*
2
;
}
}
cv
::
Mat
dist
;
cv
::
copyMakeBorder
(
resize_img
,
dist
,
0
,
0
,
0
,
int
(
imgW
-
resize_w
),
cv
::
BORDER_CONSTANT
,
{
0
,
0
,
0
});
return
dist
;
}
cv
::
Mat
crnn_resize_img
(
const
cv
::
Mat
&
img
,
float
wh_ratio
)
{
int
imgC
=
REC_IMAGE_SHAPE
[
0
];
int
imgW
=
REC_IMAGE_SHAPE
[
2
];
int
imgH
=
REC_IMAGE_SHAPE
[
1
];
if
(
CHARACTER_TYPE
==
"ch"
)
{
imgW
=
int
(
32
*
wh_ratio
);
}
float
ratio
=
float
(
img
.
cols
)
/
float
(
img
.
rows
);
int
resize_w
;
if
(
ceilf
(
imgH
*
ratio
)
>
imgW
)
resize_w
=
imgW
;
else
resize_w
=
int
(
ceilf
(
imgH
*
ratio
));
cv
::
Mat
resize_img
;
cv
::
resize
(
img
,
resize_img
,
cv
::
Size
(
resize_w
,
imgH
));
return
resize_img
;
}
cv
::
Mat
get_rotate_crop_image
(
const
cv
::
Mat
&
srcimage
,
const
std
::
vector
<
std
::
vector
<
int
>>
&
box
)
{
std
::
vector
<
std
::
vector
<
int
>>
points
=
box
;
int
x_collect
[
4
]
=
{
box
[
0
][
0
],
box
[
1
][
0
],
box
[
2
][
0
],
box
[
3
][
0
]};
int
y_collect
[
4
]
=
{
box
[
0
][
1
],
box
[
1
][
1
],
box
[
2
][
1
],
box
[
3
][
1
]};
int
left
=
int
(
*
std
::
min_element
(
x_collect
,
x_collect
+
4
));
int
right
=
int
(
*
std
::
max_element
(
x_collect
,
x_collect
+
4
));
int
top
=
int
(
*
std
::
min_element
(
y_collect
,
y_collect
+
4
));
int
bottom
=
int
(
*
std
::
max_element
(
y_collect
,
y_collect
+
4
));
cv
::
Mat
img_crop
;
srcimage
(
cv
::
Rect
(
left
,
top
,
right
-
left
,
bottom
-
top
)).
copyTo
(
img_crop
);
for
(
int
i
=
0
;
i
<
points
.
size
();
i
++
)
{
points
[
i
][
0
]
-=
left
;
points
[
i
][
1
]
-=
top
;
}
int
img_crop_width
=
int
(
sqrt
(
pow
(
points
[
0
][
0
]
-
points
[
1
][
0
],
2
)
+
pow
(
points
[
0
][
1
]
-
points
[
1
][
1
],
2
)));
int
img_crop_height
=
int
(
sqrt
(
pow
(
points
[
0
][
0
]
-
points
[
3
][
0
],
2
)
+
pow
(
points
[
0
][
1
]
-
points
[
3
][
1
],
2
)));
cv
::
Point2f
pts_std
[
4
];
pts_std
[
0
]
=
cv
::
Point2f
(
0.
,
0.
);
pts_std
[
1
]
=
cv
::
Point2f
(
img_crop_width
,
0.
);
pts_std
[
2
]
=
cv
::
Point2f
(
img_crop_width
,
img_crop_height
);
pts_std
[
3
]
=
cv
::
Point2f
(
0.
f
,
img_crop_height
);
cv
::
Point2f
pointsf
[
4
];
pointsf
[
0
]
=
cv
::
Point2f
(
points
[
0
][
0
],
points
[
0
][
1
]);
pointsf
[
1
]
=
cv
::
Point2f
(
points
[
1
][
0
],
points
[
1
][
1
]);
pointsf
[
2
]
=
cv
::
Point2f
(
points
[
2
][
0
],
points
[
2
][
1
]);
pointsf
[
3
]
=
cv
::
Point2f
(
points
[
3
][
0
],
points
[
3
][
1
]);
cv
::
Mat
M
=
cv
::
getPerspectiveTransform
(
pointsf
,
pts_std
);
cv
::
Mat
dst_img
;
cv
::
warpPerspective
(
img_crop
,
dst_img
,
M
,
cv
::
Size
(
img_crop_width
,
img_crop_height
),
cv
::
BORDER_REPLICATE
);
if
(
float
(
dst_img
.
rows
)
>=
float
(
dst_img
.
cols
)
*
1.5
)
{
/*
cv::Mat srcCopy = cv::Mat(dst_img.rows, dst_img.cols, dst_img.depth());
cv::transpose(dst_img, srcCopy);
cv::flip(srcCopy, srcCopy, 0);
return srcCopy;
*/
cv
::
transpose
(
dst_img
,
dst_img
);
cv
::
flip
(
dst_img
,
dst_img
,
0
);
return
dst_img
;
}
else
{
return
dst_img
;
}
}
deploy/ios_demo/ocr_demo/pdocr/ocr_crnn_process.h
0 → 100644
View file @
ffecf106
//
// Created by fujiayi on 2020/7/3.
//
#pragma once
#include <vector>
#include <opencv2/opencv.hpp>
extern
const
std
::
vector
<
int
>
REC_IMAGE_SHAPE
;
cv
::
Mat
get_rotate_crop_image
(
const
cv
::
Mat
&
srcimage
,
const
std
::
vector
<
std
::
vector
<
int
>>&
box
);
cv
::
Mat
crnn_resize_img
(
const
cv
::
Mat
&
img
,
float
wh_ratio
);
template
<
class
ForwardIterator
>
inline
size_t
argmax
(
ForwardIterator
first
,
ForwardIterator
last
)
{
return
std
::
distance
(
first
,
std
::
max_element
(
first
,
last
));
}
\ No newline at end of file
deploy/ios_demo/ocr_demo/pdocr/ocr_db_post_process.cpp
0 → 100644
View file @
ffecf106
// Copyright (c) 2020 PaddlePaddle Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include <iostream>
#include <vector>
#include <math.h>
#include "opencv2/core.hpp"
#include "opencv2/imgcodecs.hpp"
#include "opencv2/imgproc.hpp"
#include "ocr_clipper.hpp"
static
void
getcontourarea
(
float
**
box
,
float
unclip_ratio
,
float
&
distance
)
{
int
pts_num
=
4
;
float
area
=
0.0
f
;
float
dist
=
0.0
f
;
for
(
int
i
=
0
;
i
<
pts_num
;
i
++
)
{
area
+=
box
[
i
][
0
]
*
box
[(
i
+
1
)
%
pts_num
][
1
]
-
box
[
i
][
1
]
*
box
[(
i
+
1
)
%
pts_num
][
0
];
dist
+=
sqrtf
(
(
box
[
i
][
0
]
-
box
[(
i
+
1
)
%
pts_num
][
0
])
*
(
box
[
i
][
0
]
-
box
[(
i
+
1
)
%
pts_num
][
0
])
+
(
box
[
i
][
1
]
-
box
[(
i
+
1
)
%
pts_num
][
1
])
*
(
box
[
i
][
1
]
-
box
[(
i
+
1
)
%
pts_num
][
1
]));
}
area
=
fabs
(
float
(
area
/
2.0
));
distance
=
area
*
unclip_ratio
/
dist
;
}
static
cv
::
RotatedRect
unclip
(
float
**
box
)
{
float
unclip_ratio
=
2.0
;
float
distance
=
1.0
;
getcontourarea
(
box
,
unclip_ratio
,
distance
);
ClipperLib
::
ClipperOffset
offset
;
ClipperLib
::
Path
p
;
p
<<
ClipperLib
::
IntPoint
(
int
(
box
[
0
][
0
]),
int
(
box
[
0
][
1
]))
<<
ClipperLib
::
IntPoint
(
int
(
box
[
1
][
0
]),
int
(
box
[
1
][
1
]))
<<
ClipperLib
::
IntPoint
(
int
(
box
[
2
][
0
]),
int
(
box
[
2
][
1
]))
<<
ClipperLib
::
IntPoint
(
int
(
box
[
3
][
0
]),
int
(
box
[
3
][
1
]));
offset
.
AddPath
(
p
,
ClipperLib
::
jtRound
,
ClipperLib
::
etClosedPolygon
);
ClipperLib
::
Paths
soln
;
offset
.
Execute
(
soln
,
distance
);
std
::
vector
<
cv
::
Point2f
>
points
;
for
(
int
j
=
0
;
j
<
soln
.
size
();
j
++
)
{
for
(
int
i
=
0
;
i
<
soln
[
soln
.
size
()
-
1
].
size
();
i
++
)
{
points
.
emplace_back
(
soln
[
j
][
i
].
X
,
soln
[
j
][
i
].
Y
);
}
}
cv
::
RotatedRect
res
=
cv
::
minAreaRect
(
points
);
return
res
;
}
static
float
**
Mat2Vec
(
cv
::
Mat
mat
)
{
auto
**
array
=
new
float
*
[
mat
.
rows
];
for
(
int
i
=
0
;
i
<
mat
.
rows
;
++
i
)
array
[
i
]
=
new
float
[
mat
.
cols
];
for
(
int
i
=
0
;
i
<
mat
.
rows
;
++
i
)
{
for
(
int
j
=
0
;
j
<
mat
.
cols
;
++
j
)
{
array
[
i
][
j
]
=
mat
.
at
<
float
>
(
i
,
j
);
}
}
return
array
;
}
static
void
quickSort
(
float
**
s
,
int
l
,
int
r
)
{
if
(
l
<
r
)
{
int
i
=
l
,
j
=
r
;
float
x
=
s
[
l
][
0
];
float
*
xp
=
s
[
l
];
while
(
i
<
j
)
{
while
(
i
<
j
&&
s
[
j
][
0
]
>=
x
)
j
--
;
if
(
i
<
j
)
std
::
swap
(
s
[
i
++
],
s
[
j
]);
while
(
i
<
j
&&
s
[
i
][
0
]
<
x
)
i
++
;
if
(
i
<
j
)
std
::
swap
(
s
[
j
--
],
s
[
i
]);
}
s
[
i
]
=
xp
;
quickSort
(
s
,
l
,
i
-
1
);
quickSort
(
s
,
i
+
1
,
r
);
}
}
static
void
quickSort_vector
(
std
::
vector
<
std
::
vector
<
int
>>
&
box
,
int
l
,
int
r
,
int
axis
)
{
if
(
l
<
r
)
{
int
i
=
l
,
j
=
r
;
int
x
=
box
[
l
][
axis
];
std
::
vector
<
int
>
xp
(
box
[
l
]);
while
(
i
<
j
)
{
while
(
i
<
j
&&
box
[
j
][
axis
]
>=
x
)
j
--
;
if
(
i
<
j
)
std
::
swap
(
box
[
i
++
],
box
[
j
]);
while
(
i
<
j
&&
box
[
i
][
axis
]
<
x
)
i
++
;
if
(
i
<
j
)
std
::
swap
(
box
[
j
--
],
box
[
i
]);
}
box
[
i
]
=
xp
;
quickSort_vector
(
box
,
l
,
i
-
1
,
axis
);
quickSort_vector
(
box
,
i
+
1
,
r
,
axis
);
}
}
static
std
::
vector
<
std
::
vector
<
int
>>
order_points_clockwise
(
std
::
vector
<
std
::
vector
<
int
>>
pts
)
{
std
::
vector
<
std
::
vector
<
int
>>
box
=
pts
;
quickSort_vector
(
box
,
0
,
int
(
box
.
size
()
-
1
),
0
);
std
::
vector
<
std
::
vector
<
int
>>
leftmost
=
{
box
[
0
],
box
[
1
]};
std
::
vector
<
std
::
vector
<
int
>>
rightmost
=
{
box
[
2
],
box
[
3
]};
if
(
leftmost
[
0
][
1
]
>
leftmost
[
1
][
1
])
std
::
swap
(
leftmost
[
0
],
leftmost
[
1
]);
if
(
rightmost
[
0
][
1
]
>
rightmost
[
1
][
1
])
std
::
swap
(
rightmost
[
0
],
rightmost
[
1
]);
std
::
vector
<
std
::
vector
<
int
>>
rect
=
{
leftmost
[
0
],
rightmost
[
0
],
rightmost
[
1
],
leftmost
[
1
]};
return
rect
;
}
static
float
**
get_mini_boxes
(
cv
::
RotatedRect
box
,
float
&
ssid
)
{
ssid
=
box
.
size
.
width
>=
box
.
size
.
height
?
box
.
size
.
height
:
box
.
size
.
width
;
cv
::
Mat
points
;
cv
::
boxPoints
(
box
,
points
);
// sorted box points
auto
array
=
Mat2Vec
(
points
);
quickSort
(
array
,
0
,
3
);
float
*
idx1
=
array
[
0
],
*
idx2
=
array
[
1
],
*
idx3
=
array
[
2
],
*
idx4
=
array
[
3
];
if
(
array
[
3
][
1
]
<=
array
[
2
][
1
])
{
idx2
=
array
[
3
];
idx3
=
array
[
2
];
}
else
{
idx2
=
array
[
2
];
idx3
=
array
[
3
];
}
if
(
array
[
1
][
1
]
<=
array
[
0
][
1
])
{
idx1
=
array
[
1
];
idx4
=
array
[
0
];
}
else
{
idx1
=
array
[
0
];
idx4
=
array
[
1
];
}
array
[
0
]
=
idx1
;
array
[
1
]
=
idx2
;
array
[
2
]
=
idx3
;
array
[
3
]
=
idx4
;
return
array
;
}
template
<
class
T
>
T
clamp
(
T
x
,
T
min
,
T
max
)
{
if
(
x
>
max
){
return
max
;
}
if
(
x
<
min
){
return
min
;
}
return
x
;
}
static
float
clampf
(
float
x
,
float
min
,
float
max
)
{
if
(
x
>
max
)
return
max
;
if
(
x
<
min
)
return
min
;
return
x
;
}
float
box_score_fast
(
float
**
box_array
,
cv
::
Mat
pred
)
{
auto
array
=
box_array
;
int
width
=
pred
.
cols
;
int
height
=
pred
.
rows
;
float
box_x
[
4
]
=
{
array
[
0
][
0
],
array
[
1
][
0
],
array
[
2
][
0
],
array
[
3
][
0
]};
float
box_y
[
4
]
=
{
array
[
0
][
1
],
array
[
1
][
1
],
array
[
2
][
1
],
array
[
3
][
1
]};
int
xmin
=
clamp
(
int
(
std
::
floorf
(
*
(
std
::
min_element
(
box_x
,
box_x
+
4
)))),
0
,
width
-
1
);
int
xmax
=
clamp
(
int
(
std
::
ceilf
(
*
(
std
::
max_element
(
box_x
,
box_x
+
4
)))),
0
,
width
-
1
);
int
ymin
=
clamp
(
int
(
std
::
floorf
(
*
(
std
::
min_element
(
box_y
,
box_y
+
4
)))),
0
,
height
-
1
);
int
ymax
=
clamp
(
int
(
std
::
ceilf
(
*
(
std
::
max_element
(
box_y
,
box_y
+
4
)))),
0
,
height
-
1
);
cv
::
Mat
mask
;
mask
=
cv
::
Mat
::
zeros
(
ymax
-
ymin
+
1
,
xmax
-
xmin
+
1
,
CV_8UC1
);
cv
::
Point
root_point
[
4
];
root_point
[
0
]
=
cv
::
Point
(
int
(
array
[
0
][
0
])
-
xmin
,
int
(
array
[
0
][
1
])
-
ymin
);
root_point
[
1
]
=
cv
::
Point
(
int
(
array
[
1
][
0
])
-
xmin
,
int
(
array
[
1
][
1
])
-
ymin
);
root_point
[
2
]
=
cv
::
Point
(
int
(
array
[
2
][
0
])
-
xmin
,
int
(
array
[
2
][
1
])
-
ymin
);
root_point
[
3
]
=
cv
::
Point
(
int
(
array
[
3
][
0
])
-
xmin
,
int
(
array
[
3
][
1
])
-
ymin
);
const
cv
::
Point
*
ppt
[
1
]
=
{
root_point
};
int
npt
[]
=
{
4
};
cv
::
fillPoly
(
mask
,
ppt
,
npt
,
1
,
cv
::
Scalar
(
1
));
cv
::
Mat
croppedImg
;
pred
(
cv
::
Rect
(
xmin
,
ymin
,
xmax
-
xmin
+
1
,
ymax
-
ymin
+
1
)).
copyTo
(
croppedImg
);
auto
score
=
cv
::
mean
(
croppedImg
,
mask
)[
0
];
return
score
;
}
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>
boxes_from_bitmap
(
const
cv
::
Mat
&
pred
,
const
cv
::
Mat
&
bitmap
)
{
const
int
min_size
=
3
;
const
int
max_candidates
=
1000
;
const
float
box_thresh
=
0.5
;
int
width
=
bitmap
.
cols
;
int
height
=
bitmap
.
rows
;
std
::
vector
<
std
::
vector
<
cv
::
Point
>>
contours
;
std
::
vector
<
cv
::
Vec4i
>
hierarchy
;
cv
::
findContours
(
bitmap
,
contours
,
hierarchy
,
cv
::
RETR_LIST
,
cv
::
CHAIN_APPROX_SIMPLE
);
int
num_contours
=
contours
.
size
()
>=
max_candidates
?
max_candidates
:
contours
.
size
();
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>
boxes
;
for
(
int
_i
=
0
;
_i
<
num_contours
;
_i
++
)
{
float
ssid
;
cv
::
RotatedRect
box
=
cv
::
minAreaRect
(
contours
[
_i
]);
auto
array
=
get_mini_boxes
(
box
,
ssid
);
auto
box_for_unclip
=
array
;
//end get_mini_box
if
(
ssid
<
min_size
)
{
continue
;
}
float
score
;
score
=
box_score_fast
(
array
,
pred
);
//end box_score_fast
if
(
score
<
box_thresh
)
continue
;
// start for unclip
cv
::
RotatedRect
points
=
unclip
(
box_for_unclip
);
// end for unclip
cv
::
RotatedRect
clipbox
=
points
;
auto
cliparray
=
get_mini_boxes
(
clipbox
,
ssid
);
if
(
ssid
<
min_size
+
2
)
continue
;
int
dest_width
=
pred
.
cols
;
int
dest_height
=
pred
.
rows
;
std
::
vector
<
std
::
vector
<
int
>>
intcliparray
;
for
(
int
num_pt
=
0
;
num_pt
<
4
;
num_pt
++
)
{
std
::
vector
<
int
>
a
{
int
(
clampf
(
roundf
(
cliparray
[
num_pt
][
0
]
/
float
(
width
)
*
float
(
dest_width
)),
0
,
float
(
dest_width
))),
int
(
clampf
(
roundf
(
cliparray
[
num_pt
][
1
]
/
float
(
height
)
*
float
(
dest_height
)),
0
,
float
(
dest_height
)))};
intcliparray
.
push_back
(
a
);
}
boxes
.
push_back
(
intcliparray
);
}
//end for
return
boxes
;
}
int
_max
(
int
a
,
int
b
)
{
return
a
>=
b
?
a
:
b
;
}
int
_min
(
int
a
,
int
b
)
{
return
a
>=
b
?
b
:
a
;
}
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>
filter_tag_det_res
(
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>&
o_boxes
,
float
ratio_h
,
float
ratio_w
,
const
cv
::
Mat
&
srcimg
)
{
int
oriimg_h
=
srcimg
.
rows
;
int
oriimg_w
=
srcimg
.
cols
;
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>
boxes
{
o_boxes
};
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>
root_points
;
for
(
int
n
=
0
;
n
<
boxes
.
size
();
n
++
)
{
boxes
[
n
]
=
order_points_clockwise
(
boxes
[
n
]);
for
(
int
m
=
0
;
m
<
boxes
[
0
].
size
();
m
++
)
{
boxes
[
n
][
m
][
0
]
/=
ratio_w
;
boxes
[
n
][
m
][
1
]
/=
ratio_h
;
boxes
[
n
][
m
][
0
]
=
int
(
_min
(
_max
(
boxes
[
n
][
m
][
0
],
0
),
oriimg_w
-
1
));
boxes
[
n
][
m
][
1
]
=
int
(
_min
(
_max
(
boxes
[
n
][
m
][
1
],
0
),
oriimg_h
-
1
));
}
}
for
(
int
n
=
0
;
n
<
boxes
.
size
();
n
++
)
{
int
rect_width
,
rect_height
;
rect_width
=
int
(
sqrt
(
pow
(
boxes
[
n
][
0
][
0
]
-
boxes
[
n
][
1
][
0
],
2
)
+
pow
(
boxes
[
n
][
0
][
1
]
-
boxes
[
n
][
1
][
1
],
2
)));
rect_height
=
int
(
sqrt
(
pow
(
boxes
[
n
][
0
][
0
]
-
boxes
[
n
][
3
][
0
],
2
)
+
pow
(
boxes
[
n
][
0
][
1
]
-
boxes
[
n
][
3
][
1
],
2
)));
if
(
rect_width
<=
10
||
rect_height
<=
10
)
continue
;
root_points
.
push_back
(
boxes
[
n
]);
}
return
root_points
;
}
/*
using namespace std;
// read data from txt file
cv::Mat readtxt2(std::string path, int imgw, int imgh, int imgc) {
std::cout << "read data file from txt file! " << std::endl;
ifstream in(path);
string line;
int count = 0;
int i = 0, j = 0;
std::vector<float> img_mean = {0.485, 0.456, 0.406};
std::vector<float> img_std = {0.229, 0.224, 0.225};
float trainData[imgh][imgw*imgc];
while (getline(in, line)) {
stringstream ss(line);
double x;
while (ss >> x) {
// trainData[i][j] = float(x) * img_std[j % 3] + img_mean[j % 3];
trainData[i][j] = float(x);
j++;
}
i++;
j = 0;
}
cv::Mat pred_map(imgh, imgw*imgc, CV_32FC1, (float *) trainData);
cv::Mat reshape_img = pred_map.reshape(imgc, imgh);
return reshape_img;
}
*/
//using namespace std;
//
//void writetxt(vector<vector<float>> data, std::string save_path){
//
// ofstream fout(save_path);
//
// for (int i = 0; i < data.size(); i++) {
// for (int j=0; j< data[0].size(); j++){
// fout << data[i][j] << " ";
// }
// fout << endl;
// }
// fout << endl;
// fout.close();
//}
deploy/ios_demo/ocr_demo/pdocr/ocr_db_post_process.h
0 → 100644
View file @
ffecf106
//
// Created by fujiayi on 2020/7/2.
//
#pragma once
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>
boxes_from_bitmap
(
const
cv
::
Mat
&
pred
,
const
cv
::
Mat
&
bitmap
);
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>
filter_tag_det_res
(
const
std
::
vector
<
std
::
vector
<
std
::
vector
<
int
>>>&
o_boxes
,
float
ratio_h
,
float
ratio_w
,
const
cv
::
Mat
&
srcimg
);
\ No newline at end of file
deploy/ios_demo/ocr_demo/timer.h
0 → 100644
View file @
ffecf106
//
// timer.h
// face_demo
//
// Created by Li,Xiaoyang(SYS) on 2019/8/20.
// Copyright © 2019年 Li,Xiaoyang(SYS). All rights reserved.
//
#ifndef timer_h
#define timer_h
#include <chrono>
#include <list>
class
Timer
final
{
public:
Timer
()
{}
~
Timer
()
{}
void
clear
()
{
ms_time
.
clear
();
}
void
start
()
{
tstart
=
std
::
chrono
::
system_clock
::
now
();
}
void
end
()
{
tend
=
std
::
chrono
::
system_clock
::
now
();
auto
ts
=
std
::
chrono
::
duration_cast
<
std
::
chrono
::
microseconds
>
(
tend
-
tstart
);
float
elapse_ms
=
1000.
f
*
float
(
ts
.
count
())
*
std
::
chrono
::
microseconds
::
period
::
num
/
\
std
::
chrono
::
microseconds
::
period
::
den
;
ms_time
.
push_back
(
elapse_ms
);
}
float
get_average_ms
()
{
if
(
ms_time
.
size
()
==
0
)
{
return
0.
f
;
}
float
sum
=
0.
f
;
for
(
auto
i
:
ms_time
){
sum
+=
i
;
}
return
sum
/
ms_time
.
size
();
}
float
get_sum_ms
(){
if
(
ms_time
.
size
()
==
0
)
{
return
0.
f
;
}
float
sum
=
0.
f
;
for
(
auto
i
:
ms_time
){
sum
+=
i
;
}
return
sum
;
}
// return tile (0-99) time.
float
get_tile_time
(
float
tile
)
{
if
(
tile
<
0
||
tile
>
100
)
{
return
-
1.
f
;
}
int
total_items
=
(
int
)
ms_time
.
size
();
if
(
total_items
<=
0
)
{
return
-
2.
f
;
}
ms_time
.
sort
();
int
pos
=
(
int
)(
tile
*
total_items
/
100
);
auto
it
=
ms_time
.
begin
();
for
(
int
i
=
0
;
i
<
pos
;
++
i
)
{
++
it
;
}
return
*
it
;
}
const
std
::
list
<
float
>
get_time_stat
()
{
return
ms_time
;
}
private:
std
::
chrono
::
time_point
<
std
::
chrono
::
system_clock
>
tstart
;
std
::
chrono
::
time_point
<
std
::
chrono
::
system_clock
>
tend
;
std
::
list
<
float
>
ms_time
;
};
#endif
/* timer_h */
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