개정판 88c80c43
issue #663: craft testing
Change-Id: Ic61dd2ba0971430a0219d7b53bee066e6c55a0a7
DTI_PID/DTI_PID/TextDetector.py | ||
---|---|---|
110 | 110 |
@history 2018.06.08 Jeongwoo Add angle |
111 | 111 |
humkyung 2018.06.18 fixed logic to detect text area |
112 | 112 |
''' |
113 |
|
|
114 | 113 |
def getTextAreaInfo(self, imgGray, offset_x, offset_y): |
115 | 114 |
#from imutils.object_detection import non_max_suppression |
116 | 115 |
from AppDocData import AppDocData |
... | ... | |
127 | 126 |
minSize = int(configs[0].value) if 1 == len(configs) else 15 |
128 | 127 |
|
129 | 128 |
ocr_image = imgGray.copy() # np.ones(imgGray.shape, np.uint8) * 255 |
130 |
cv2.rectangle(ocr_image, (0, 0), ocr_image.shape[::-1], (255, 255, 255), -1) |
|
131 |
|
|
132 |
mask = cv2.threshold(imgGray, 200, 255, cv2.THRESH_BINARY)[1] |
|
133 | 129 |
|
134 |
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) |
|
135 |
for contour in contours: |
|
136 |
# remove too big one or horizontal/vertical line |
|
137 |
[x, y, w, h] = cv2.boundingRect(contour) |
|
138 |
area = cv2.contourArea(contour, True) |
|
139 |
|
|
140 |
# skip one which size is greater than max size or less then minimum size |
|
141 |
if (w > maxTextSize or h > maxTextSize) or (w <= minSize and h <= minSize): |
|
142 |
#cv2.drawContours(ocr_image, [contour], -1, (255, 255, 255), -1) |
|
143 |
continue |
|
130 |
# get text box original way |
|
131 |
not_containing_bbox, binary_image = self.getTextBox(ocr_image, imgGray, maxTextSize, minSize) |
|
144 | 132 |
|
145 |
if area >= 0: |
|
146 |
cv2.drawContours(ocr_image, [contour], -1, (0, 0, 0), -1) |
|
147 |
#cv2.drawContours(ocr_image, [contour], -1, (255, 255, 255), 1) |
|
148 |
#else: |
|
149 |
# cv2.drawContours(ocr_image, [contour], -1, (255, 255, 255), -1) |
|
133 |
# using craft |
|
134 |
#not_containing_bbox, binary_image = self.getTextBox_craft(ocr_image, maxTextSize, minSize) |
|
150 | 135 |
|
151 |
path = os.path.join(project.getTempPath(), 'OCR_{}.png'.format(app_doc_data.imgName)) |
|
152 |
cv2.imwrite(path, ocr_image) |
|
153 |
|
|
154 |
""" |
|
155 |
east = False |
|
156 |
if east: |
|
157 |
# define the two output layer names for the EAST detector model that |
|
158 |
# we are interested -- the first is the output probabilities and the |
|
159 |
# second can be used to derive the bounding box coordinates of text |
|
160 |
layerNames = [ |
|
161 |
"feature_fusion/Conv_7/Sigmoid", |
|
162 |
"feature_fusion/concat_3"] |
|
163 |
|
|
164 |
# load the pre-trained EAST text detector |
|
165 |
net = cv2.dnn.readNet("C:\\ProgramData\\Digital PID\\frozen_east_text_detection.pb") |
|
166 |
|
|
167 |
(H, W) = ocr_image.shape[:2] |
|
168 |
# construct a blob from the image and then perform a forward pass of |
|
169 |
# the model to obtain the two output layer sets |
|
170 |
blob = cv2.dnn.blobFromImage(ocr_image, 1.0, (W, H), (123.68, 116.78, 103.94), swapRB=True, crop=False) |
|
171 |
net.setInput(blob) |
|
172 |
(scores, geometry) = net.forward(layerNames) |
|
173 |
|
|
174 |
# decode the predictions, then apply non-maxima suppression to |
|
175 |
# suppress weak, overlapping bounding boxes |
|
176 |
(rects, confidences) = self.decode_predictions(scores, geometry) |
|
177 |
boxes = non_max_suppression(np.array(rects), probs=confidences) |
|
178 |
# loop over the bounding boxes |
|
179 |
for (startX, startY, endX, endY) in boxes: |
|
180 |
pass |
|
181 |
else: |
|
182 |
""" |
|
183 | 136 |
rects = [] |
184 |
configs = app_doc_data.getConfigs('Text Recognition', 'Expand Size') |
|
185 |
expand_size = int(configs[0].value) if 1 == len(configs) else 10 |
|
186 |
configs = app_doc_data.getConfigs('Text Recognition', 'Shrink Size') |
|
187 |
shrinkSize = int(configs[0].value) if 1 == len(configs) else 0 |
|
188 |
|
|
189 |
binary_image = cv2.threshold(ocr_image, 200, 255, cv2.THRESH_BINARY)[1] |
|
190 |
eroded = cv2.erode(binary_image, np.ones((expand_size, expand_size), np.uint8)) |
|
191 |
eroded = cv2.bitwise_not(eroded) |
|
192 |
|
|
193 |
bboxes = [] |
|
194 |
contours, hierarchy = cv2.findContours(eroded, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) |
|
195 |
for contour in contours: |
|
196 |
area = cv2.contourArea(contour, True) |
|
197 |
if area < 0: |
|
198 |
[x, y, w, h] = cv2.boundingRect(contour) |
|
199 |
bboxes.append(QRect(x, y, w, h)) |
|
200 |
|
|
201 |
# exclude bounding boxes contains child bounding box |
|
202 |
not_containing_bbox = [] |
|
203 |
for bbox in bboxes: |
|
204 |
matches = [_bbox for _bbox in bboxes if bbox != _bbox and bbox.contains(_bbox)] |
|
205 |
if not matches: |
|
206 |
not_containing_bbox.append(bbox) |
|
207 |
# up to here |
|
208 | 137 |
|
209 | 138 |
for bbox in not_containing_bbox: |
210 | 139 |
x, y = bbox.left(), bbox.top() |
... | ... | |
278 | 207 |
|
279 | 208 |
return list, ocr_image |
280 | 209 |
|
210 |
def getTextBox_craft(self, ocr_image, maxTextSize, minSize): |
|
211 |
pass |
|
212 |
''' |
|
213 |
from CRAFT_pytorch_master import text_craft |
|
214 |
from AppDocData import AppDocData |
|
215 |
|
|
216 |
app_doc_data = AppDocData.instance() |
|
217 |
project = app_doc_data.getCurrentProject() |
|
218 |
|
|
219 |
binary_image = cv2.threshold(ocr_image, 200, 255, cv2.THRESH_BINARY)[1] |
|
220 |
|
|
221 |
score_path = os.path.join(project.getTempPath(), 'OCR_CRAFT_SCORE_{}.png'.format(app_doc_data.imgName)) |
|
222 |
img_path = os.path.join(project.getTempPath(), 'OCR_CRAFT_{}.png'.format(app_doc_data.imgName)) |
|
223 |
|
|
224 |
boxes = text_craft.get_text_box(ocr_image, img_path, score_path) |
|
225 |
rects = [] |
|
226 |
|
|
227 |
for box in boxes: |
|
228 |
rects.append(QRect(box[0], box[1], box[4] - box[0], box[5] - box[1])) |
|
229 |
|
|
230 |
return rects, binary_image |
|
231 |
''' |
|
232 |
|
|
233 |
def getTextBox(self, ocr_image, imgGray, maxTextSize, minSize): |
|
234 |
""" get text box """ |
|
235 |
from AppDocData import AppDocData |
|
236 |
|
|
237 |
app_doc_data = AppDocData.instance() |
|
238 |
project = app_doc_data.getCurrentProject() |
|
239 |
|
|
240 |
cv2.rectangle(ocr_image, (0, 0), ocr_image.shape[::-1], (255, 255, 255), -1) |
|
241 |
|
|
242 |
mask = cv2.threshold(imgGray, 200, 255, cv2.THRESH_BINARY)[1] |
|
243 |
|
|
244 |
contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE) |
|
245 |
for contour in contours: |
|
246 |
# remove too big one or horizontal/vertical line |
|
247 |
[x, y, w, h] = cv2.boundingRect(contour) |
|
248 |
area = cv2.contourArea(contour, True) |
|
249 |
|
|
250 |
# skip one which size is greater than max size or less then minimum size |
|
251 |
if (w > maxTextSize or h > maxTextSize) or (w <= minSize and h <= minSize): |
|
252 |
#cv2.drawContours(ocr_image, [contour], -1, (255, 255, 255), -1) |
|
253 |
continue |
|
254 |
|
|
255 |
if area >= 0: |
|
256 |
cv2.drawContours(ocr_image, [contour], -1, (0, 0, 0), -1) |
|
257 |
#cv2.drawContours(ocr_image, [contour], -1, (255, 255, 255), 1) |
|
258 |
#else: |
|
259 |
# cv2.drawContours(ocr_image, [contour], -1, (255, 255, 255), -1) |
|
260 |
|
|
261 |
path = os.path.join(project.getTempPath(), 'OCR_{}.png'.format(app_doc_data.imgName)) |
|
262 |
cv2.imwrite(path, ocr_image) |
|
263 |
|
|
264 |
""" |
|
265 |
east = False |
|
266 |
if east: |
|
267 |
# define the two output layer names for the EAST detector model that |
|
268 |
# we are interested -- the first is the output probabilities and the |
|
269 |
# second can be used to derive the bounding box coordinates of text |
|
270 |
layerNames = [ |
|
271 |
"feature_fusion/Conv_7/Sigmoid", |
|
272 |
"feature_fusion/concat_3"] |
|
273 |
|
|
274 |
# load the pre-trained EAST text detector |
|
275 |
net = cv2.dnn.readNet("C:\\ProgramData\\Digital PID\\frozen_east_text_detection.pb") |
|
276 |
|
|
277 |
(H, W) = ocr_image.shape[:2] |
|
278 |
# construct a blob from the image and then perform a forward pass of |
|
279 |
# the model to obtain the two output layer sets |
|
280 |
blob = cv2.dnn.blobFromImage(ocr_image, 1.0, (W, H), (123.68, 116.78, 103.94), swapRB=True, crop=False) |
|
281 |
net.setInput(blob) |
|
282 |
(scores, geometry) = net.forward(layerNames) |
|
283 |
|
|
284 |
# decode the predictions, then apply non-maxima suppression to |
|
285 |
# suppress weak, overlapping bounding boxes |
|
286 |
(rects, confidences) = self.decode_predictions(scores, geometry) |
|
287 |
boxes = non_max_suppression(np.array(rects), probs=confidences) |
|
288 |
# loop over the bounding boxes |
|
289 |
for (startX, startY, endX, endY) in boxes: |
|
290 |
pass |
|
291 |
else: |
|
292 |
""" |
|
293 |
configs = app_doc_data.getConfigs('Text Recognition', 'Expand Size') |
|
294 |
expand_size = int(configs[0].value) if 1 == len(configs) else 10 |
|
295 |
configs = app_doc_data.getConfigs('Text Recognition', 'Shrink Size') |
|
296 |
shrinkSize = int(configs[0].value) if 1 == len(configs) else 0 |
|
297 |
|
|
298 |
binary_image = cv2.threshold(ocr_image, 200, 255, cv2.THRESH_BINARY)[1] |
|
299 |
eroded = cv2.erode(binary_image, np.ones((expand_size, expand_size), np.uint8)) |
|
300 |
eroded = cv2.bitwise_not(eroded) |
|
301 |
|
|
302 |
bboxes = [] |
|
303 |
contours, hierarchy = cv2.findContours(eroded, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) |
|
304 |
for contour in contours: |
|
305 |
area = cv2.contourArea(contour, True) |
|
306 |
if area < 0: |
|
307 |
[x, y, w, h] = cv2.boundingRect(contour) |
|
308 |
bboxes.append(QRect(x, y, w, h)) |
|
309 |
|
|
310 |
# exclude bounding boxes contains child bounding box |
|
311 |
not_containing_bbox = [] |
|
312 |
for bbox in bboxes: |
|
313 |
matches = [_bbox for _bbox in bboxes if bbox != _bbox and bbox.contains(_bbox)] |
|
314 |
if not matches: |
|
315 |
not_containing_bbox.append(bbox) |
|
316 |
# up to here |
|
317 |
|
|
318 |
return not_containing_bbox, binary_image |
|
319 |
|
|
320 |
|
|
281 | 321 |
''' |
282 | 322 |
@brief recognize text of given text info |
283 | 323 |
@author humkyung |
... | ... | |
285 | 325 |
@history change parameter updateProgressSignal to worker |
286 | 326 |
2018.11.08 euisung add white char list check process on db |
287 | 327 |
''' |
288 |
|
|
289 | 328 |
@staticmethod |
290 | 329 |
def recognizeTextFromImage(tInfos, imgOCR, offset, searchedSymbolList, worker, listWidget, maxProgressValue): |
291 | 330 |
import re |
내보내기 Unified diff