개정판 e2ae85c2
issue #480: fixed an error to fail to detect line when symbol is flipped
- Ctrl + Arrow Key : 심볼 이동 빠르게
Change-Id: Ie4125ccb782c93f294d0b3cb9c0437f64f553412
DTI_PID/DTI_PID/AppDocData.py | ||
---|---|---|
3670 | 3670 |
if type in self._symbolType: |
3671 | 3671 |
return self._symbolType[type] |
3672 | 3672 |
|
3673 |
conn = self.project.database.connect() |
|
3674 |
with conn: |
|
3673 |
with self.project.database.connect() as conn: |
|
3675 | 3674 |
try: |
3676 | 3675 |
cursor = conn.cursor() |
3677 | 3676 |
sql = self.project.database.to_sql('SELECT Category FROM SymbolType WHERE [Type] = ?') |
DTI_PID/DTI_PID/Commands/CreateSymbolCommand.py | ||
---|---|---|
1 | 1 |
import os.path |
2 | 2 |
import AbstractCommand |
3 |
|
|
3 | 4 |
try: |
4 | 5 |
from PyQt5.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR |
5 | 6 |
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QCursor |
... | ... | |
14 | 15 |
from AppDocData import AppDocData |
15 | 16 |
import cv2 |
16 | 17 |
import numpy as np |
18 |
|
|
17 | 19 |
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__)))) |
18 | 20 |
import SymbolEditorDialog |
21 |
|
|
19 | 22 |
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + '\\Shapes') |
20 | 23 |
from SymbolSvgItem import SymbolSvgItem |
21 | 24 |
|
25 |
|
|
22 | 26 |
class CreateSymbolCommand(AbstractCommand.AbstractCommand): |
23 |
''' |
|
24 |
@history 2018.05.04 Jeongwoo Add Parameter |
|
25 |
''' |
|
27 |
'''@history 2018.05.04 Jeongwoo Add Parameter''' |
|
28 |
|
|
26 | 29 |
def __init__(self, imageViewer, resultTreeWidget, dirTreeWidget): |
27 | 30 |
super(CreateSymbolCommand, self).__init__(imageViewer) |
28 | 31 |
self.name = 'CreateSymbol' |
29 | 32 |
self.imageViewer.setCursor(QCursor(Qt.CrossCursor)) |
30 | 33 |
self.resultTreeWidget = resultTreeWidget |
31 | 34 |
self.dirTreeWidget = dirTreeWidget |
32 |
|
|
35 |
|
|
33 | 36 |
''' |
34 | 37 |
@brief crop image by rectangle selected by user |
35 | 38 |
@history 2018.05.02 Jeongwoo Init self.offsetX and self.offsetY |
... | ... | |
38 | 41 |
2018.05.04 Jeongwoo Add self.dirTreeWidget.initTreeWidget() |
39 | 42 |
2018.06.08 Jeongwoo Add Parameter on SymbolSvgItem.buildItem() |
40 | 43 |
''' |
44 |
|
|
41 | 45 |
def execute(self, param): |
42 | 46 |
event = param[1] |
43 | 47 |
scenePos = param[2] |
... | ... | |
48 | 52 |
elif 'mouseReleaseEvent' == param[0] and event.button() == Qt.LeftButton: |
49 | 53 |
try: |
50 | 54 |
QGraphicsView.mouseReleaseEvent(self.imageViewer, event) |
51 |
viewBBox = self.imageViewer.zoomStack[-1] if len(self.imageViewer.zoomStack) else self.imageViewer.sceneRect() |
|
55 |
viewBBox = self.imageViewer.zoomStack[-1] if len( |
|
56 |
self.imageViewer.zoomStack) else self.imageViewer.sceneRect() |
|
52 | 57 |
selectionBBox = self.imageViewer.scene.selectionArea().boundingRect().intersected(viewBBox) |
53 | 58 |
if selectionBBox.isValid(): |
54 | 59 |
croppedImage = self.imageViewer.image().copy(selectionBBox.toAlignedRect()) |
55 |
symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self.imageViewer, croppedImage, AppDocData.instance().getCurrentProject()) |
|
60 |
symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self.imageViewer, croppedImage, |
|
61 |
AppDocData.instance().getCurrentProject()) |
|
56 | 62 |
(isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog() |
57 | 63 |
self.dirTreeWidget.initDirTreeWidget() |
58 | 64 |
if isAccepted: |
... | ... | |
65 | 71 |
else: |
66 | 72 |
_chan, w, h = img.shape[::-1] |
67 | 73 |
svg = SymbolSvgItem(svgPath) |
68 |
svg.buildItem(newSym.getName(), newSym.getType(), 0, [selectionBBox.x()+offsetX, selectionBBox.y()+offsetY], [w, h], [float(x) for x in newSym.getOriginalPoint().split(',')], [(float(x.split(',')[0]), float(x.split(',')[1])) for x in newSym.getConnectionPoint().split('/')], newSym.getBaseSymbol(), newSym.getAdditionalSymbol()) |
|
74 |
svg.buildItem(newSym.getName(), newSym.getType(), 0, |
|
75 |
[selectionBBox.x() + offsetX, selectionBBox.y() + offsetY], [w, h], |
|
76 |
[float(x) for x in newSym.getOriginalPoint().split(',')], |
|
77 |
[(float(x.split(',')[0]), float(x.split(',')[1])) for x in |
|
78 |
newSym.getConnectionPoint().split('/')], newSym.getBaseSymbol(), |
|
79 |
newSym.getAdditionalSymbol()) |
|
69 | 80 |
|
70 |
#### lambda param=svg : bind 'svg' object to lambda('param') |
|
71 |
#### If case of 'lambda svg=svg:', function uses the 'svg' value bound to lambda |
|
72 | 81 |
svg.clicked.connect(lambda param=svg: self.resultTreeWidget.findItem(param)) |
73 | 82 |
svg.transfer.onRemoved.connect(self.resultTreeWidget.itemRemoved) |
74 | 83 |
svg.addSvgItemToScene(self.imageViewer.scene) |
... | ... | |
85 | 94 |
pass |
86 | 95 |
|
87 | 96 |
def redo(self): |
88 |
pass |
|
97 |
pass |
DTI_PID/DTI_PID/LineDetector.py | ||
---|---|---|
174 | 174 |
return -1 for thickness if fail to calculate thickness |
175 | 175 |
""" |
176 | 176 |
from AppDocData import AppDocData |
177 |
docData = AppDocData.instance() |
|
178 |
windowSize = docData.getSlidingWindowSize() |
|
177 |
|
|
178 |
app_doc_data = AppDocData.instance() |
|
179 |
windowSize = app_doc_data.getSlidingWindowSize() |
|
179 | 180 |
|
180 | 181 |
try: |
181 | 182 |
white = 255 |
182 | 183 |
black = 0 |
183 | 184 |
|
184 | 185 |
norm = [-dir[1], dir[0]] |
185 |
if black == self._image[pt[1] + round(dir[1] * windowSize[1]), pt[0] + round(dir[0] * windowSize[1])]:
|
|
186 |
if white != self._image[pt[1] + round(dir[1] * windowSize[1]), pt[0] + round(dir[0] * windowSize[1])]:
|
|
186 | 187 |
_pt = [pt[0] + round(dir[0] * windowSize[1]), pt[1] + round(dir[1] * windowSize[1])] |
187 | 188 |
else: |
188 | 189 |
found = False |
189 | 190 |
for step in [1, 2, -1, -2]: |
190 |
if black == self._image[pt[1] + round(dir[1] * windowSize[1] + norm[1] * step),
|
|
191 |
if white != self._image[pt[1] + round(dir[1] * windowSize[1] + norm[1] * step),
|
|
191 | 192 |
pt[0] + round(dir[0] * windowSize[1] + norm[0] * step)]: |
192 | 193 |
_pt = [pt[0] + round(dir[0] * windowSize[1] + norm[0] * step), |
193 | 194 |
pt[1] + round(dir[1] * windowSize[1] + norm[1] * step)] |
... | ... | |
250 | 251 |
# get direction of connector |
251 | 252 |
direction = connector.dir() |
252 | 253 |
if direction is None: |
254 |
# calculate direction of connector |
|
253 | 255 |
dx = connector.sceneConnectPoint[0] - symbol.origin[0] |
254 | 256 |
dy = connector.sceneConnectPoint[1] - symbol.origin[1] |
255 | 257 |
else: |
... | ... | |
268 | 270 |
pt, thickness = self.adjust_start_point(pt, dir) |
269 | 271 |
if thickness != -1: |
270 | 272 |
pool.append([dir, pt, thickness, True if not pool else False]) |
271 |
# print("v") |
|
272 | 273 |
elif abs(dy) < 0.1: # horizontal line |
273 | 274 |
dir = [1 if dx > 0 else -1, 0] |
274 | 275 |
pt = [round(connector.sceneConnectPoint[0] - offsetX), |
... | ... | |
508 | 509 |
"""detect a line along given direction""" |
509 | 510 |
from AppDocData import AppDocData |
510 | 511 |
|
511 |
lineLengthConfigs = AppDocData.instance().getConfigs('Small Line Minimum Length', 'Min Length') |
|
512 |
app_doc_data = AppDocData.instance() |
|
513 |
lineLengthConfigs = app_doc_data.getConfigs('Small Line Minimum Length', 'Min Length') |
|
512 | 514 |
lineMinLength = int(lineLengthConfigs[0].value) if 1 == len(lineLengthConfigs) else 10 |
513 | 515 |
try: |
514 | 516 |
white = [255] |
515 |
windowSize = AppDocData.instance().getSlidingWindowSize()
|
|
517 |
windowSize = app_doc_data.getSlidingWindowSize()
|
|
516 | 518 |
xHalf = round(windowSize[0] * 0.5) |
517 | 519 |
yHalf = round(windowSize[1] * 0.5) |
518 | 520 |
|
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
166 | 166 |
self.verticalLayout.addWidget(self.graphicsView) |
167 | 167 |
|
168 | 168 |
# Add Custom TreeWidget |
169 |
self.dirTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
|
|
170 |
self.dirTreeWidget.header().hide()
|
|
171 |
self.symbolTabVerticalLayout.addWidget(self.dirTreeWidget)
|
|
169 |
self.symbolTreeWidget = SymbolTreeWidget.QSymbolTreeWidget()
|
|
170 |
self.symbolTreeWidget.header().hide()
|
|
171 |
self.symbolTabVerticalLayout.addWidget(self.symbolTreeWidget)
|
|
172 | 172 |
|
173 | 173 |
# Add Custom Property TableWidget |
174 | 174 |
self.propertyTableWidget = SymbolPropertyTableWidget.QSymbolPropertyTableWidget() |
175 | 175 |
self.symbolTabVerticalLayout.addWidget(self.propertyTableWidget) |
176 |
self.dirTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
|
|
176 |
self.symbolTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol)
|
|
177 | 177 |
# add splitter widget |
178 | 178 |
splitter = QSplitter(Qt.Vertical) |
179 |
splitter.addWidget(self.dirTreeWidget)
|
|
179 |
splitter.addWidget(self.symbolTreeWidget)
|
|
180 | 180 |
splitter.addWidget(self.propertyTableWidget) |
181 | 181 |
self.symbolTabVerticalLayout.addWidget(splitter) |
182 | 182 |
# up to here |
... | ... | |
907 | 907 |
self.setWindowTitle(title if title[-1] == '*' else title + '*') |
908 | 908 |
|
909 | 909 |
def onConvertPDFToImage(self): |
910 |
""" |
|
911 |
@brief convert to selected pdf to image |
|
912 |
@author humkyung |
|
913 |
@date 2018.07.09 |
|
914 |
@history Euisung 2018.10.11 hide shell |
|
915 |
""" |
|
910 |
"""convert to selected pdf to image""" |
|
911 |
import os |
|
912 |
|
|
916 | 913 |
try: |
917 |
filePath = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'bin64', 'PDF_TO_IMAGE.exe')
|
|
918 |
subprocess.call(filePath, shell=False)
|
|
914 |
file_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'bin64', 'PDF_TO_IMAGE.exe')
|
|
915 |
os.startfile(file_path)
|
|
919 | 916 |
except Exception as ex: |
920 | 917 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
921 | 918 |
sys.exc_info()[-1].tb_lineno) |
... | ... | |
958 | 955 |
|
959 | 956 |
def onSelectionChanged(self): |
960 | 957 |
"""selection changed""" |
961 |
items = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem) or \
|
|
962 |
type(item) is QEngineeringLineItem or issubclass(type(item), QEngineeringTextItem) or type(
|
|
963 |
item) is QEngineeringUnknownItem or type(item) is QEngineeringVendorItem] |
|
958 |
items = [item for item in self.graphicsView.scene.selectedItems() if issubclass(type(item), SymbolSvgItem) or |
|
959 |
type(item) is QEngineeringLineItem or issubclass(type(item), QEngineeringTextItem) or |
|
960 |
type(item) is QEngineeringUnknownItem or type(item) is QEngineeringVendorItem]
|
|
964 | 961 |
if items: |
965 | 962 |
item = items[-1] |
966 | 963 |
self.itemTreeWidget.findItem(item) |
... | ... | |
970 | 967 |
if self.tableWidgetInconsistency.item(index, 1).tag is item: |
971 | 968 |
self.tableWidgetInconsistency.selectRow(index) |
972 | 969 |
break |
970 |
if issubclass(type(item), SymbolSvgItem): |
|
971 |
self.symbolTreeWidget.select_symbol(item) |
|
973 | 972 |
else: |
974 | 973 |
self.resultPropertyTableWidget.show_item_property(None) |
975 | 974 |
|
... | ... | |
1063 | 1062 |
return |
1064 | 1063 |
if self.actionEquipment.isChecked(): |
1065 | 1064 |
self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget, |
1066 |
self.dirTreeWidget)
|
|
1065 |
self.symbolTreeWidget)
|
|
1067 | 1066 |
else: |
1068 | 1067 |
self.graphicsView.useDefaultCommand() |
1069 | 1068 |
|
... | ... | |
1081 | 1080 |
return |
1082 | 1081 |
if self.actionNozzle.isChecked(): |
1083 | 1082 |
self.graphicsView.command = CreateSymbolCommand.CreateSymbolCommand(self.graphicsView, self.itemTreeWidget, |
1084 |
self.dirTreeWidget)
|
|
1083 |
self.symbolTreeWidget)
|
|
1085 | 1084 |
else: |
1086 | 1085 |
self.graphicsView.useDefaultCommand() |
1087 | 1086 |
|
... | ... | |
1565 | 1564 |
symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, image.copy(x, y, width, height), |
1566 | 1565 |
AppDocData.instance().getCurrentProject()) |
1567 | 1566 |
(isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog() |
1568 |
self.dirTreeWidget.initDirTreeWidget()
|
|
1567 |
self.symbolTreeWidget.initDirTreeWidget()
|
|
1569 | 1568 |
if isAccepted: |
1570 | 1569 |
if isImmediateInsert: |
1571 | 1570 |
svgPath = newSym.getSvgFileFullPath() |
... | ... | |
1833 | 1832 |
dlg.show() |
1834 | 1833 |
elif event.key() == Qt.Key_I: |
1835 | 1834 |
# insert symbol item that is selected symbol in tree to main window if symbol already selected on main window, replace |
1836 |
items = self.dirTreeWidget.selectedItems()
|
|
1835 |
items = self.symbolTreeWidget.selectedItems()
|
|
1837 | 1836 |
if items and hasattr(items[0], 'svgFilePath'): |
1838 |
symData = items[0].data(0, self.dirTreeWidget.TREE_DATA_ROLE)
|
|
1837 |
symData = items[0].data(0, self.symbolTreeWidget.TREE_DATA_ROLE)
|
|
1839 | 1838 |
symName = symData.getName() |
1840 | 1839 |
else: |
1841 | 1840 |
return |
... | ... | |
1855 | 1854 |
|
1856 | 1855 |
if old_symbol: |
1857 | 1856 |
return |
1857 |
elif event.key() == Qt.Key_X: |
|
1858 |
items = self.graphicsView.scene.selectedItems() |
|
1859 |
if items: |
|
1860 |
item = self.symbolTreeWidget.currentItem() |
|
1861 |
if item: |
|
1862 |
self.symbolTreeWidget.showSymbolEditorDialog(item, 0) |
|
1858 | 1863 |
|
1859 | 1864 |
QMainWindow.keyPressEvent(self, event) |
1860 | 1865 |
except Exception as ex: |
... | ... | |
1958 | 1963 |
self.dlg = QRecognitionDialog(self, drawingList, False) |
1959 | 1964 |
self.dlg.exec_() |
1960 | 1965 |
|
1961 |
if appDocData.needReOpening == True:
|
|
1966 |
if appDocData.needReOpening: |
|
1962 | 1967 |
self.itemTreeWidget.setCurrentPID(appDocData.activeDrawing.name) |
1963 | 1968 |
self.drawDetectedItemsToScene() |
1964 | 1969 |
|
DTI_PID/DTI_PID/RecognitionDialog.py | ||
---|---|---|
124 | 124 |
configs = app_doc_data.getConfigs('Small Object Size', 'Max Area') |
125 | 125 |
maxArea = int(configs[0].value) if 1 == len(configs) else 50 |
126 | 126 |
|
127 |
# try to convert grayscale to binary |
|
128 |
image = cv2.threshold(image, 200, 255, cv2.THRESH_BINARY)[1] |
|
129 |
|
|
127 | 130 |
contours, _ = cv2.findContours(image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
128 | 131 |
selectedContours = [] |
129 | 132 |
for contour in contours: |
... | ... | |
219 | 222 |
euisung 2018.11.12 add title block properties |
220 | 223 |
""" |
221 | 224 |
import re |
225 |
import timeit |
|
222 | 226 |
from TextDetector import TextDetector |
223 | 227 |
from Drawing import Drawing |
224 | 228 |
|
... | ... | |
236 | 240 |
|
237 | 241 |
# remove already existing symbol and text |
238 | 242 |
if not batch: |
243 |
listWidget.addItem('Deleting existing items...') |
|
239 | 244 |
items = [item for item in worker.graphicsView.scene.items() if |
240 | 245 |
type(item) is QEngineeringUnknownItem or type(item) is QEngineeringEndBreakItem or |
241 |
type(item) is QEngineeringErrorItem] |
|
246 |
type(item) is QEngineeringErrorItem or type(item) is QGraphicsBoundingBoxItem] |
|
247 |
|
|
242 | 248 |
if worker.isSymbolChecked: |
243 | 249 |
items.extend( |
244 | 250 |
[item for item in worker.graphicsView.scene.items() if issubclass(type(item), SymbolSvgItem)]) |
... | ... | |
247 | 253 |
issubclass(type(item), QEngineeringTextItem)]) |
248 | 254 |
for item in items: |
249 | 255 |
item.transfer.onRemoved.emit(item) |
250 |
# worker.graphicsView.scene.removeItem(item) |
|
251 |
for item in [item for item in worker.graphicsView.scene.items() if |
|
252 |
type(item) is QGraphicsBoundingBoxItem]: |
|
253 |
item.transfer.onRemoved.emit(item) |
|
254 | 256 |
# up to here |
255 | 257 |
|
256 | 258 |
srcList = path |
... | ... | |
312 | 314 |
area.contours, area.hierachy = cv2.findContours(area.not_img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
313 | 315 |
|
314 | 316 |
maxProgressValue = 0 |
315 |
listWidget.addItem("Start recognition : " + mainRes) |
|
317 |
start_time = timeit.default_timer() |
|
318 |
listWidget.addItem(f"Start recognition{str(start_time)} : {mainRes}") |
|
316 | 319 |
threadLock.acquire() |
317 | 320 |
|
318 | 321 |
worker.updateBatchProgress.emit(len(srcList), 1) |
... | ... | |
564 | 567 |
for symbol in app_doc_data.symbols: |
565 | 568 |
matches = [it for it in app_doc_data.symbols if |
566 | 569 |
it is not symbol and symbol.is_connectable(it, toler=toler)] |
567 |
# print(str(symbol)) |
|
568 |
# print(matches) |
|
569 | 570 |
for match in matches: |
570 | 571 |
symbol.connect_if_possible(match) |
571 | 572 |
except Exception as ex: |
... | ... | |
669 | 670 |
items = [item for item in worker.graphicsView.scene.items() if (type(item) is QEngineeringLineItem)] |
670 | 671 |
for item in items: |
671 | 672 |
item.transfer.onRemoved.emit(item) |
672 |
# worker.graphicsView.scene.removeItem(item) |
|
673 | 673 |
# up to here |
674 | 674 |
|
675 | 675 |
# detect line |
... | ... | |
736 | 736 |
targetSymbolList.append(nozzles) |
737 | 737 |
targetSymbolList.append([item for item in symbolList if item not in equipments and item not in nozzles]) |
738 | 738 |
|
739 |
# for i in range(len(targetSymbolList[0])): |
|
740 |
# print(targetSymbolList[0][i].getName()) |
|
741 |
# for i in range(len(targetSymbolList[1])): |
|
742 |
# print(targetSymbolList[1][i].getName()) |
|
743 |
# for i in range(len(targetSymbolList[2])): |
|
744 |
# print(targetSymbolList[2][i].getName()) |
|
745 |
|
|
746 | 739 |
return targetSymbolList |
747 | 740 |
|
748 | 741 |
''' |
... | ... | |
848 | 841 |
roiItemSp = (0, 0) |
849 | 842 |
roiItemEp = (srcWidth, srcHeight) |
850 | 843 |
|
851 |
# For OPC
|
|
844 |
# when text is located inside of symbol
|
|
852 | 845 |
if area is not None and hasInstrumentLabel: |
853 | 846 |
# remove objects smaller than symbol |
854 | 847 |
selected_contours = [] |
... | ... | |
867 | 860 |
# draw contour with white color |
868 | 861 |
roiItem = cv2.drawContours(roiItem, selected_contours, -1, (255, 255, 255), -1) |
869 | 862 |
|
870 |
for index in range(2): |
|
871 |
if index is 0: |
|
872 |
# continue |
|
873 |
pass |
|
874 |
elif detectFlip is not 1 and index is 1: |
|
875 |
continue |
|
876 |
else: |
|
863 |
# try to recognize symbol twice(first one is normal, second on is flipped) |
|
864 |
steps = [False, True] if detectFlip else [False] |
|
865 |
for flipped in steps: |
|
866 |
if flipped: |
|
877 | 867 |
symGray = symGrayOri |
878 | 868 |
symGray = cv2.flip(symGray, 1) |
879 |
# cv2.imwrite('out.png', symGray) |
|
880 |
opx = sow - float(symbolOriginalPoint.split(',')[0]) |
|
881 |
opy = float(symbolOriginalPoint.split(',')[1]) |
|
882 |
symbolOriginalPoint = str(opx) + ',' + str(opy) |
|
883 |
|
|
884 |
symbolConnectionPoint = symbolConnectionPoint.split("/") |
|
885 |
symbolConnectionPointStr = '' |
|
886 |
for strConnPt in symbolConnectionPoint: |
|
887 |
if strConnPt == '': continue |
|
888 |
tokens = strConnPt.split(',') |
|
889 |
|
|
890 |
direction = 'AUTO' |
|
891 |
symbol_idx = '0' |
|
892 |
if len(tokens) == 2: |
|
893 |
cpx = sow - float(tokens[0]) |
|
894 |
cpy = float(tokens[1]) |
|
895 |
cflip = direction + ',' + str(cpx) + ',' + str(cpy) |
|
896 |
elif len(tokens) == 3: |
|
897 |
direction = tokens[0] |
|
898 |
cpx = sow - float(tokens[1]) |
|
899 |
cpy = float(tokens[2]) |
|
900 |
cflip = direction + ',' + str(cpx) + ',' + str(cpy) |
|
901 |
elif len(tokens) >= 4: |
|
902 |
direction = tokens[0] |
|
903 |
cpx = sow - float(tokens[1]) |
|
904 |
cpy = float(tokens[2]) |
|
905 |
symbol_idx = tokens[3] |
|
906 |
cflip = direction + ',' + str(cpx) + ',' + str(cpy) + ',' + str(symbol_idx) |
|
907 |
|
|
908 |
if symbolConnectionPointStr == '': |
|
909 |
symbolConnectionPointStr = cflip |
|
910 |
else: |
|
911 |
symbolConnectionPointStr = symbolConnectionPointStr + '/' + cflip |
|
912 |
symbolConnectionPoint = symbolConnectionPointStr |
|
913 | 869 |
|
914 |
# print(symbolOriginalPoint) |
|
915 |
# print(symbolConnectionPoint) |
|
916 | 870 |
symbolRotatedAngle = 0 |
917 |
for rc in range(symbolRotateCount + 1): # Rotation Count를 사용자 기준으로 받아서 1을 더한 후 사용
|
|
871 |
for rc in range(symbolRotateCount + 1): # Rotation count를 사용자 기준으로 받아서 1을 더한 후 사용
|
|
918 | 872 |
sw, sh = symGray.shape[::-1] |
919 | 873 |
roiw = (roiItemEp[0] - roiItemSp[0]) |
920 | 874 |
roih = (roiItemEp[1] - roiItemSp[1]) |
... | ... | |
930 | 884 |
|
931 | 885 |
# get Rotated Original Point |
932 | 886 |
originalPoint = Worker.getCalculatedOriginalPoint(additionalSymbol, symbolOriginalPoint, |
933 |
symbolRotatedAngle, sw, sh, sow, soh) |
|
887 |
symbolRotatedAngle, sw, sh, sow, soh, flipped)
|
|
934 | 888 |
connectionPoint = Worker.getCalculatedConnectionPoint(symbolConnectionPoint, symbolRotatedAngle, sw, |
935 |
sh, sow, soh) |
|
889 |
sh, sow, soh, flipped)
|
|
936 | 890 |
|
937 | 891 |
# For OPC |
938 | 892 |
drawing_area = app_doc_data.getArea('Drawing') |
... | ... | |
987 | 941 |
isDetectOnOrigin, symbolRotateCount, symbolOcrOption, |
988 | 942 |
isContainChild, |
989 | 943 |
originalPoint, connectionPoint, baseSymbol, additionalSymbol, |
990 |
isExceptDetect, detectFlip=1 if index is 1 else 0, |
|
944 |
isExceptDetect, |
|
945 |
detectFlip=1 if flipped else 0, |
|
991 | 946 |
hasInstrumentLabel=hasInstrumentLabel) |
992 | 947 |
threadLock.release() |
993 | 948 |
else: # 겹치는 영역이 기준값보다 클 경우 |
... | ... | |
1016 | 971 |
connectionPoint), |
1017 | 972 |
baseSymbol, additionalSymbol, |
1018 | 973 |
isExceptDetect, |
1019 |
detectFlip=1 if index is 1 else 0,
|
|
974 |
detectFlip=1 if flipped else 0,
|
|
1020 | 975 |
hasInstrumentLabel=hasInstrumentLabel) |
1021 | 976 |
threadLock.release() |
1022 | 977 |
# 현재 심볼과 검출된 심볼이 같지 않을 경우 (포함) |
... | ... | |
1031 | 986 |
isContainChild, |
1032 | 987 |
originalPoint, connectionPoint, baseSymbol, |
1033 | 988 |
additionalSymbol, isExceptDetect, |
1034 |
detectFlip=1 if index is 1 else 0,
|
|
989 |
detectFlip=1 if flipped else 0,
|
|
1035 | 990 |
hasInstrumentLabel=hasInstrumentLabel) |
1036 | 991 |
threadLock.release() |
1037 | 992 |
# 현재 심볼과 검출된 심볼이 같지 않을 경우 (교체) |
... | ... | |
1057 | 1012 |
connectionPoint), |
1058 | 1013 |
baseSymbol, additionalSymbol, |
1059 | 1014 |
isExceptDetect, |
1060 |
detectFlip=1 if index is 1 else 0,
|
|
1015 |
detectFlip=1 if flipped else 0,
|
|
1061 | 1016 |
hasInstrumentLabel=hasInstrumentLabel) |
1062 | 1017 |
threadLock.release() |
1063 | 1018 |
# 학습용 데이터 생성을 위해 교체하지 않고 추가함 |
... | ... | |
1071 | 1026 |
isContainChild, |
1072 | 1027 |
originalPoint, connectionPoint, baseSymbol, |
1073 | 1028 |
additionalSymbol, isExceptDetect, |
1074 |
detectFlip=1 if index is 1 else 0,
|
|
1029 |
detectFlip=1 if flipped else 0,
|
|
1075 | 1030 |
hasInstrumentLabel=hasInstrumentLabel) |
1076 | 1031 |
threadLock.release() |
1077 | 1032 |
|
... | ... | |
1198 | 1153 |
roiItem = img |
1199 | 1154 |
|
1200 | 1155 |
symbolAngle = 0 |
1201 |
for rc in range(symbolRotateCount + 1): ## Rotation Count를 사용자 기준으로 받아서 1을 더한 후 사용
|
|
1156 |
for rc in range(symbolRotateCount + 1): # Rotation Count를 사용자 기준으로 받아서 1을 더한 후 사용 |
|
1202 | 1157 |
sw, sh = symGray.shape[::-1] |
1203 | 1158 |
roiw = (roiItemEp[0] - roiItemSp[0]) |
1204 | 1159 |
roih = (roiItemEp[1] - roiItemSp[1]) |
1205 | 1160 |
|
1206 |
## get Rotated Original Point
|
|
1161 |
# get Rotated Original Point |
|
1207 | 1162 |
originalPoint = Worker.getCalculatedOriginalPoint(additionalSymbol, symbolOriginalPoint, symbolAngle, |
1208 | 1163 |
sw, sh, sow, soh) |
1209 | 1164 |
connectionPoint = Worker.getCalculatedConnectionPoint(symbolConnectionPoint, symbolAngle, sw, sh, sow, |
... | ... | |
1211 | 1166 |
dx = connectionPoint[0][0] - originalPoint[0] |
1212 | 1167 |
dy = connectionPoint[0][1] - originalPoint[1] |
1213 | 1168 |
|
1214 |
## Template Matching
|
|
1169 |
# Template Matching |
|
1215 | 1170 |
tmRes = cv2.matchTemplate(roiItem, symGray, cv2.TM_CCOEFF_NORMED) |
1216 | 1171 |
loc = np.where(tmRes >= symbolThreshold) |
1217 | 1172 |
|
... | ... | |
1339 | 1294 |
|
1340 | 1295 |
@staticmethod |
1341 | 1296 |
def getCalculatedOriginalPoint(additionalSymbol, symbolOriginalPoint, symbolRotatedAngle, rotateSymbolWidth, |
1342 |
rotateSymbolHeight, originalSymbolWidth, originalSymbolHeight): |
|
1297 |
rotateSymbolHeight, originalSymbolWidth, originalSymbolHeight, flipped=False):
|
|
1343 | 1298 |
res = [] |
1344 | 1299 |
|
1345 | 1300 |
if additionalSymbol is None and symbolOriginalPoint is None: |
1346 | 1301 |
res.append(rotateSymbolWidth // 2) |
1347 | 1302 |
res.append(rotateSymbolHeight // 2) |
1348 | 1303 |
else: |
1349 |
opx = float(symbolOriginalPoint.split(',')[0]) |
|
1350 |
opy = float(symbolOriginalPoint.split(',')[1]) |
|
1304 |
if flipped: |
|
1305 |
opx = originalSymbolWidth - float(symbolOriginalPoint.split(',')[0]) |
|
1306 |
opy = float(symbolOriginalPoint.split(',')[1]) |
|
1307 |
else: |
|
1308 |
opx = float(symbolOriginalPoint.split(',')[0]) |
|
1309 |
opy = float(symbolOriginalPoint.split(',')[1]) |
|
1310 |
|
|
1351 | 1311 |
rPt = Worker.getCoordOnRotatedImage(symbolRotatedAngle, ('AUTO', opx, opy, '0'), originalSymbolWidth, |
1352 | 1312 |
originalSymbolHeight) |
1353 | 1313 |
|
... | ... | |
1364 | 1324 |
|
1365 | 1325 |
@staticmethod |
1366 | 1326 |
def getCalculatedConnectionPoint(symbolConnectionPointStr, symbolRotatedAngle, rotateSymbolWidth, |
1367 |
rotateSymbolHeight, originalSymbolWidth, originalSymbolHeight): |
|
1327 |
rotateSymbolHeight, originalSymbolWidth, originalSymbolHeight, flipped=0):
|
|
1368 | 1328 |
res = [] |
1369 | 1329 |
|
1370 | 1330 |
if symbolConnectionPointStr is not None and symbolConnectionPointStr != '': |
... | ... | |
1374 | 1334 |
|
1375 | 1335 |
direction = 'AUTO' |
1376 | 1336 |
symbol_idx = '0' |
1377 |
if len(tokens) == 2: |
|
1378 |
cpx = float(tokens[0]) |
|
1379 |
cpy = float(tokens[1]) |
|
1380 |
elif len(tokens) == 3: |
|
1381 |
direction = tokens[0] |
|
1382 |
cpx = float(tokens[1]) |
|
1383 |
cpy = float(tokens[2]) |
|
1384 |
elif len(tokens) >= 4: |
|
1385 |
direction = tokens[0] |
|
1386 |
cpx = float(tokens[1]) |
|
1387 |
cpy = float(tokens[2]) |
|
1388 |
symbol_idx = tokens[3] |
|
1337 |
if flipped: |
|
1338 |
converted = {'AUTO': 'AUTO', 'LEFT': 'RIGHT', 'RIGHT': 'LEFT', 'UP': 'UP', 'DOWN': 'DOWN'} |
|
1339 |
|
|
1340 |
if len(tokens) == 2: |
|
1341 |
cpx = originalSymbolWidth - float(tokens[0]) |
|
1342 |
cpy = float(tokens[1]) |
|
1343 |
elif len(tokens) == 3: |
|
1344 |
direction = converted[tokens[0]] |
|
1345 |
cpx = originalSymbolWidth - float(tokens[1]) |
|
1346 |
cpy = float(tokens[2]) |
|
1347 |
elif len(tokens) >= 4: |
|
1348 |
direction = converted[tokens[0]] |
|
1349 |
cpx = originalSymbolWidth - float(tokens[1]) |
|
1350 |
cpy = float(tokens[2]) |
|
1351 |
symbol_idx = tokens[3] |
|
1352 |
else: |
|
1353 |
if len(tokens) == 2: |
|
1354 |
cpx = float(tokens[0]) |
|
1355 |
cpy = float(tokens[1]) |
|
1356 |
elif len(tokens) == 3: |
|
1357 |
direction = tokens[0] |
|
1358 |
cpx = float(tokens[1]) |
|
1359 |
cpy = float(tokens[2]) |
|
1360 |
elif len(tokens) >= 4: |
|
1361 |
direction = tokens[0] |
|
1362 |
cpx = float(tokens[1]) |
|
1363 |
cpy = float(tokens[2]) |
|
1364 |
symbol_idx = tokens[3] |
|
1389 | 1365 |
|
1390 | 1366 |
res.append(Worker.getCoordOnRotatedImage(symbolRotatedAngle, (direction, cpx, cpy, symbol_idx), |
1391 | 1367 |
originalSymbolWidth, originalSymbolHeight)) |
... | ... | |
1402 | 1378 |
''' |
1403 | 1379 |
|
1404 | 1380 |
@staticmethod |
1405 |
def getCoordOnRotatedImage(rAngle, connPt, originImageWidth, originImageHeight):
|
|
1381 |
def getCoordOnRotatedImage(angle, connPt, originImageWidth, originImageHeight):
|
|
1406 | 1382 |
rx = None |
1407 | 1383 |
ry = None |
1408 | 1384 |
|
1409 |
## calculate rotated direction
|
|
1385 |
# calculate rotated direction |
|
1410 | 1386 |
direction = connPt[0] |
1411 | 1387 |
if direction == 'LEFT': |
1412 |
direction = 'DOWN' if rAngle == 90 else 'RIGHT' if rAngle == 180 else 'UP' if rAngle == 270 else direction
|
|
1388 |
direction = 'DOWN' if angle == 90 else 'RIGHT' if angle == 180 else 'UP' if angle == 270 else direction
|
|
1413 | 1389 |
elif direction == 'RIGHT': |
1414 |
direction = 'UP' if rAngle == 90 else 'LEFT' if rAngle == 180 else 'DOWN' if rAngle == 270 else direction
|
|
1390 |
direction = 'UP' if angle == 90 else 'LEFT' if angle == 180 else 'DOWN' if angle == 270 else direction
|
|
1415 | 1391 |
elif direction == 'UP': |
1416 |
direction = 'LEFT' if rAngle == 90 else 'DOWN' if rAngle == 180 else 'RIGHT' if rAngle == 270 else direction
|
|
1392 |
direction = 'LEFT' if angle == 90 else 'DOWN' if angle == 180 else 'RIGHT' if angle == 270 else direction
|
|
1417 | 1393 |
elif direction == 'DOWN': |
1418 |
direction = 'RIGHT' if rAngle == 90 else 'UP' if rAngle == 180 else 'LEFT' if rAngle == 270 else direction
|
|
1419 |
## up to here
|
|
1394 |
direction = 'RIGHT' if angle == 90 else 'UP' if angle == 180 else 'LEFT' if angle == 270 else direction
|
|
1395 |
# up to here |
|
1420 | 1396 |
|
1421 | 1397 |
transform = QTransform() |
1422 |
if rAngle == 90 or rAngle == 270:
|
|
1398 |
if angle == 90 or angle == 270:
|
|
1423 | 1399 |
transform.translate(originImageHeight * 0.5, originImageWidth * 0.5) |
1424 |
elif rAngle == 0 or rAngle == 180:
|
|
1400 |
elif angle == 0 or angle == 180:
|
|
1425 | 1401 |
transform.translate(originImageWidth * 0.5, originImageHeight * 0.5) |
1426 |
transform.rotate(-abs(rAngle))
|
|
1402 |
transform.rotate(-abs(angle))
|
|
1427 | 1403 |
transform.translate(-originImageWidth * 0.5, -originImageHeight * 0.5) |
1428 | 1404 |
point = QPoint(connPt[1], connPt[2]) |
1429 | 1405 |
point = transform.map(point) |
... | ... | |
1446 | 1422 |
def addSearchedSymbol(sName, sType |
1447 | 1423 |
, sp, w, h, threshold, minMatchCount, hitRate, rotatedAngle |
1448 | 1424 |
, isDetectOnOrigin, rotateCount, ocrOption, isContainChild |
1449 |
, originalPoint, connectionPoint, baseSymbol, additionalSymbol, isExceptDetect, detectFlip,
|
|
1450 |
hasInstrumentLabel): |
|
1425 |
, originalPoint, connectionPoint, baseSymbol, additionalSymbol, isExceptDetect, detectFlip |
|
1426 |
, hasInstrumentLabel):
|
|
1451 | 1427 |
global searchedSymbolList |
1452 | 1428 |
|
1453 | 1429 |
newSym = None |
... | ... | |
1458 | 1434 |
','.join(str(x) for x in originalPoint), |
1459 | 1435 |
'/'.join('{},{},{},{}'.format(param[0], param[1], param[2], param[3]) for param in |
1460 | 1436 |
connectionPoint), |
1461 |
baseSymbol, additionalSymbol, isExceptDetect, detectFlip=detectFlip,
|
|
1437 |
baseSymbol, additionalSymbol, isExceptDetect, detectFlip=1 if detectFlip else 0,
|
|
1462 | 1438 |
hasInstrumentLabel=hasInstrumentLabel) |
1463 | 1439 |
|
1464 | 1440 |
searchedSymbolList.append(newSym) |
DTI_PID/DTI_PID/Shapes/SymbolSvgItem.py | ||
---|---|---|
397 | 397 |
return errors |
398 | 398 |
|
399 | 399 |
def includes(self, pt, margin=0): |
400 |
""" |
|
401 |
return True if symbol contains given point else return False |
|
402 |
""" |
|
400 |
"""return True if symbol contains given point else return False""" |
|
403 | 401 |
rect = self.sceneBoundingRect() |
404 | 402 |
allowed_error = 0.1 |
405 | 403 |
|
... | ... | |
621 | 619 |
x = float(tokens[0]) |
622 | 620 |
y = float(tokens[1]) |
623 | 621 |
elif len(tokens) >= 3: |
624 |
direction = tokens[0]
|
|
622 |
direction = connPts[index][0]
|
|
625 | 623 |
x = float(tokens[1]) |
626 | 624 |
y = float(tokens[2]) |
627 | 625 |
if len(tokens) >= 4: |
... | ... | |
641 | 639 |
self.connectors[index].symbol_idx = symbol_idx |
642 | 640 |
self.connectors[index].setPos((x, y)) |
643 | 641 |
self.connectors[index].connectPoint = (x, y) |
644 |
self.connectors[index].sceneConnectPoint = (connPts[index][0], connPts[index][1]) if len(
|
|
645 |
connPts[index]) == 2 else \
|
|
646 |
(connPts[index][1], connPts[index][2]) if len(connPts[index]) == 3 else \
|
|
647 |
(connPts[index][1], connPts[index][2]) if len(connPts[index]) == 4 else None
|
|
642 |
self.connectors[index].sceneConnectPoint = (connPts[index][0], connPts[index][1]) if \
|
|
643 |
len(connPts[index]) == 2 else (connPts[index][1], connPts[index][2]) if \
|
|
644 |
len(connPts[index]) == 3 else (connPts[index][1], connPts[index][2]) if \
|
|
645 |
len(connPts[index]) == 4 else None |
|
648 | 646 |
self.parentSymbol = parentSymbol |
649 | 647 |
self.childSymbol = childSymbol |
650 | 648 |
self.hasInstrumentLabel = hasInstrumentLabel |
... | ... | |
1014 | 1012 |
self.rotateSymbol() |
1015 | 1013 |
elif event.key() == Qt.Key_O and type(self) is not QEngineeringErrorItem: |
1016 | 1014 |
pass |
1017 |
#self.changeStandardPoint() |
|
1018 | 1015 |
elif event.key() == Qt.Key_C and type(self) is not QEngineeringErrorItem: |
1019 | 1016 |
self.changeConnPoint() |
1020 | 1017 |
elif event.key() == Qt.Key_F and type(self) is not QEngineeringErrorItem: |
1021 | 1018 |
self.flipSymbol() |
1022 |
elif event.key() == Qt.Key_X:
|
|
1019 |
elif event.key() == Qt.Key_Return:
|
|
1023 | 1020 |
dialog = QRotateSymbolDialog(None, self.angle, self.origin, self.zValue()) |
1024 | 1021 |
(isAccept, angle, x, y, z) = dialog.showDialog() |
1025 | 1022 |
|
... | ... | |
1027 | 1024 |
self.angle = angle |
1028 | 1025 |
self.loc = [x - self.symbolOrigin[0], y - self.symbolOrigin[1]] |
1029 | 1026 |
self.origin = [x, y] |
1030 |
# scene = self.scene() |
|
1031 |
# scene.removeItem(self) |
|
1032 |
# self.addSvgItemToScene(scene) |
|
1033 | 1027 |
self.rotate(self.getCurrentPoint(), self.angle) |
1034 | 1028 |
self.setZValue(z) |
1035 | 1029 |
elif event.key() == Qt.Key_Escape: |
... | ... | |
1043 | 1037 |
self.setTransform(transform) |
1044 | 1038 |
|
1045 | 1039 |
del self._rotating |
1046 |
elif event.key() == Qt.Key_Up: ### translate up/down/left/right symbol |
|
1047 |
self.loc[1] = self.loc[1] - 1 |
|
1048 |
self.origin[1] = self.origin[1] - 1 |
|
1040 |
elif event.key() == Qt.Key_Up: # translate up/down/left/right symbol |
|
1041 |
modifiers = QApplication.keyboardModifiers() |
|
1042 |
delta = 5 if modifiers == Qt.ControlModifier else 1 |
|
1043 |
|
|
1044 |
self.loc[1] = self.loc[1] - delta |
|
1045 |
self.origin[1] = self.origin[1] - delta |
|
1049 | 1046 |
self.rotate(self.getCurrentPoint(), self.angle) |
1050 | 1047 |
elif event.key() == Qt.Key_Down: |
1051 |
self.loc[1] = self.loc[1] + 1 |
|
1052 |
self.origin[1] = self.origin[1] + 1 |
|
1048 |
modifiers = QApplication.keyboardModifiers() |
|
1049 |
delta = 5 if modifiers == Qt.ControlModifier else 1 |
|
1050 |
|
|
1051 |
self.loc[1] = self.loc[1] + delta |
|
1052 |
self.origin[1] = self.origin[1] + delta |
|
1053 | 1053 |
self.rotate(self.getCurrentPoint(), self.angle) |
1054 | 1054 |
elif event.key() == Qt.Key_Left: |
1055 |
self.loc[0] = self.loc[0] - 1 |
|
1056 |
self.origin[0] = self.origin[0] - 1 |
|
1055 |
modifiers = QApplication.keyboardModifiers() |
|
1056 |
delta = 5 if modifiers == Qt.ControlModifier else 1 |
|
1057 |
|
|
1058 |
self.loc[0] = self.loc[0] - delta |
|
1059 |
self.origin[0] = self.origin[0] - delta |
|
1057 | 1060 |
self.rotate(self.getCurrentPoint(), self.angle) |
1058 | 1061 |
elif event.key() == Qt.Key_Right: |
1059 |
self.loc[0] = self.loc[0] + 1 |
|
1060 |
self.origin[0] = self.origin[0] + 1 |
|
1062 |
modifiers = QApplication.keyboardModifiers() |
|
1063 |
delta = 5 if modifiers == Qt.ControlModifier else 1 |
|
1064 |
|
|
1065 |
self.loc[0] = self.loc[0] + delta |
|
1066 |
self.origin[0] = self.origin[0] + delta |
|
1061 | 1067 |
self.rotate(self.getCurrentPoint(), self.angle) |
1062 |
elif event.key() == Qt.Key_I: |
|
1068 |
elif event.key() == Qt.Key_I or event.key() == Qt.Key_X:
|
|
1063 | 1069 |
from App import App |
1064 | 1070 |
App.mainWnd().keyPressEvent(event) |
1065 | 1071 |
|
... | ... | |
1383 | 1389 |
if component['ConnectionPoint']: |
1384 | 1390 |
for conn_pt in component['ConnectionPoint'].split('/'): |
1385 | 1391 |
tokens = conn_pt.split(',') |
1386 |
connPts.append(('AUTO', float(tokens[0]), float(tokens[1]), '0') if len(tokens) == 2 else \
|
|
1387 |
(tokens[0], float(tokens[1]), float(tokens[2]), '0') if len(tokens) == 3 else \
|
|
1388 |
(tokens[0], float(tokens[1]), float(tokens[2]), tokens[3]))
|
|
1392 |
connPts.append(('AUTO', float(tokens[0]), float(tokens[1]), '0') if len(tokens) == 2 else |
|
1393 |
(tokens[0], float(tokens[1]), float(tokens[2]), '0') if len(tokens) == 3 else
|
|
1394 |
(tokens[0], float(tokens[1]), float(tokens[2]), tokens[3])) |
|
1389 | 1395 |
|
1390 | 1396 |
baseSymbol = dbData.baseSymbol |
1391 | 1397 |
|
... | ... | |
1394 | 1400 |
|
1395 | 1401 |
owner = component['Owner'] if component['Owner'] is not None and component['Owner'] != 'None' else None |
1396 | 1402 |
|
1397 |
#hasInstrumentLabelNode = component['HasInstrumentLabel'] |
|
1398 | 1403 |
hasInstrumentLabel = dbData.hasInstrumentLabel |
1399 | 1404 |
|
1400 | 1405 |
flipLabelNode = component['Flip'] |
DTI_PID/DTI_PID/SymbolTreeWidget.py | ||
---|---|---|
257 | 257 |
os.makedirs(tempDir) |
258 | 258 |
|
259 | 259 |
def showSymbolEditorDialog(self, item, columnNo, display=False): |
260 |
"""pop up symbol editor dialog""" |
|
261 |
|
|
260 | 262 |
try: |
261 | 263 |
sym = self.getSymbolByItemName(item, columnNo) |
262 | 264 |
if sym and display: |
... | ... | |
292 | 294 |
sys.exc_info()[-1].tb_lineno) |
293 | 295 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
294 | 296 |
|
297 |
def select_symbol(self, symbol): |
|
298 |
"""select a tree with given symbol""" |
|
299 |
|
|
300 |
founds = self.findItems(symbol.name, Qt.MatchExactly | Qt.MatchRecursive, 0) |
|
301 |
if founds: |
|
302 |
self.setCurrentItem(founds[0]) |
|
303 |
|
|
295 | 304 |
def itemDoubleClickEvent(self, item, columnNo): |
296 | 305 |
self.isDoubleClicked = True |
297 | 306 |
sym = self.getSymbolByItemName(item, columnNo) |
DTI_PID/DTI_PID/potrace.py | ||
---|---|---|
14 | 14 |
from LineDetector import LineDetector |
15 | 15 |
|
16 | 16 |
# potrace command |
17 |
POTRACE = os.path.dirname(os.path.realpath(__file__)) + '\\potrace.exe'
|
|
17 |
POTRACE = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'potrace.exe')
|
|
18 | 18 |
ADJUST = 10 |
19 | 19 |
|
20 |
def convertImageToSvg(imgFilePath, destFilePath, normalColor, hoverColor): |
|
21 |
thresh = 127
|
|
20 |
def convertImageToSvg(imgFilePath, destFilePath, normalColor, hoverColor, threshold=200):
|
|
21 |
"""convert image to svg file by using potrace"""
|
|
22 | 22 |
|
23 |
image = cv2.imread(imgFilePath, cv2.IMREAD_GRAYSCALE)
|
|
24 |
threshold = cv2.threshold(image, thresh, 255, cv2.THRESH_BINARY)[1] |
|
23 |
image = cv2.imread(imgFilePath, cv2.IMREAD_GRAYSCALE) |
|
24 |
threshold = cv2.threshold(image, threshold, 255, cv2.THRESH_BINARY)[1]
|
|
25 | 25 |
|
26 | 26 |
# convert to bmp binary so that potrace can handle it |
27 | 27 |
retval, buf = cv2.imencode('.bmp', threshold) |
28 |
if retval == False:
|
|
28 |
if not retval:
|
|
29 | 29 |
raise ValueError('Failed to convert into BMP binary data') |
30 | 30 |
# convert buf from numpy.ndarray to bytes |
31 | 31 |
binbmp = buf.tobytes() |
DTI_PID/DTI_PID/symbol.py | ||
---|---|---|
12 | 12 |
class Symbol(SymbolBase): |
13 | 13 |
def __init__(self, sName, sType, sp, width, height, threshold, minMatchCount, hitRate, rotatedAngle |
14 | 14 |
, isDetectOnOrigin, rotationCount, ocrOption, isContainChild = 0 |
15 |
, originalPoint = None, connectionPoint = None, baseSymbol = None, additionalSymbol = None, isExceptDetect = 0, hasInstrumentLabel = 0, uid = None, detectFlip = None): |
|
15 |
, originalPoint = None, connectionPoint = None, baseSymbol = None, additionalSymbol = None |
|
16 |
, isExceptDetect = 0, hasInstrumentLabel = 0, uid = None, detectFlip = None): |
|
16 | 17 |
SymbolBase.__init__(self, sName, sType, threshold, minMatchCount |
17 | 18 |
, isDetectOnOrigin, rotationCount, ocrOption, isContainChild |
18 |
, originalPoint, connectionPoint, baseSymbol, additionalSymbol, isExceptDetect, hasInstrumentLabel, uid, detectFlip=detectFlip) |
|
19 |
, originalPoint, connectionPoint, baseSymbol, additionalSymbol, isExceptDetect |
|
20 |
, hasInstrumentLabel, uid, detectFlip=detectFlip) |
|
19 | 21 |
self.sp = sp |
20 | 22 |
self.width = width |
21 | 23 |
self.height = height |
내보내기 Unified diff