개정판 38657e1b
issue #480: 라인 인식(revised)
Change-Id: I53ac02518e08cc1a10e051827090433d74c3429c
DTI_PID/DTI_PID/Commands/DefaultCommand.py | ||
---|---|---|
80 | 80 |
self._vertices.append(param[2]) |
81 | 81 |
finally: |
82 | 82 |
self.imageViewer.setDragMode(QGraphicsView.NoDrag) |
83 |
x = min(self._vertices[0].x(), self._vertices[1].x()) |
|
84 |
y = min(self._vertices[0].y(), self._vertices[1].y()) |
|
85 |
width = abs(self._vertices[0].x() - self._vertices[1].x()) |
|
86 |
height = abs(self._vertices[0].y() - self._vertices[1].y()) |
|
87 |
self.onSuccess.emit(x, y, width, height) |
|
83 |
if len(self._vertices) == 2: |
|
84 |
x = min(self._vertices[0].x(), self._vertices[1].x()) |
|
85 |
y = min(self._vertices[0].y(), self._vertices[1].y()) |
|
86 |
width = abs(self._vertices[0].x() - self._vertices[1].x()) |
|
87 |
height = abs(self._vertices[0].y() - self._vertices[1].y()) |
|
88 |
self.onSuccess.emit(x, y, width, height) |
|
88 | 89 |
self.isClicked = False |
89 | 90 |
elif self.isClicked and 'mouseMoveEvent' == param[0]: |
90 | 91 |
endX = scenePos.x() |
DTI_PID/DTI_PID/LineDetector.py | ||
---|---|---|
429 | 429 |
|
430 | 430 |
def connectLineToSymbol(self, line, symbol, toler): |
431 | 431 |
try: |
432 |
start_pt = list(line.startPoint())
|
|
432 |
start_pt = list(line.start_point())
|
|
433 | 433 |
distStart = [(self.distanceTo(start_pt, (connector.center()[0], connector.center()[1])), |
434 | 434 |
(connector.center()[0], connector.center()[1])) for connector in |
435 | 435 |
symbol.connectors] |
436 | 436 |
distStart.sort() |
437 | 437 |
|
438 |
end_pt = list(line.endPoint())
|
|
438 |
end_pt = list(line.end_point())
|
|
439 | 439 |
distEnd = [(self.distanceTo(end_pt, (connector.center()[0], connector.center()[1])), |
440 | 440 |
(connector.center()[0], connector.center()[1])) for connector in |
441 | 441 |
symbol.connectors] |
... | ... | |
495 | 495 |
if not res: |
496 | 496 |
return |
497 | 497 |
|
498 |
lhs_start = list(lhs.startPoint())
|
|
499 |
lhs_end = list(lhs.endPoint())
|
|
500 |
rhs_start = list(rhs.startPoint())
|
|
501 |
rhs_end = list(rhs.endPoint())
|
|
498 |
lhs_start = list(lhs.start_point())
|
|
499 |
lhs_end = list(lhs.end_point())
|
|
500 |
rhs_start = list(rhs.start_point())
|
|
501 |
rhs_end = list(rhs.end_point())
|
|
502 | 502 |
|
503 | 503 |
dx = rhs_end[0] - rhs_start[0] |
504 | 504 |
dy = rhs_end[1] - rhs_start[1] |
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
3342 | 3342 |
# flowMark.setParentItem(line) |
3343 | 3343 |
# up to here |
3344 | 3344 |
|
3345 |
""" |
|
3346 |
group_box = QGroupBox("Contact Details") |
|
3347 |
number_label = QLabel("Telephone number"); |
|
3348 |
number_edit = QTextEdit('hello\nthis is ....') |
|
3349 |
layout = QFormLayout() |
|
3350 |
layout.addRow(number_label, number_edit) |
|
3351 |
group_box.setLayout(layout) |
|
3352 |
|
|
3353 |
proxy = QGraphicsProxyWidget() |
|
3354 |
proxy.setWidget(group_box) |
|
3355 |
self.graphicsView.scene().addItem(proxy) # (group_box, QGraphicsItem.ItemIgnoresTransformations) |
|
3356 |
""" |
|
3357 |
|
|
3345 | 3358 |
""" update scene """ |
3346 | 3359 |
_items = [_item for _item in self.graphicsView.scene().items() if hasattr(_item, 'owner') or hasattr(_item, 'connectors')] |
3347 | 3360 |
if _items: |
DTI_PID/DTI_PID/MainWindow_UI.py | ||
---|---|---|
2 | 2 |
|
3 | 3 |
# Form implementation generated from reading ui file '.\UI\MainWindow.ui' |
4 | 4 |
# |
5 |
# Created by: PyQt5 UI code generator 5.14.1
|
|
5 |
# Created by: PyQt5 UI code generator 5.13.0
|
|
6 | 6 |
# |
7 | 7 |
# WARNING! All changes made in this file will be lost! |
8 | 8 |
|
... | ... | |
515 | 515 |
self.actionExportAsImage.setObjectName("actionExportAsImage") |
516 | 516 |
self.actionEditRecognizeLine = QtWidgets.QAction(MainWindow) |
517 | 517 |
self.actionEditRecognizeLine.setObjectName("actionEditRecognizeLine") |
518 |
self.actionRecognizeTable = QtWidgets.QAction(MainWindow) |
|
519 |
icon24 = QtGui.QIcon() |
|
520 |
icon24.addPixmap(QtGui.QPixmap(":/newPrefix/table_ocr.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off) |
|
521 |
self.actionRecognizeTable.setIcon(icon24) |
|
522 |
self.actionRecognizeTable.setObjectName("actionRecognizeTable") |
|
518 | 523 |
self.menuExport.addAction(self.actionExportAsSVG) |
519 | 524 |
self.menuExport.addAction(self.actionExportAsXML) |
520 | 525 |
self.menuExport.addAction(self.actionExportAsImage) |
... | ... | |
559 | 564 |
self.menu_5.addAction(self.actionText_Data_List) |
560 | 565 |
self.menu_5.addSeparator() |
561 | 566 |
self.menu_5.addAction(self.actionEditRecognizeLine) |
567 |
self.menu_5.addAction(self.actionRecognizeTable) |
|
562 | 568 |
self.menuHelp.addAction(self.actionHelp) |
563 | 569 |
self.menubar.addAction(self.menu.menuAction()) |
564 | 570 |
self.menubar.addAction(self.menu_5.menuAction()) |
... | ... | |
698 | 704 |
self.actionExportAsImage.setText(_translate("MainWindow", "Image")) |
699 | 705 |
self.actionEditRecognizeLine.setText(_translate("MainWindow", "Recognize Line")) |
700 | 706 |
self.actionEditRecognizeLine.setToolTip(_translate("MainWindow", "Recognize Line")) |
707 |
self.actionRecognizeTable.setText(_translate("MainWindow", "Recognize Table")) |
|
708 |
self.actionRecognizeTable.setToolTip(_translate("MainWindow", "Recognize Table")) |
|
709 |
self.actionRecognizeTable.setShortcut(_translate("MainWindow", "Alt+T")) |
|
701 | 710 |
import MainWindow_rc |
DTI_PID/DTI_PID/QtImageViewer.py | ||
---|---|---|
567 | 567 |
if len(self.scene().items()) is 0: |
568 | 568 |
return |
569 | 569 |
if hasattr(self, '_underItem') and self._underItem is not None and self._underItem in self.scene().items(): |
570 |
self._underItem.hoverLeaveEvent(event)
|
|
570 |
self._underItem.hoverLeaveEvent(None)
|
|
571 | 571 |
self._underItem = None |
572 | 572 |
else: |
573 | 573 |
self._underItem = None |
DTI_PID/DTI_PID/Shapes/EngineeringGuidelineItem.py | ||
---|---|---|
56 | 56 |
@author humkyung |
57 | 57 |
@date 2018.08.28 |
58 | 58 |
''' |
59 |
def startPoint(self):
|
|
59 |
def start_point(self):
|
|
60 | 60 |
at = self.line().p1() |
61 | 61 |
return (at.x(), at.y()) |
62 | 62 |
|
... | ... | |
65 | 65 |
@author humkyung |
66 | 66 |
@date 2018.08.28 |
67 | 67 |
''' |
68 |
def endPoint(self):
|
|
68 |
def end_point(self):
|
|
69 | 69 |
at = self.line().p2() |
70 | 70 |
return (at.x(), at.y()) |
71 | 71 |
|
... | ... | |
77 | 77 |
def isHorizontal(self): |
78 | 78 |
import math |
79 | 79 |
|
80 |
startPt = self.startPoint()
|
|
81 |
endPt = self.endPoint()
|
|
80 |
startPt = self.start_point()
|
|
81 |
endPt = self.end_point()
|
|
82 | 82 |
dx = endPt[0] - startPt[0] |
83 | 83 |
dy = endPt[1] - startPt[1] |
84 | 84 |
|
... | ... | |
92 | 92 |
def isVertical(self): |
93 | 93 |
import math |
94 | 94 |
|
95 |
startPt = self.startPoint()
|
|
96 |
endPt = self.endPoint()
|
|
95 |
startPt = self.start_point()
|
|
96 |
endPt = self.end_point()
|
|
97 | 97 |
dx = endPt[0] - startPt[0] |
98 | 98 |
dy = endPt[1] - startPt[1] |
99 | 99 |
|
DTI_PID/DTI_PID/Shapes/EngineeringOriginItem.py | ||
---|---|---|
148 | 148 |
length = items[0].length()*0.5 |
149 | 149 |
dir = items[0].perpendicular() |
150 | 150 |
if self.parent.isHorizontal(): |
151 |
start = [event.scenePos().x() - dir[0]*length, self.parent.startPoint()[1] - dir[1]*length]
|
|
152 |
end = [event.scenePos().x() + dir[0]*length, self.parent.startPoint()[1] + dir[1]*length]
|
|
151 |
start = [event.scenePos().x() - dir[0]*length, self.parent.start_point()[1] - dir[1]*length]
|
|
152 |
end = [event.scenePos().x() + dir[0]*length, self.parent.start_point()[1] + dir[1]*length]
|
|
153 | 153 |
else: |
154 |
start = [self.parent.startPoint()[0] - dir[0]*length, event.scenePos().y() - dir[1]*length]
|
|
155 |
end = [self.parent.startPoint()[0] + dir[0]*length, event.scenePos().y() + dir[1]*length]
|
|
154 |
start = [self.parent.start_point()[0] - dir[0]*length, event.scenePos().y() - dir[1]*length]
|
|
155 |
end = [self.parent.start_point()[0] + dir[0]*length, event.scenePos().y() + dir[1]*length]
|
|
156 | 156 |
|
157 | 157 |
pt = items[0].intersection([start, end]) |
158 | 158 |
if (pt is not None) and (type(pt) == shapely.geometry.point.Point): |
... | ... | |
229 | 229 |
length = items[0].length()*0.5 |
230 | 230 |
dir = items[0].perpendicular() |
231 | 231 |
if self.parent.isHorizontal(): |
232 |
start = [event.scenePos().x() - dir[0]*length, self.parent.startPoint()[1] - dir[1]*length]
|
|
233 |
end = [event.scenePos().x() + dir[0]*length, self.parent.startPoint()[1] + dir[1]*length]
|
|
232 |
start = [event.scenePos().x() - dir[0]*length, self.parent.start_point()[1] - dir[1]*length]
|
|
233 |
end = [event.scenePos().x() + dir[0]*length, self.parent.start_point()[1] + dir[1]*length]
|
|
234 | 234 |
else: |
235 |
start = [self.parent.startPoint()[0] - dir[0]*length, event.scenePos().y() - dir[1]*length]
|
|
236 |
end = [self.parent.startPoint()[0] + dir[0]*length, event.scenePos().y() + dir[1]*length]
|
|
235 |
start = [self.parent.start_point()[0] - dir[0]*length, event.scenePos().y() - dir[1]*length]
|
|
236 |
end = [self.parent.start_point()[0] + dir[0]*length, event.scenePos().y() + dir[1]*length]
|
|
237 | 237 |
|
238 | 238 |
pt = items[0].intersection([start, end]) |
239 | 239 |
if (pt is not None) and (type(pt) == shapely.geometry.point.Point): |
DTI_PID/DTI_PID/Shapes/EngineeringPolylineItem.py | ||
---|---|---|
204 | 204 |
|
205 | 205 |
def boundingRectOnScene(self): |
206 | 206 |
rect = self.boundingRect() |
207 |
sp = self.startPoint()
|
|
207 |
sp = self.start_point()
|
|
208 | 208 |
rect.moveTo(sp[0], sp[1]) |
209 | 209 |
return rect |
210 | 210 |
|
DTI_PID/DTI_PID/Shapes/EngineeringReservedWordTextItem.py | ||
---|---|---|
93 | 93 |
dx = dl if (line.connectors[0].center()[0] - line.connectors[1].center()[0]) > 0 else -dl |
94 | 94 |
dy = -dl if (line.connectors[0].center()[1] - line.connectors[1].center()[1]) > 0 else dl |
95 | 95 |
|
96 |
startPoint = line.endPoint()
|
|
96 |
startPoint = line.end_point()
|
|
97 | 97 |
for index in range(30): |
98 | 98 |
point = (startPoint[0] + index * dx, startPoint[1] + index * dy) |
99 | 99 |
if self.sceneBoundingRect().contains(point[0], point[1]): |
DTI_PID/DTI_PID/Shapes/EngineeringTextItem.py | ||
---|---|---|
191 | 191 |
''' |
192 | 192 |
|
193 | 193 |
def keyPressEvent(self, event): |
194 |
import math |
|
195 |
|
|
196 | 194 |
if Qt.Key_Return == event.key(): |
197 | 195 |
self.edit_text() |
198 | 196 |
elif event.key() == Qt.Key_R: |
... | ... | |
272 | 270 |
''' |
273 | 271 |
|
274 | 272 |
def drawFocusRect(self, painter): |
275 |
self.focuspen = QPen(Qt.DotLine) |
|
276 |
self.focuspen.setColor(Qt.black) |
|
277 |
self.focuspen.setWidthF(1.5) |
|
278 |
hilightColor = QColor(255, 0, 0, 127) |
|
279 |
painter.setBrush(QBrush(hilightColor)) |
|
280 |
painter.setPen(self.focuspen) |
|
273 |
if not hasattr(self, '_focus_pen'): |
|
274 |
self._focus_pen = QPen(Qt.DotLine) |
|
275 |
self._focus_pen.setColor(Qt.black) |
|
276 |
self._focus_pen.setWidthF(1.5) |
|
277 |
|
|
278 |
if not hasattr(self, '_hilight_color'): |
|
279 |
self._hilight_color = QColor(255, 0, 0, 127) |
|
280 |
painter.setBrush(QBrush(self._hilight_color)) |
|
281 |
|
|
282 |
painter.setPen(self._focus_pen) |
|
281 | 283 |
painter.drawRect(self.text_size) |
282 | 284 |
|
283 | 285 |
''' |
... | ... | |
378 | 380 |
|
379 | 381 |
return item |
380 | 382 |
|
383 |
def focusOutEvent(self, event: QFocusEvent) -> None: |
|
384 |
self.setTextInteractionFlags(Qt.NoTextInteraction) |
|
385 |
super(QEngineeringTextItem, self).focusOutEvent(event) |
|
386 |
|
|
381 | 387 |
''' |
382 | 388 |
@brief Double click event, Show QOcrResultDialog |
383 | 389 |
@author Jeongwoo |
... | ... | |
387 | 393 |
|
388 | 394 |
def mouseDoubleClickEvent(self, event): |
389 | 395 |
if event.buttons() == Qt.LeftButton: |
396 |
""" |
|
397 |
if self.textInteractionFlags() == Qt.NoTextInteraction: |
|
398 |
self.setTextInteractionFlags(Qt.TextEditorInteraction) |
|
399 |
self.setFocus() |
|
400 |
""" |
|
390 | 401 |
self.edit_text() |
402 |
super(QGraphicsTextItem, self).mouseDoubleClickEvent(event) |
|
391 | 403 |
|
392 | 404 |
''' |
393 | 405 |
@brief rotate text |
DTI_PID/DTI_PID/Shapes/SymbolSvgItem.py | ||
---|---|---|
265 | 265 |
App.mainWnd().addMessage.emit(MessageType.Error, str(self.uid) + self.name + message) |
266 | 266 |
|
267 | 267 |
def validate(self): |
268 |
''' |
|
269 |
@brief validation check |
|
270 |
@author euisung |
|
271 |
@date 2019.04.16 |
|
272 |
''' |
|
268 |
"""validation check""" |
|
269 |
|
|
273 | 270 |
from EngineeringAbstractItem import QEngineeringAbstractItem |
274 | 271 |
from EngineeringLineItem import QEngineeringLineItem |
275 | 272 |
from EngineeringSpecBreakItem import QEngineeringSpecBreakItem |
... | ... | |
278 | 275 |
errors = [] |
279 | 276 |
|
280 | 277 |
try: |
281 |
docdata = AppDocData.instance()
|
|
282 |
dataPath = docdata.getErrorItemSvgPath()
|
|
278 |
app_doc_data = AppDocData.instance()
|
|
279 |
dataPath = app_doc_data.getErrorItemSvgPath()
|
|
283 | 280 |
|
284 | 281 |
# validate connectors |
285 | 282 |
for connector in self.connectors: |
... | ... | |
287 | 284 |
|
288 | 285 |
# check if connected two lines has same direction |
289 | 286 |
if len(self.connectors) is 2: |
290 |
if (type(self.connectors[0].connectedItem) is QEngineeringLineItem and self.connectors[
|
|
291 |
0]._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT) and \ |
|
292 |
(type(self.connectors[1].connectedItem) is QEngineeringLineItem and self.connectors[
|
|
293 |
1]._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT):
|
|
287 |
if (type(self.connectors[0].connectedItem) is QEngineeringLineItem and |
|
288 |
self.connectors[0]._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT) and \
|
|
289 |
(type(self.connectors[1].connectedItem) is QEngineeringLineItem and |
|
290 |
self.connectors[1]._connected_at == QEngineeringAbstractItem.CONNECTED_AT_PT):
|
|
294 | 291 |
indices = [0, 0] |
295 | 292 |
|
296 | 293 |
center = self.connectors[0].center() |
... | ... | |
318 | 315 |
errors.append(error) |
319 | 316 |
|
320 | 317 |
# check disconnected point |
321 |
disconnect = False |
|
322 |
if len(self.connectors) is not 0: |
|
323 |
disconnect = True |
|
324 |
for connector in self.connectors: |
|
325 |
if connector.connectedItem is not None: |
|
326 |
disconnect = False |
|
327 |
break |
|
318 |
attrs = self.getAttributes() |
|
319 |
matches = [(attr, value) for attr, value in attrs.items() if attr.Attribute == 'OWNERSYMBOL'] |
|
320 |
if matches: |
|
321 |
if not matches[0][1]: |
|
322 |
error = SymbolSvgItem.createItem('Error', None, dataPath) |
|
323 |
error.parent = self |
|
324 |
error.msg = 'not combined' |
|
325 |
error.setToolTip(error.msg) |
|
326 |
error.area = 'Drawing' |
|
327 |
error.name = 'Error' |
|
328 |
errors.append(error) |
|
329 |
else: |
|
330 |
disconnect = False |
|
331 |
if len(self.connectors) is not 0: |
|
332 |
disconnect = True |
|
333 |
for connector in self.connectors: |
|
334 |
if connector.connectedItem is not None: |
|
335 |
disconnect = False |
|
336 |
break |
|
328 | 337 |
|
329 |
if disconnect: |
|
330 |
error = SymbolSvgItem.createItem('Error', None, dataPath) |
|
331 |
error.parent = self |
|
332 |
error.msg = 'disconnected' |
|
333 |
error.setToolTip(error.msg) |
|
334 |
error.area = 'Drawing' |
|
335 |
error.name = 'Error' |
|
336 |
errors.append(error) |
|
338 |
if disconnect:
|
|
339 |
error = SymbolSvgItem.createItem('Error', None, dataPath)
|
|
340 |
error.parent = self
|
|
341 |
error.msg = 'disconnected'
|
|
342 |
error.setToolTip(error.msg)
|
|
343 |
error.area = 'Drawing'
|
|
344 |
error.name = 'Error'
|
|
345 |
errors.append(error)
|
|
337 | 346 |
|
338 | 347 |
# check if symbol size if 0 |
339 | 348 |
if self.size[0] == 0 or self.size[1] == 0: |
... | ... | |
1633 | 1642 |
|
1634 | 1643 |
except_pattern = re.compile('[^a-zA-Z0-9-_]') |
1635 | 1644 |
for attr, value in self.getAttributes().items(): |
1636 |
node.attrib[re.sub(except_pattern, '_', attr.Attribute)] = value if value else ''
|
|
1645 |
node.attrib[re.sub(except_pattern, '_', attr.Attribute)] = str(value) if value else ''
|
|
1637 | 1646 |
trans = self.sceneTransform() |
1638 | 1647 |
node.attrib['transform'] = f"matrix(" \ |
1639 | 1648 |
f"{trans.m11()},{trans.m12()}," \ |
DTI_PID/DTI_PID/UI/MainWindow.ui | ||
---|---|---|
143 | 143 |
<addaction name="actionText_Data_List"/> |
144 | 144 |
<addaction name="separator"/> |
145 | 145 |
<addaction name="actionEditRecognizeLine"/> |
146 |
<addaction name="actionRecognizeTable"/> |
|
146 | 147 |
</widget> |
147 | 148 |
<widget class="QMenu" name="menuHelp"> |
148 | 149 |
<property name="title"> |
... | ... | |
1183 | 1184 |
<string>Recognize Line</string> |
1184 | 1185 |
</property> |
1185 | 1186 |
</action> |
1187 |
<action name="actionRecognizeTable"> |
|
1188 |
<property name="icon"> |
|
1189 |
<iconset resource="../res/MainWindow.qrc"> |
|
1190 |
<normaloff>:/newPrefix/table_ocr.png</normaloff>:/newPrefix/table_ocr.png</iconset> |
|
1191 |
</property> |
|
1192 |
<property name="text"> |
|
1193 |
<string>Recognize Table</string> |
|
1194 |
</property> |
|
1195 |
<property name="toolTip"> |
|
1196 |
<string>Recognize Table</string> |
|
1197 |
</property> |
|
1198 |
<property name="shortcut"> |
|
1199 |
<string>Alt+T</string> |
|
1200 |
</property> |
|
1201 |
</action> |
|
1186 | 1202 |
</widget> |
1187 | 1203 |
<resources> |
1188 | 1204 |
<include location="../res/MainWindow.qrc"/> |
DTI_PID/DTI_PID/res/MainWindow.qrc | ||
---|---|---|
1 | 1 |
<RCC> |
2 | 2 |
<qresource prefix="newPrefix"> |
3 |
<file>table_ocr.png</file> |
|
3 | 4 |
<file>svg.png</file> |
4 | 5 |
<file>zoom_area.png</file> |
5 | 6 |
<file>remove-text.png</file> |
내보내기 Unified diff