개정판 01a65c95
issue #486: 라인 생성시 잔상이 남는 현상 수정
Change-Id: I6c49d02ebdd4ce4e5c386d35dcc263fbbe6105dd
DTI_PID/DTI_PID/Shapes/EngineeringPolylineItem.py | ||
---|---|---|
19 | 19 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
20 | 20 |
|
21 | 21 |
class QEngineeringPolylineItem(QGraphicsPathItem, QEngineeringAbstractItem): |
22 |
""" |
|
23 |
This is EngineeringPolylineItem Class |
|
24 |
""" |
|
22 |
""" This is EngineeringPolylineItem Class """ |
|
25 | 23 |
|
26 | 24 |
AXIS_MODE = 0 |
27 | 25 |
FREE_MODE = 1 |
... | ... | |
46 | 44 |
self.isCreated = False |
47 | 45 |
self._pt = None |
48 | 46 |
self._pol = QPolygonF() |
49 |
self._path = None |
|
50 | 47 |
self.setPen(QPen(Qt.blue, 4, Qt.SolidLine)) # set default pen |
51 | 48 |
|
52 | 49 |
self.transfer = Transfer() |
... | ... | |
97 | 94 |
@date 2018.04.23 |
98 | 95 |
''' |
99 | 96 |
def buildItem(self): |
100 |
self._path = QPainterPath() |
|
101 |
self._path.addPolygon(self._pol) |
|
102 |
self.setPath(self._path) |
|
97 |
path = QPainterPath() |
|
98 |
path.moveTo(self._vertices[0][0], self._vertices[0][1]) |
|
99 |
for i in range(1, len(self._vertices)): |
|
100 |
path.lineTo(self._vertices[i][0], self._vertices[i][1]) |
|
101 |
if self._pt is not None: |
|
102 |
path.lineTo(self._pt[0], self._pt[1]) |
|
103 |
self.setPath(path) |
|
103 | 104 |
self.isCreated = True |
104 | 105 |
|
105 | 106 |
''' |
... | ... | |
174 | 175 |
else: |
175 | 176 |
self._pt = pt |
176 | 177 |
|
178 |
self.buildItem() |
|
177 | 179 |
self.update() |
178 | 180 |
|
179 | 181 |
''' |
... | ... | |
191 | 193 |
@brief paint |
192 | 194 |
@history 2018.05.11 Jeongwoo Change variable pen → self.pen |
193 | 195 |
''' |
196 |
""" |
|
194 | 197 |
def paint(self, painter, options=None, widget=None): |
195 | 198 |
if self.isCreated: |
196 | 199 |
painter.setPen(self.pen()) |
... | ... | |
201 | 204 |
painter.drawLine(self._vertices[i][0], self._vertices[i][1], self._vertices[i+1][0], self._vertices[i+1][1]) |
202 | 205 |
if self._pt is not None: |
203 | 206 |
painter.drawLine(self._vertices[-1][0], self._vertices[-1][1], self._pt[0], self._pt[1]) |
207 |
""" |
|
204 | 208 |
|
205 | 209 |
''' |
206 | 210 |
@brief Set Color. Override QEngineeringAbstractItem's |
DTI_PID/DTI_PID/azure_ocr_module.py | ||
---|---|---|
1 |
import sys |
|
2 |
import os |
|
3 |
import http.client |
|
4 |
import urllib |
|
5 |
import base64 |
|
6 |
import json |
|
7 |
import cv2 |
|
8 |
import numpy as np |
|
9 |
import matplotlib.pyplot as plt |
|
10 |
import matplotlib.image as mpimg |
|
11 |
from PIL import Image |
|
12 |
from io import BytesIO |
|
13 |
import TextInfo as ti |
|
14 |
|
|
15 |
try: |
|
16 |
from PyQt5.QtCore import * |
|
17 |
from PyQt5.QtGui import * |
|
18 |
except: |
|
19 |
from PyQt4.QtCore import * |
|
20 |
from PyQt4.QtGui import * |
|
21 |
|
|
22 |
EXCEPTION_LIST = ['0', 'o', 'O' |
|
23 |
, '-0', '-o', '-O', '—0', '—o', '—O'] |
|
24 |
STANDARD_SIZE = 30 |
|
25 |
|
|
26 |
def getRotatedAngleByOrientation(orientation): |
|
27 |
angle = 0 |
|
28 |
if orientation == "Up": |
|
29 |
angle = 0 |
|
30 |
elif orientation == "Left": |
|
31 |
angle = 90 |
|
32 |
elif orientation == "Down": |
|
33 |
angle = 180 |
|
34 |
elif orientation == "Right": |
|
35 |
angle = 270 |
|
36 |
else: # general case |
|
37 |
angle = 0 |
|
38 |
return angle |
|
39 |
|
|
40 |
''' |
|
41 |
@history 18.04.25 Jeongwoo Calculate Left-Top Coord by QRect and QTransform |
|
42 |
''' |
|
43 |
def getCoordOnRotatedImage(rAngle, x, y, originImageWidth, originImageHeight, otw, oth): |
|
44 |
rx = None |
|
45 |
ry = None |
|
46 |
transform = QTransform() |
|
47 |
if rAngle == 90 or rAngle == 270: |
|
48 |
transform.translate(originImageHeight*0.5, originImageWidth*0.5) |
|
49 |
elif rAngle == 0 or rAngle == 180: |
|
50 |
transform.translate(originImageWidth*0.5, originImageHeight*0.5) |
|
51 |
transform.rotate(-abs(rAngle)) |
|
52 |
transform.translate(-originImageWidth*0.5, -originImageHeight*0.5) |
|
53 |
rect = QRect(x, y, otw, oth) |
|
54 |
rect = transform.mapRect(rect) |
|
55 |
rx = rect.x() |
|
56 |
ry = rect.y() |
|
57 |
rwidth = rect.width() |
|
58 |
rheight = rect.height() |
|
59 |
return (rx, ry, rwidth, rheight) |
|
60 |
|
|
61 |
def getRollbackRotateCodeByOrientation(orientation): |
|
62 |
rotatedAngle = None |
|
63 |
if orientation == "Left": |
|
64 |
rotatedAngle = cv2.ROTATE_90_COUNTERCLOCKWISE |
|
65 |
elif orientation == "Right": |
|
66 |
rotatedAngle = cv2.ROTATE_90_CLOCKWISE |
|
67 |
else: |
|
68 |
rotatedAngle = cv2.ROTATE_180 |
|
69 |
return rotatedAngle |
|
70 |
|
|
71 |
def getRotateCodeByOrientation(orientation): |
|
72 |
rotatedAngle = None |
|
73 |
if orientation == "Left": |
|
74 |
rotatedAngle = cv2.ROTATE_90_CLOCKWISE |
|
75 |
elif orientation == "Right": |
|
76 |
rotatedAngle = cv2.ROTATE_90_COUNTERCLOCKWISE |
|
77 |
else: |
|
78 |
rotatedAngle = cv2.ROTATE_180 |
|
79 |
return rotatedAngle |
|
80 |
|
|
81 |
|
|
82 |
#################################### |
|
83 |
|
|
84 |
############################################### |
|
85 |
#### Update or verify the following values. ### |
|
86 |
############################################### |
|
87 |
|
|
88 |
# Replace the subscription_key string value with your valid subscription key. |
|
89 |
subscription_key = '0c331f82837b4adeb5cbdb80a6c03d68' # master |
|
90 |
''' |
|
91 |
[NAME] |
|
92 |
CognitiveService_ImagePnID |
|
93 |
[KEY 1] |
|
94 |
0c331f82837b4adeb5cbdb80a6c03d68 |
|
95 |
[KEY 2] |
|
96 |
642218f51d364b00bb6d750d2575ca3f |
|
97 |
''' |
|
98 |
|
|
99 |
# Replace or verify the region. |
|
100 |
# |
|
101 |
# You must use the same region in your REST API call as you used to obtain your |
|
102 |
# subscription keys. |
|
103 |
# For example, if you obtained your subscription keys from the westus region, |
|
104 |
# replace |
|
105 |
# "westcentralus" in the URI below with "westus". |
|
106 |
# |
|
107 |
# NOTE: Free trial subscription keys are generated in the westcentralus region, |
|
108 |
# so if you are using |
|
109 |
# a free trial subscription key, you should not need to change this region. |
|
110 |
uri_base = 'eastasia.api.cognitive.microsoft.com' # southeast asia for master |
|
111 |
|
|
112 |
headers = { |
|
113 |
# Request headers. |
|
114 |
#'Content-Type': 'application/json', |
|
115 |
'Content-Type': 'application/octet-stream', |
|
116 |
'Ocp-Apim-Subscription-Key': subscription_key, |
|
117 |
} |
|
118 |
|
|
119 |
#params = urllib.urlencode({ |
|
120 |
params = urllib.parse.urlencode({ |
|
121 |
# Request parameters. The language setting "unk" means automatically |
|
122 |
# detect the language. |
|
123 |
'language': 'en', |
|
124 |
#'language': 'unk', |
|
125 |
'detectOrientation ': 'false', |
|
126 |
}) |
|
127 |
|
|
128 |
# The URL of a JPEG image containing text. |
|
129 |
#body = "{'url':'D:/Visual Studio Project/PyOpenCv/PyOpenCv/res/symbol1.png'}" |
|
130 |
#body = |
|
131 |
#"{'url':'https://upload.wikimedia.org/wikipedia/commons/thumb/a/af/Atomist_quote_from_Democritus.png/338px-Atomist_quote_from_Democritus.png'}" |
|
132 |
#body = "{'url':'http://cfile9.uf.tistory.com/image/99AFE1505A322DBD114994'}" |
|
133 |
''' |
|
134 |
@history 18.04.25 Jeongwoo Init TextInfo Object with getCoordOnRotatedImage() |
|
135 |
''' |
|
136 |
def detectAndRemoveText(image, offsetX, offsetY): |
|
137 |
tmp = image.copy() |
|
138 |
img = np.array(tmp) |
|
139 |
tInfo = [] |
|
140 |
try: |
|
141 |
tmp = image.copy() |
|
142 |
bin_img = BytesIO() |
|
143 |
tmp.save(bin_img, format='PNG') |
|
144 |
tmp.close() |
|
145 |
|
|
146 |
img_data = bin_img.getvalue() |
|
147 |
bin_img.close() |
|
148 |
|
|
149 |
#region REST API with raw file |
|
150 |
# Execute the REST API call and get the response. |
|
151 |
conn = http.client.HTTPSConnection(uri_base) |
|
152 |
conn.request("POST", "/vision/v1.0/ocr?%s" % params, img_data, headers) |
|
153 |
response = conn.getresponse() |
|
154 |
data = response.read() |
|
155 |
#endregion |
|
156 |
|
|
157 |
#region REST API with url |
|
158 |
## Execute the REST API call and get the response. |
|
159 |
#conn = httplib.HTTPSConnection(uri_base) |
|
160 |
#conn.request("POST", "/vision/v1.0/ocr?%s" % params, body, headers) |
|
161 |
#response = conn.getresponse() |
|
162 |
#data = response.read() |
|
163 |
#endregion |
|
164 |
|
|
165 |
# 'data' contains the JSON data. The following formats the JSON data |
|
166 |
# for display. |
|
167 |
parsed = json.loads(data) |
|
168 |
#print ("Response:") |
|
169 |
#print (json.dumps(parsed, sort_keys=True, indent=2)) |
|
170 |
conn.close() |
|
171 |
#chan, w, h = img.shape[::-1] |
|
172 |
w, h = img.shape[::-1] |
|
173 |
|
|
174 |
orientation = parsed['orientation'] |
|
175 |
#if orientation != "Up": |
|
176 |
# img = cv2.rotate(img, getRotateCodeByOrientation(orientation)) |
|
177 |
|
|
178 |
count = 0 |
|
179 |
print(str(parsed['orientation'])) |
|
180 |
print(str(parsed['textAngle'])) |
|
181 |
for cs in parsed['regions']: |
|
182 |
for re in cs['lines']: |
|
183 |
strArr = re['boundingBox'].split(',') |
|
184 |
(rx, ry, rwidth, rheight) = getCoordOnRotatedImage(getRotatedAngleByOrientation(orientation), int(strArr[0]), int(strArr[1]), w if orientation == 'Up' or orientation == 'Down' else h, h if orientation == 'Up' or orientation == 'Down' else w, int(strArr[2]), int(strArr[3])) |
|
185 |
text = "" |
|
186 |
for words in re['words']: |
|
187 |
print(words) |
|
188 |
text = text + " " + words['text'] |
|
189 |
|
|
190 |
#print(text) |
|
191 |
if not(text in EXCEPTION_LIST and height < STANDARD_SIZE): |
|
192 |
tInfo.append(ti.TextInfo(text.strip(), rx + int(offsetX), ry + int(offsetY), rwidth, rheight, getRotatedAngleByOrientation(orientation))) |
|
193 |
count = count + 1 |
|
194 |
|
|
195 |
print("OCR Result count : " + str(count)) |
|
196 |
|
|
197 |
#if orientation != "Up": |
|
198 |
# img = cv2.rotate(img, getRollbackRotateCodeByOrientation(orientation)) |
|
199 |
|
|
200 |
return (img, tInfo) |
|
201 |
|
|
202 |
except Exception as ex: |
|
203 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
204 |
|
|
205 |
return (img, tInfo) |
|
206 |
|
|
207 |
#def removeText(imagePath): |
|
208 |
# image = Image.open(imagePath) |
|
209 |
# ret = np.array(image) |
|
210 |
# textInfoList = [] |
|
211 |
|
|
212 |
# for i in range(1): |
|
213 |
# (ret, tInfo) = detectAndRemoveText(Image.fromarray(ret)) |
|
214 |
# #ret = cv2.rotate(ret, cv2.ROTATE_90_CLOCKWISE) |
|
215 |
# textInfoList.extend(tInfo) |
|
216 |
|
|
217 |
# image.close() |
|
218 |
# return (ret, textInfoList) |
|
219 |
|
|
220 |
def removeTextFromNpArray(img, offsetX, offsetY): |
|
221 |
ret = img.copy() |
|
222 |
textInfoList = [] |
|
223 |
imgW, imgH = ret.shape[::-1] |
|
224 |
for i in range(1): |
|
225 |
(ret, tInfo) = detectAndRemoveText(Image.fromarray(ret), offsetX, offsetY) |
|
226 |
#ret = cv2.rotate(ret, cv2.ROTATE_90_CLOCKWISE) |
|
227 |
textInfoList.extend(tInfo) |
|
228 |
|
|
229 |
return (ret, textInfoList) |
|
230 |
|
|
231 |
## NOT USED |
|
232 |
def removeText(img, text, x, y, imgW, imgH, width, height, angle): |
|
233 |
roi = img[y:y+height, x:x+width] |
|
234 |
w, h = roi.shape[::-1] |
|
235 |
if w > 0 and h > 0: |
|
236 |
temp = roi.copy() |
|
237 |
tempBin = cv2.bitwise_not(temp) |
|
238 |
img[y:y+height, x:x+width] = cv2.bitwise_xor(roi, tempBin) |
|
239 |
return img |
|
240 |
|
|
241 |
def getTextInfoFromNpArray(image): |
|
242 |
try: |
|
243 |
tmp = Image.fromarray(image) |
|
244 |
bin_img = BytesIO() |
|
245 |
tmp.save(bin_img, format='PNG') |
|
246 |
tmp.close() |
|
247 |
|
|
248 |
img_data = bin_img.getvalue() |
|
249 |
bin_img.close() |
|
250 |
|
|
251 |
#region REST API with raw file |
|
252 |
# Execute the REST API call and get the response. |
|
253 |
conn = http.client.HTTPSConnection(uri_base) |
|
254 |
conn.request("POST", "/vision/v1.0/ocr?%s" % params, img_data, headers) |
|
255 |
response = conn.getresponse() |
|
256 |
data = response.read() |
|
257 |
#endregion |
|
258 |
|
|
259 |
#region REST API with url |
|
260 |
## Execute the REST API call and get the response. |
|
261 |
#conn = httplib.HTTPSConnection(uri_base) |
|
262 |
#conn.request("POST", "/vision/v1.0/ocr?%s" % params, body, headers) |
|
263 |
#response = conn.getresponse() |
|
264 |
#data = response.read() |
|
265 |
#endregion |
|
266 |
|
|
267 |
# 'data' contains the JSON data. The following formats the JSON data |
|
268 |
# for display. |
|
269 |
parsed = json.loads(data) |
|
270 |
#print ("Response:") |
|
271 |
#print (json.dumps(parsed, sort_keys=True, indent=2)) |
|
272 |
conn.close() |
|
273 |
chan, w, h = image.shape[::-1] |
|
274 |
|
|
275 |
orientation = parsed['orientation'] |
|
276 |
if orientation != "Up": |
|
277 |
image = cv2.rotate(image, getRotateCodeByOrientation(orientation)) |
|
278 |
|
|
279 |
count = 0 |
|
280 |
|
|
281 |
textInfoList = [] |
|
282 |
for cs in parsed['regions']: |
|
283 |
for re in cs['lines']: |
|
284 |
for words in re['words']: |
|
285 |
print(words) |
|
286 |
text = words['text'] |
|
287 |
strArr = words['boundingBox'].split(',') |
|
288 |
pt = (int(strArr[0]), int(strArr[1])) |
|
289 |
width = int(strArr[2]) |
|
290 |
height = int(strArr[3]) |
|
291 |
|
|
292 |
textInfoList.append((text, pt, width, height)) |
|
293 |
|
|
294 |
if orientation != "Up": |
|
295 |
image = cv2.rotate(image, getRollbackRotateCodeByOrientation(orientation)) |
|
296 |
|
|
297 |
return textInfoList |
|
298 |
|
|
299 |
except Exception as ex: |
|
300 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
301 |
|
|
302 |
return None |
|
303 |
|
|
304 |
if __name__ == '__main__': |
|
305 |
from AppDocData import AppDocData |
|
306 |
im = cv2.imread('D:/Visual Studio Project/DTIPID/DTIPID/DTI_PID/DTI_PID/res/UY1-K-2000_P1_300dpi.png', 1) |
|
307 |
#im = cv2.imread('D:/TestSrc/ConvertPNG/10077467_PFD-Diesel Hydrotreating_171120_P1_1100DPI.png', 1) |
|
308 |
area = AppDocData.instance().getArea('Drawing') |
|
309 |
if area is not None: |
|
310 |
im = im[int(area.y):int(area.y+area.height), int(area.x):int(area.x+area.width)] |
|
311 |
im = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY) |
|
312 |
(_img, textInfoList) = removeTextFromNpArray(im, 0, 0) |
|
313 |
for tinfo in textInfoList: |
|
314 |
cv2.putText(im, tinfo.getText(), (tinfo.getX(), tinfo.getY()+tinfo.getH()), 2, 1.0, (0, 0, 0)) |
|
315 |
cv2.rectangle(im, (tinfo.getX(), tinfo.getY()), (tinfo.getX()+tinfo.getW(), tinfo.getY()+tinfo.getH()), (0, 0, 255), 2) |
|
316 |
cv2.imwrite(os.path.dirname(os.path.realpath(__file__)) + "/res/Result/Standalone_OCR_Test.png", im) |
내보내기 Unified diff