cimo001 commited on
Commit
345568c
·
verified ·
1 Parent(s): d511a43
Files changed (1) hide show
  1. PP-OCRv6_medium_det/src/example.py +162 -0
PP-OCRv6_medium_det/src/example.py ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ sys.dont_write_bytecode = True
3
+
4
+ import cv2
5
+ import numpy
6
+ import pyclipper
7
+
8
+ from helper import onnxSessionBuild
9
+
10
+ pathModel = "./PP-OCRv6_medium_det/"
11
+
12
+ limitSideLength = 960
13
+ limitSideLengthMax = 4000
14
+ binaryThreshold = 0.2
15
+ boxThreshold = 0.45
16
+ unclipRatio = 1.4
17
+ candidateMax = 3000
18
+ sideMinimum = 3
19
+
20
+ meanList = numpy.array([0.485, 0.456, 0.406], dtype=numpy.float32)
21
+ standardList = numpy.array([0.229, 0.224, 0.225], dtype=numpy.float32)
22
+
23
+ onnxSession = onnxSessionBuild(f"{pathModel}onnx/pp-ocrV6_medium_det.onnx")
24
+
25
+ def imageResize(image):
26
+ imageHeight, imageWidth = image.shape[0:2]
27
+
28
+ ratio = 1.0
29
+
30
+ if max(imageHeight, imageWidth) > limitSideLength:
31
+ if imageHeight > imageWidth:
32
+ ratio = float(limitSideLength) / imageHeight
33
+ else:
34
+ ratio = float(limitSideLength) / imageWidth
35
+
36
+ resizeHeight = int(imageHeight * ratio)
37
+ resizeWidth = int(imageWidth * ratio)
38
+
39
+ if max(resizeHeight, resizeWidth) > limitSideLengthMax:
40
+ ratio = float(limitSideLengthMax) / max(resizeHeight, resizeWidth)
41
+
42
+ resizeHeight = int(resizeHeight * ratio)
43
+ resizeWidth = int(resizeWidth * ratio)
44
+
45
+ resizeHeight = max(int(round(resizeHeight / 32) * 32), 32)
46
+ resizeWidth = max(int(round(resizeWidth / 32) * 32), 32)
47
+
48
+ return cv2.resize(image, (resizeWidth, resizeHeight))
49
+
50
+ def boxOrder(contour):
51
+ rectangle = cv2.minAreaRect(contour)
52
+
53
+ pointList = sorted(list(cv2.boxPoints(rectangle)), key=lambda point: point[0])
54
+
55
+ index1 = 0
56
+ index2 = 1
57
+ index3 = 2
58
+ index4 = 3
59
+
60
+ if pointList[1][1] > pointList[0][1]:
61
+ index1 = 0
62
+ index4 = 1
63
+ else:
64
+ index1 = 1
65
+ index4 = 0
66
+
67
+ if pointList[3][1] > pointList[2][1]:
68
+ index2 = 2
69
+ index3 = 3
70
+ else:
71
+ index2 = 3
72
+ index3 = 2
73
+
74
+ return [pointList[index1], pointList[index2], pointList[index3], pointList[index4]], min(rectangle[1])
75
+
76
+ def boxScore(probabilityMap, box):
77
+ mapHeight, mapWidth = probabilityMap.shape[0:2]
78
+
79
+ boxLocal = box.copy()
80
+
81
+ xMinimum = max(0, min(int(numpy.floor(box[:, 0].min())), mapWidth - 1))
82
+ xMaximum = max(0, min(int(numpy.ceil(box[:, 0].max())), mapWidth - 1))
83
+ yMinimum = max(0, min(int(numpy.floor(box[:, 1].min())), mapHeight - 1))
84
+ yMaximum = max(0, min(int(numpy.ceil(box[:, 1].max())), mapHeight - 1))
85
+
86
+ mask = numpy.zeros((yMaximum - yMinimum + 1, xMaximum - xMinimum + 1), dtype=numpy.uint8)
87
+
88
+ boxLocal[:, 0] = boxLocal[:, 0] - xMinimum
89
+ boxLocal[:, 1] = boxLocal[:, 1] - yMinimum
90
+
91
+ cv2.fillPoly(mask, boxLocal.reshape(1, -1, 2).astype(numpy.int32), 1)
92
+
93
+ return cv2.mean(probabilityMap[yMinimum:yMaximum + 1, xMinimum:xMaximum + 1], mask)[0]
94
+
95
+ def boxUnclip(box):
96
+ area = cv2.contourArea(box)
97
+ length = cv2.arcLength(box, True)
98
+
99
+ distance = area * unclipRatio / length
100
+
101
+ offsetObject = pyclipper.PyclipperOffset()
102
+
103
+ offsetObject.AddPath(box, pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
104
+
105
+ return numpy.array(offsetObject.Execute(distance))
106
+
107
+ def inference(image):
108
+ resultList = []
109
+
110
+ imageHeight, imageWidth = image.shape[0:2]
111
+ imageResized = imageResize(image)
112
+
113
+ tensor = (imageResized.astype(numpy.float32) / 255.0 - meanList) / standardList
114
+ tensor = numpy.expand_dims(tensor.transpose((2, 0, 1)), axis=0).astype(numpy.float32)
115
+
116
+ tensorOutputList = onnxSession.run(None, {"x": tensor})
117
+
118
+ probabilityMap = tensorOutputList[0][0][0]
119
+ bitmap = (probabilityMap > binaryThreshold).astype(numpy.uint8)
120
+
121
+ scaleWidth = imageWidth / float(bitmap.shape[1])
122
+ scaleHeight = imageHeight / float(bitmap.shape[0])
123
+
124
+ contourList, hierarchy = cv2.findContours(bitmap * 255, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
125
+
126
+ for a in range(min(len(contourList), candidateMax)):
127
+ pointList, sideLength = boxOrder(contourList[a])
128
+
129
+ if sideLength < sideMinimum:
130
+ continue
131
+
132
+ score = boxScore(probabilityMap, numpy.array(pointList).reshape(-1, 2))
133
+
134
+ if score < boxThreshold:
135
+ continue
136
+
137
+ pointList, sideLength = boxOrder(boxUnclip(numpy.array(pointList)).reshape(-1, 1, 2))
138
+
139
+ if sideLength < sideMinimum + 2:
140
+ continue
141
+
142
+ coordinateList = []
143
+
144
+ for b in range(len(pointList)):
145
+ x = max(0, min(int(round(pointList[b][0] * scaleWidth)), imageWidth))
146
+ y = max(0, min(int(round(pointList[b][1] * scaleHeight)), imageHeight))
147
+
148
+ coordinateList.append([x, y])
149
+
150
+ resultList.append({
151
+ "score": score,
152
+ "coordinate": coordinateList
153
+ })
154
+
155
+ return resultList
156
+
157
+ image = cv2.imread(sys.argv[1])
158
+
159
+ itemList = inference(image)
160
+
161
+ for a in range(len(itemList)):
162
+ print(f"{itemList[a]['score']:.6f} | {itemList[a]['coordinate']}")