개정판 35eb686f
issue #663: add symbol data merge function
Change-Id: I1fce5d3aecb7ccf354933533e8c5cece81c08625
DTI_PID/DTI_PID/AppDocData.py | ||
---|---|---|
247 | 247 |
try: |
248 | 248 |
project = AppDocData.instance().getCurrentProject() |
249 | 249 |
path = project.getTrainingFilePath() |
250 |
drawingFileList = os.listdir(path)
|
|
251 |
drawingFileList.sort()
|
|
250 |
trainingFileList = os.listdir(path)
|
|
251 |
trainingFileList.sort()
|
|
252 | 252 |
except Exception as ex: |
253 | 253 |
from App import App |
254 | 254 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
255 | 255 |
sys.exc_info()[-1].tb_lineno) |
256 | 256 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
257 | 257 |
|
258 |
return drawingFileList |
|
258 |
return trainingFileList |
|
259 |
|
|
260 |
def getTrainingSymbolFileList(self): |
|
261 |
""" Get Symbol Training file list """ |
|
262 |
try: |
|
263 |
project = AppDocData.instance().getCurrentProject() |
|
264 |
path = project.getTrainingSymbolFilePath() |
|
265 |
symbolTrainingFileList = os.listdir(path) |
|
266 |
symbolTrainingFileList.sort() |
|
267 |
except Exception as ex: |
|
268 |
from App import App |
|
269 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
270 |
sys.exc_info()[-1].tb_lineno) |
|
271 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
272 |
|
|
273 |
return symbolTrainingFileList |
|
259 | 274 |
|
260 | 275 |
''' |
261 | 276 |
@brief Get DB file path in ProgramData |
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
59 | 59 |
from UserInputAttribute import UserInputAttribute |
60 | 60 |
from TextItemFactory import TextItemFactory |
61 | 61 |
from TrainingImageListDialog import QTrainingImageListDialog |
62 |
from TrainingSymbolImageListDialog import QTrainingSymbolImageListDialog |
|
62 | 63 |
from TextDataListDialog import QTextDataListDialog |
63 | 64 |
from ImportTextFromCADDialog import QImportTextFromCADDialog |
64 | 65 |
from SymbolThicknessDialog import QSymbolThicknessDialog |
... | ... | |
252 | 253 |
configs = docData.getAppConfigs('app', 'mode') |
253 | 254 |
if configs and 1 == len(configs) and 'advanced' == configs[0].value: |
254 | 255 |
self.actionOCR_Training.triggered.connect(self.oCRTrainingClicked) |
255 |
self.pushButtonBatchRecognition
|
|
256 |
self.actionSymbol_Training.triggered.connect(self.symbolTrainingClicked)
|
|
256 | 257 |
else: |
257 | 258 |
self.actionOCR_Training.setVisible(False) |
259 |
self.actionSymbol_Training.setVisible(False) |
|
258 | 260 |
self.pushButtonBatchRecognition.setVisible(False) |
259 | 261 |
self.pushButtonCreateSymbol.setVisible(False) |
260 | 262 |
self.pushButtonDetectSymbol.setVisible(False) |
... | ... | |
544 | 546 |
sys.exc_info()[-1].tb_lineno) |
545 | 547 |
self.addMessage.emit(MessageType.Error, message) |
546 | 548 |
|
549 |
|
|
550 |
def symbolTrainingClicked(self): |
|
551 |
try: |
|
552 |
dialog = QTrainingSymbolImageListDialog(self) |
|
553 |
dialog.exec_() |
|
554 |
except Exception as ex: |
|
555 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, |
|
556 |
sys.exc_info()[-1].tb_lineno) |
|
557 |
self.addMessage.emit(MessageType.Error, message) |
|
558 |
|
|
547 | 559 |
''' |
548 | 560 |
@brief show unknownitem's count |
549 | 561 |
@author kyouho |
DTI_PID/DTI_PID/MainWindow_UI.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 | 2 |
|
3 |
# Form implementation generated from reading ui file '.\UI\MainWindow.ui'
|
|
3 |
# Form implementation generated from reading ui file './UI/MainWindow.ui'
|
|
4 | 4 |
# |
5 |
# Created by: PyQt5 UI code generator 5.13.0
|
|
5 |
# Created by: PyQt5 UI code generator 5.11.3
|
|
6 | 6 |
# |
7 | 7 |
# WARNING! All changes made in this file will be lost! |
8 | 8 |
|
9 |
|
|
10 | 9 |
from PyQt5 import QtCore, QtGui, QtWidgets |
11 | 10 |
|
12 |
|
|
13 | 11 |
class Ui_MainWindow(object): |
14 | 12 |
def setupUi(self, MainWindow): |
15 | 13 |
MainWindow.setObjectName("MainWindow") |
... | ... | |
497 | 495 |
self.actionSymbol_Thickness_Reinforcement.setObjectName("actionSymbol_Thickness_Reinforcement") |
498 | 496 |
self.actionExportEqpDatasheet = QtWidgets.QAction(MainWindow) |
499 | 497 |
self.actionExportEqpDatasheet.setObjectName("actionExportEqpDatasheet") |
498 |
self.actionSymbol_Training = QtWidgets.QAction(MainWindow) |
|
499 |
self.actionSymbol_Training.setObjectName("actionSymbol_Training") |
|
500 | 500 |
self.menu.addAction(self.actionOpen) |
501 | 501 |
self.menu.addAction(self.actionArea) |
502 | 502 |
self.menu.addAction(self.actionConfiguration) |
... | ... | |
513 | 513 |
self.menu_2.addAction(self.actionOPCRelation) |
514 | 514 |
self.menu_2.addSeparator() |
515 | 515 |
self.menu_2.addAction(self.actionCodeTable) |
516 |
self.menu_2.addSeparator() |
|
516 | 517 |
self.menu_2.addAction(self.actionOCR_Training) |
518 |
self.menu_2.addAction(self.actionSymbol_Training) |
|
517 | 519 |
self.menu_3.addAction(self.actionImage_Drawing) |
518 | 520 |
self.menu_3.addAction(self.actionViewText) |
519 | 521 |
self.menu_3.addAction(self.actionViewSymbol) |
... | ... | |
663 | 665 |
self.actionSymbol_Thickness_Reinforcement.setText(_translate("MainWindow", "Symbol Thickness Reinforcement")) |
664 | 666 |
self.actionExportEqpDatasheet.setText(_translate("MainWindow", "Export Eqp Datasheet")) |
665 | 667 |
self.actionExportEqpDatasheet.setToolTip(_translate("MainWindow", "Export Equipment Datasheet")) |
668 |
self.actionSymbol_Training.setText(_translate("MainWindow", "Symbol Training")) |
|
669 |
|
|
666 | 670 |
import MainWindow_rc |
671 |
|
|
672 |
if __name__ == "__main__": |
|
673 |
import sys |
|
674 |
app = QtWidgets.QApplication(sys.argv) |
|
675 |
MainWindow = QtWidgets.QMainWindow() |
|
676 |
ui = Ui_MainWindow() |
|
677 |
ui.setupUi(MainWindow) |
|
678 |
MainWindow.show() |
|
679 |
sys.exit(app.exec_()) |
|
680 |
|
DTI_PID/DTI_PID/Project.py | ||
---|---|---|
116 | 116 |
def getTrainingFilePath(self): |
117 | 117 |
return os.path.join(self.getPath(), 'Training') |
118 | 118 |
|
119 |
def getTrainingSymbolFilePath(self): |
|
120 |
""" return symbol training path """ |
|
121 |
return os.path.join(self.getPath(), 'Training_Symbol') |
|
122 |
|
|
119 | 123 |
def get_data_sheet_path(self): |
120 | 124 |
""" return data sheet path """ |
121 | 125 |
|
... | ... | |
172 | 176 |
trainingPath = self.getTrainingFilePath() |
173 | 177 |
if not os.path.exists(trainingPath): |
174 | 178 |
os.makedirs(trainingPath) |
179 |
trainingSymbolPath = self.getTrainingSymbolFilePath() |
|
180 |
if not os.path.exists(trainingSymbolPath): |
|
181 |
os.makedirs(trainingSymbolPath) |
|
175 | 182 |
|
176 | 183 |
path = os.path.join(tempDir, 'Tile') |
177 | 184 |
if not os.path.exists(path): |
DTI_PID/DTI_PID/TrainingEditorDialog.py | ||
---|---|---|
4 | 4 |
from PyQt5.QtCore import * |
5 | 5 |
from PyQt5.QtGui import * |
6 | 6 |
from PyQt5.QtWidgets import * |
7 |
from AppDocData import AppDocData
|
|
7 |
from AppDocData import *
|
|
8 | 8 |
import TrainingEditor_UI |
9 | 9 |
import QtImageViewer |
10 | 10 |
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
DTI_PID/DTI_PID/TrainingImageListDialog.py | ||
---|---|---|
10 | 10 |
from PyQt5.QtCore import * |
11 | 11 |
from PyQt5.QtGui import * |
12 | 12 |
from PyQt5.QtWidgets import * |
13 |
from AppDocData import AppDocData
|
|
13 |
from AppDocData import *
|
|
14 | 14 |
import pytesseract |
15 | 15 |
import TrainingImageList_UI |
16 | 16 |
from TrainingEditorDialog import QTrainingEditorDialog |
... | ... | |
320 | 320 |
grid_size[1] = box[4] |
321 | 321 |
|
322 | 322 |
space = 5 |
323 |
grid_size[0] = grid_size[0] + space*2
|
|
324 |
grid_size[1] = grid_size[1] + space*2
|
|
323 |
grid_size[0] = grid_size[0] + space * 2
|
|
324 |
grid_size[1] = grid_size[1] + space * 2
|
|
325 | 325 |
|
326 | 326 |
dimension = [None, None] |
327 | 327 |
dimension[0] = int(math.sqrt(len(boxes)) + 1) |
DTI_PID/DTI_PID/TrainingSymbolEditorDialog.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 |
import sys |
|
3 |
import os, time, datetime |
|
4 |
from PyQt5.QtCore import * |
|
5 |
from PyQt5.QtGui import * |
|
6 |
from PyQt5.QtWidgets import * |
|
7 |
from AppDocData import * |
|
8 |
import TrainingEditor_UI |
|
9 |
import QtImageViewer |
|
10 |
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
|
11 |
from TrainingBoxItem import QTrainingBoxItem |
|
12 |
import cv2 |
|
13 |
import numpy as np |
|
14 |
from PIL import Image |
|
15 |
import AreaZoomCommand |
|
16 |
import PlaceLineCommand |
|
17 |
|
|
18 |
class QTrainingSymbolEditorDialog(QDialog): |
|
19 |
def __init__(self, parent, trainingImgPath, trainingBoxPath, boundaryOcrData, dateItem, boxItem): |
|
20 |
self.spinBoxFlag = False |
|
21 |
QDialog.__init__(self, parent) |
|
22 |
self.setWindowFlag(Qt.WindowMinMaxButtonsHint) |
|
23 |
|
|
24 |
self.trainingImgPath = trainingImgPath |
|
25 |
self.trainingBoxPath = trainingBoxPath |
|
26 |
self.boundaryOcrData = boundaryOcrData |
|
27 |
self.dateItem = dateItem |
|
28 |
self.boxItem = boxItem |
|
29 |
self.isChanged = False |
|
30 |
|
|
31 |
appDocData = AppDocData.instance() |
|
32 |
project = appDocData.getCurrentProject() |
|
33 |
|
|
34 |
self.ui = TrainingEditor_UI.Ui_TrainingEditorDialog() |
|
35 |
self.ui.setupUi(self) |
|
36 |
|
|
37 |
self.graphicsViewTrainingDrawing = QtImageViewer.QtImageViewer(self) |
|
38 |
self.graphicsViewTrainingDrawing.setParent(self.ui.centralWidget) |
|
39 |
self.graphicsViewTrainingDrawing.useDefaultCommand() |
|
40 |
self.ui.verticalLayoutTrainingDrawing.addWidget(self.graphicsViewTrainingDrawing) |
|
41 |
|
|
42 |
self.graphicsViewZoomDrawing = QGraphicsView(self) |
|
43 |
self.graphicsViewZoomDrawing.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff) |
|
44 |
self.graphicsViewZoomDrawing.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) |
|
45 |
self.graphicsViewZoomDrawing.setParent(self.ui.leftSideWidget) |
|
46 |
self.ui.horizontalLayoutZoomDrawing.addWidget(self.graphicsViewZoomDrawing) |
|
47 |
|
|
48 |
|
|
49 |
# 학습 이미지 읽어서 메인 뷰에 그림, 사이드 뷰에 추가 |
|
50 |
try: |
|
51 |
#trainingImgPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.tif') |
|
52 |
cvImg = cv2.cvtColor(cv2.imread(trainingImgPath), cv2.COLOR_BGR2GRAY) |
|
53 |
blur = cv2.GaussianBlur(cvImg, (5,5),0) |
|
54 |
cvImg = cv2.threshold(cvImg, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1] |
|
55 |
bytesPerLine = cvImg.shape[1] |
|
56 |
image = QImage(cvImg.data, cvImg.shape[1], cvImg.shape[0], bytesPerLine, QImage.Format_Indexed8) |
|
57 |
|
|
58 |
self.graphicsViewTrainingDrawing.setImage(image) |
|
59 |
|
|
60 |
# 사이드 뷰 |
|
61 |
if type(image) is QPixmap: |
|
62 |
pixmap = image |
|
63 |
elif type(image) is QImage: |
|
64 |
pixmap = QPixmap.fromImage(image) |
|
65 |
scene = QGraphicsScene() |
|
66 |
self.graphicsViewZoomDrawing.setScene(scene) |
|
67 |
self._pixmapHandle = self.graphicsViewZoomDrawing.scene().addPixmap(pixmap) |
|
68 |
self.graphicsViewZoomDrawing.scene().setSceneRect(0, 0, pixmap.width(), pixmap.height()) |
|
69 |
self.graphicsViewZoomDrawing.fitInView(self.graphicsViewZoomDrawing.scene().sceneRect(), Qt.KeepAspectRatioByExpanding) |
|
70 |
rect = QGraphicsRectItem(0, 0, 0, 0) |
|
71 |
pen = QPen(Qt.SolidLine) |
|
72 |
pen.setColor(Qt.green) |
|
73 |
pen.setWidthF(1) |
|
74 |
pen.setJoinStyle(Qt.MiterJoin) |
|
75 |
rect.setPen(pen) |
|
76 |
rect.setOpacity(0.7) |
|
77 |
self.graphicsViewZoomDrawing.scene().addItem(rect) |
|
78 |
|
|
79 |
except Exception as ex: |
|
80 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
81 |
|
|
82 |
# 박스 읽어서 메인 뷰에 그림 |
|
83 |
try: |
|
84 |
boxList = [] |
|
85 |
if self.boundaryOcrData is None: |
|
86 |
fBox = open(trainingBoxPath, 'r', encoding='utf8') |
|
87 |
SBox = fBox.read() |
|
88 |
fBox.close() |
|
89 |
boxList = SBox.split('\n') |
|
90 |
else: |
|
91 |
boxList = boundaryOcrData.split('\n') |
|
92 |
|
|
93 |
for box in boxList: |
|
94 |
if box == '': continue |
|
95 |
boxComponent = box.split(' ') |
|
96 |
singleBox = QTrainingBoxItem(str(boxComponent[0]), int(boxComponent[1]), cvImg.shape[0] - int(boxComponent[4]), int(boxComponent[3]) - int(boxComponent[1]), int(boxComponent[4]) - int(boxComponent[2])) |
|
97 |
singleBox.transfer.onRemoved.connect(self.itemRemoved) |
|
98 |
singleBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag) |
|
99 |
except Exception as ex: |
|
100 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
101 |
|
|
102 |
self.removedItems = [] |
|
103 |
|
|
104 |
self.ui.pushButtonZoom.clicked.connect(self.onAreaZoom) |
|
105 |
self.ui.pushButtonSave.clicked.connect(self.pushButtonSaveClicked) |
|
106 |
self.ui.pushButtonCancel.clicked.connect(self.pushButtonCancelClicked) |
|
107 |
self.ui.pushButtonDelete.clicked.connect(self.pushButtonDeleteClicked) |
|
108 |
self.ui.pushButtonAdd.clicked.connect(self.pushButtonAddClicked) |
|
109 |
self.ui.pushButtonSplit.clicked.connect(self.pushButtonSplitClicked) |
|
110 |
self.ui.spinBoxLeft.valueChanged.connect(self.spinBoxChangedEvent) |
|
111 |
self.ui.spinBoxTop.valueChanged.connect(self.spinBoxChangedEvent) |
|
112 |
self.ui.spinBoxWidth.valueChanged.connect(self.spinBoxChangedEvent) |
|
113 |
self.ui.spinBoxHeight.valueChanged.connect(self.spinBoxChangedEvent) |
|
114 |
self.ui.lineEditChar.returnPressed.connect(self.pushButtonChangeClicked) |
|
115 |
|
|
116 |
''' |
|
117 |
@brief split boxitem by button click |
|
118 |
@author euisung |
|
119 |
@date 2018.10.31 |
|
120 |
''' |
|
121 |
def pushButtonSplitClicked(self): |
|
122 |
self.isChanged = True |
|
123 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
|
124 |
if len(items) is not 1: |
|
125 |
return |
|
126 |
rect = items[0].rect() |
|
127 |
secondBox = QTrainingBoxItem('', rect.x() + round(rect.width() / 2), rect.y(), round(rect.width() / 2), rect.height()) |
|
128 |
secondBox.transfer.onRemoved.connect(self.itemRemoved) |
|
129 |
secondBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag) |
|
130 |
items[0].setRect(rect.x(), rect.y(), round(rect.width() / 2), rect.height()) |
|
131 |
|
|
132 |
''' |
|
133 |
@brief add boxitem by button click |
|
134 |
@author euisung |
|
135 |
@date 2018.10.17 |
|
136 |
''' |
|
137 |
def pushButtonAddClicked(self): |
|
138 |
self.isChanged = True |
|
139 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
|
140 |
allItems = self.graphicsViewTrainingDrawing.scene.items() |
|
141 |
totalWidth = 0 |
|
142 |
totalHeight = 0 |
|
143 |
count = 0 |
|
144 |
if len(items) is 1: |
|
145 |
rect = items[0].rect() |
|
146 |
elif len(allItems) > 1: |
|
147 |
for item in allItems: |
|
148 |
if type(item) is QGraphicsPixmapItem: |
|
149 |
x = int(item.boundingRect().width() / 2) |
|
150 |
y = int(item.boundingRect().height()/ 2) |
|
151 |
elif hasattr(item, 'rect'): |
|
152 |
count += 1 |
|
153 |
totalWidth += item.rect().width() |
|
154 |
totalHeight += item.rect().height() |
|
155 |
|
|
156 |
rect = QRectF(x, y, round(totalWidth / count), round(totalHeight / count)) |
|
157 |
else: |
|
158 |
for item in allItems: |
|
159 |
if type(item) is QGraphicsPixmapItem: |
|
160 |
x = int(item.boundingRect().width() / 2) |
|
161 |
y = int(item.boundingRect().height()/ 2) |
|
162 |
rect = QRectF(x, y, 5, 10) |
|
163 |
singleBox = QTrainingBoxItem('', rect.x() + 3, rect.y(), rect.width(), rect.height()) |
|
164 |
singleBox.transfer.onRemoved.connect(self.itemRemoved) |
|
165 |
singleBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag) |
|
166 |
|
|
167 |
''' |
|
168 |
@brief delete boxitem by button click |
|
169 |
@author euisung |
|
170 |
@date 2018.10.17 |
|
171 |
''' |
|
172 |
def pushButtonDeleteClicked(self): |
|
173 |
self.isChanged = True |
|
174 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
|
175 |
for item in items: |
|
176 |
item.transfer.onRemoved.emit(item) |
|
177 |
|
|
178 |
def onCharChanged(self, text): |
|
179 |
""" |
|
180 |
change lineedit's text with given text |
|
181 |
""" |
|
182 |
if text: |
|
183 |
self.ui.lineEditChar.setText(text) |
|
184 |
self.pushButtonChangeClicked() |
|
185 |
|
|
186 |
''' |
|
187 |
@brief change boxitem char by button click |
|
188 |
@author euisung |
|
189 |
@date 2018.10.17 |
|
190 |
''' |
|
191 |
def pushButtonChangeClicked(self): |
|
192 |
self.isChanged = True |
|
193 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
|
194 |
if len(items) is not 1: |
|
195 |
return |
|
196 |
items[0].char = self.ui.lineEditChar.text() |
|
197 |
items[0].textShowBox.setHtml(self.ui.lineEditChar.text()) |
|
198 |
|
|
199 |
''' |
|
200 |
@brief close dialog by button click |
|
201 |
@author euisung |
|
202 |
@date 2018.10.17 |
|
203 |
''' |
|
204 |
def pushButtonCancelClicked(self): |
|
205 |
if self.isChanged: |
|
206 |
reply = QMessageBox.question(self, self.tr('Continue?'), self.tr('Changes may not have been saved.'), QMessageBox.Ignore, QMessageBox.Cancel) |
|
207 |
if reply == QMessageBox.Ignore: |
|
208 |
QDialog.reject(self) |
|
209 |
else: |
|
210 |
QDialog.reject(self) |
|
211 |
|
|
212 |
''' |
|
213 |
@brief save box item by button click |
|
214 |
@author euisung |
|
215 |
@date 2018.10.16 |
|
216 |
''' |
|
217 |
def pushButtonSaveClicked(self): |
|
218 |
items = self.graphicsViewTrainingDrawing.scene.items() |
|
219 |
outBox = "" |
|
220 |
for item in items: |
|
221 |
if type(item) is QGraphicsPixmapItem: |
|
222 |
imgHeight = int(item.boundingRect().height()) |
|
223 |
imgWidth = int(item.boundingRect().width()) |
|
224 |
for item in items: |
|
225 |
if type(item) is QTrainingBoxItem: |
|
226 |
rect = item.rect() |
|
227 |
char, x, y, width, height = item.char, int(rect.x()), int(rect.y()), int(rect.width()), int(rect.height()) |
|
228 |
bx, by, bx2, by2 = str(x), str(imgHeight - y - height), str(x + width), str(imgHeight - y) |
|
229 |
if char == '': |
|
230 |
continue |
|
231 |
outBox += char + " " + bx + " " + by + " " + bx2 + " " + by2 + "\n" |
|
232 |
fw = open(self.trainingBoxPath, 'w') |
|
233 |
fw.write(outBox) |
|
234 |
fw.close() |
|
235 |
modifiedTime = str(datetime.datetime.strptime(time.ctime(os.path.getmtime(self.trainingBoxPath)), "%a %b %d %H:%M:%S %Y")) |
|
236 |
self.dateItem.setText(modifiedTime) |
|
237 |
|
|
238 |
boxContent = outBox.split('\n') |
|
239 |
boxContent = boxContent[:-1] |
|
240 |
boxchars = '' |
|
241 |
for char in boxContent: |
|
242 |
boxchars += char[0] |
|
243 |
self.boxItem.setText(boxchars) |
|
244 |
|
|
245 |
self.isChanged = False |
|
246 |
reply = QMessageBox.information(self, self.tr('Information'), self.tr('Save Success!'), QMessageBox.Ok, QMessageBox.Cancel) |
|
247 |
if reply == QMessageBox.Ok: |
|
248 |
QDialog.reject(self) |
|
249 |
|
|
250 |
''' |
|
251 |
@brief chane box item's rect by button click |
|
252 |
@author euisung |
|
253 |
@date 2018.10.16 |
|
254 |
''' |
|
255 |
def spinBoxChangedEvent(self, event): |
|
256 |
self.isChanged = True |
|
257 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
|
258 |
if (len(items) is not 1) or self.spinBoxFlag: |
|
259 |
return |
|
260 |
spinBoxName = self.sender().objectName() |
|
261 |
rect = items[0].rect() |
|
262 |
bound = self.graphicsViewZoomDrawing.scene().items()[0] |
|
263 |
|
|
264 |
if spinBoxName == 'spinBoxLeft': |
|
265 |
spinBoxValue = self.ui.spinBoxLeft.value() |
|
266 |
items[0].setRect(QRectF(spinBoxValue, rect.y(), rect.width(), rect.height())) |
|
267 |
items[0].textShowBox.setPos(items[0].rect().x() + round(items[0].rect().width() / 3), items[0].rect().y() - round(items[0].rect().height() / 2)) |
|
268 |
elif spinBoxName == 'spinBoxTop': |
|
269 |
spinBoxValue = self.ui.spinBoxTop.value() |
|
270 |
items[0].setRect(QRectF(rect.x(), spinBoxValue, rect.width(), rect.height())) |
|
271 |
items[0].textShowBox.setPos(items[0].rect().x() + round(items[0].rect().width() / 3), items[0].rect().y() - round(items[0].rect().height() / 2)) |
|
272 |
elif spinBoxName == 'spinBoxWidth': |
|
273 |
spinBoxValue = self.ui.spinBoxWidth.value() |
|
274 |
items[0].setRect(QRectF(rect.x(), rect.y(), spinBoxValue, rect.height())) |
|
275 |
items[0].textShowBox.setPos(items[0].rect().x() + round(items[0].rect().width() / 3), items[0].rect().y() - round(items[0].rect().height() / 2)) |
|
276 |
elif spinBoxName == 'spinBoxHeight': |
|
277 |
spinBoxValue = self.ui.spinBoxHeight.value() |
|
278 |
items[0].setRect(QRectF(rect.x(), rect.y(), rect.width(), spinBoxValue)) |
|
279 |
items[0].textShowBox.setPos(items[0].rect().x() + round(items[0].rect().width() / 3), items[0].rect().y() - round(items[0].rect().height() / 2)) |
|
280 |
|
|
281 |
rect = items[0].rect() |
|
282 |
bound.setRect(rect) |
|
283 |
rectSide = QRectF(rect.x() - 3, rect.y() - 3, rect.width() + 6, rect.height() + 6) |
|
284 |
self.graphicsViewZoomDrawing.fitInView(rectSide) |
|
285 |
self.graphicsViewTrainingDrawing.scene.update() |
|
286 |
|
|
287 |
def onAreaZoom(self, action): |
|
288 |
if self.ui.pushButtonZoom.isChecked(): |
|
289 |
cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsViewTrainingDrawing) |
|
290 |
cmd.onRejected.connect(self.onCommandRejected) |
|
291 |
self.graphicsViewTrainingDrawing.command = cmd |
|
292 |
|
|
293 |
def onCommandRejected(self, cmd): |
|
294 |
try: |
|
295 |
if type(cmd) is AreaZoomCommand.AreaZoomCommand: |
|
296 |
self.ui.pushButtonZoom.setChecked(False) |
|
297 |
finally: |
|
298 |
self.graphicsViewTrainingDrawing.useDefaultCommand() |
|
299 |
|
|
300 |
def itemRemoved(self, item): |
|
301 |
try: |
|
302 |
if type(item) is QTrainingBoxItem: |
|
303 |
self.removedItems.append(str(item.uid)) |
|
304 |
|
|
305 |
if item.scene is not None: item.scene.removeItem(item) |
|
306 |
except Exception as ex: |
|
307 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
308 |
|
|
309 |
''' |
|
310 |
@brief key pressed event |
|
311 |
@author euisung |
|
312 |
@date 2018.11.05 |
|
313 |
''' |
|
314 |
def keyPressEvent(self, event): |
|
315 |
try: |
|
316 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
|
317 |
if len(items) is not 1 or type(items[0]) is not QTrainingBoxItem: |
|
318 |
return |
|
319 |
selectedItem = items[0] |
|
320 |
closestItem = None |
|
321 |
x = selectedItem.rect().x() |
|
322 |
|
|
323 |
if event.key() == Qt.Key_Left: |
|
324 |
dx = sys.maxsize |
|
325 |
for item in self.graphicsViewTrainingDrawing.scene.items(): |
|
326 |
if type(item) is QTrainingBoxItem: |
|
327 |
if x - item.rect().x() > 0 and x - item.rect().x() < dx: |
|
328 |
closestItem = item |
|
329 |
dx = x - item.rect().x() |
|
330 |
if closestItem is not None: |
|
331 |
closestItem.setSelected(True) |
|
332 |
selectedItem.setSelected(False) |
|
333 |
closestItem.mousePressEvent('arrow key') |
|
334 |
elif event.key() == Qt.Key_Right: |
|
335 |
dx = -sys.maxsize |
|
336 |
for item in self.graphicsViewTrainingDrawing.scene.items(): |
|
337 |
if type(item) is QTrainingBoxItem: |
|
338 |
if x - item.rect().x() < 0 and x - item.rect().x() > dx: |
|
339 |
closestItem = item |
|
340 |
dx = x - item.rect().x() |
|
341 |
if closestItem is not None: |
|
342 |
closestItem.setSelected(True) |
|
343 |
selectedItem.setSelected(False) |
|
344 |
closestItem.mousePressEvent('arrow key') |
|
345 |
elif event.key() == Qt.Key_Up: |
|
346 |
self.ui.spinBoxWidth.setValue(self.ui.spinBoxWidth.value() + 1) |
|
347 |
elif event.key() == Qt.Key_Down: |
|
348 |
self.ui.spinBoxWidth.setValue(self.ui.spinBoxWidth.value() - 1) |
|
349 |
elif event.key() == Qt.Key_Return: |
|
350 |
pass |
|
351 |
elif selectedItem: |
|
352 |
text = event.text() |
|
353 |
if text: self.onCharChanged(text) |
|
354 |
except Exception as ex: |
|
355 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
356 |
from App import App |
|
357 |
from AppDocData import MessageType |
|
358 |
|
|
359 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
360 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
361 |
return None |
DTI_PID/DTI_PID/TrainingSymbolImageListDialog.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 |
""" This is symbol training image list dialog module """ |
|
3 |
|
|
4 |
import sys |
|
5 |
import os, time, datetime, copy |
|
6 |
from PyQt5.QtCore import * |
|
7 |
from PyQt5.QtGui import * |
|
8 |
from PyQt5.QtWidgets import * |
|
9 |
from AppDocData import * |
|
10 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse |
|
11 |
import TrainingSymbolImageList_UI |
|
12 |
from TrainingSymbolEditorDialog import QTrainingSymbolEditorDialog |
|
13 |
import numpy as np |
|
14 |
import pyqtgraph as pg |
|
15 |
import cv2 |
|
16 |
|
|
17 |
#// for remove noise |
|
18 |
#noisePassList = ['.', '\"', '\'', ',', '`', '-', '+'] |
|
19 |
|
|
20 |
class QTrainingSymbolImageListDialog(QDialog): |
|
21 |
""" |
|
22 |
This is training image list dialog class |
|
23 |
""" |
|
24 |
TRAINING_DATA_COUNT = 5 |
|
25 |
|
|
26 |
def __init__(self, parent): |
|
27 |
QDialog.__init__(self, parent) |
|
28 |
self.setWindowFlag(Qt.WindowMinMaxButtonsHint) |
|
29 |
|
|
30 |
self.ui = TrainingSymbolImageList_UI.Ui_TraingingSymbolImageListDialog() |
|
31 |
self.ui.setupUi(self) |
|
32 |
self.ui.progressBar.setValue(0) |
|
33 |
self.labelList = [] |
|
34 |
|
|
35 |
# for List |
|
36 |
self.ui.tableWidgetList.setSelectionMode(QAbstractItemView.SingleSelection) |
|
37 |
self.ui.tableWidgetList.setColumnCount(4) |
|
38 |
|
|
39 |
## column header 명 설정 |
|
40 |
self.ui.tableWidgetList.setHorizontalHeaderLabels([self.tr('No.'), self.tr('Image List'), self.tr('Modified Date'), self.tr('Label Contents')]) |
|
41 |
self.ui.tableWidgetList.horizontalHeaderItem(1).setToolTip(self.tr('Image Name')) # header tooltip |
|
42 |
self.ui.tableWidgetList.horizontalHeaderItem(2).setToolTip(self.tr('Edit Status')) # header tooltip |
|
43 |
self.ui.tableWidgetList.horizontalHeaderItem(3).setToolTip(self.tr('Label Contents')) # header tooltip |
|
44 |
self.ui.tableWidgetList.horizontalHeaderItem(1).setSizeHint(QSize(30, 30)) |
|
45 |
self.ui.tableWidgetList.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents) |
|
46 |
self.ui.tableWidgetList.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) |
|
47 |
self.ui.tableWidgetList.horizontalHeader().setSectionResizeMode(2, QHeaderView.Stretch) |
|
48 |
self.ui.tableWidgetList.horizontalHeader().setSectionResizeMode(3, QHeaderView.Stretch) |
|
49 |
self.ui.tableWidgetList.resizeColumnsToContents() |
|
50 |
self.ui.tableWidgetList.setEditTriggers(QAbstractItemView.NoEditTriggers) |
|
51 |
|
|
52 |
self.listUpdate() |
|
53 |
|
|
54 |
# connect signals and slots |
|
55 |
self.ui.tableWidgetList.cellDoubleClicked.connect(self.listCellDoubleClicked) |
|
56 |
self.ui.pushButtonLabel.clicked.connect(self.pushButtonLabelClicked) |
|
57 |
self.ui.pushButtonMakeTrainingImage.clicked.connect(self.makeTrainingImageClicked) |
|
58 |
self.ui.pushButtonImageDelete.clicked.connect(self.pushButtonImageDeleteClicked) |
|
59 |
self.ui.pushButtonLabelDelete.clicked.connect(self.pushButtonLabelDeleteClicked) |
|
60 |
self.ui.pushButtonClose.clicked.connect(self.pushButtonCloseClicked) |
|
61 |
self.ui.pushButtonDeleteBatchLabel.clicked.connect(self.pushButtonDeleteBatchLabelClicked) |
|
62 |
|
|
63 |
# delete character in box |
|
64 |
#self.ui.pushButtonDeleteBatchLabel.setEnabled(False) |
|
65 |
#self.ui.pushButtonDeleteBatchLabel.setHidden(True) |
|
66 |
#self.ui.lineEditTargetLabel.setEnabled(False) |
|
67 |
#self.ui.lineEditTargetLabel.setHidden(True) |
|
68 |
self.ui.pushButtonDeleteBatchLabel.setEnabled(True) |
|
69 |
self.ui.pushButtonDeleteBatchLabel.setHidden(False) |
|
70 |
self.ui.lineEditTargetLabel.setEnabled(True) |
|
71 |
self.ui.lineEditTargetLabel.setHidden(False) |
|
72 |
|
|
73 |
appDocData = AppDocData.instance() |
|
74 |
project = appDocData.getCurrentProject() |
|
75 |
dataList = appDocData.getTrainingSymbolFileList() |
|
76 |
|
|
77 |
# for reset chart |
|
78 |
self.labelList = [] |
|
79 |
for labelCounts in self.labelList: |
|
80 |
labelCount = [labelCounts[0], labelCounts[1]] |
|
81 |
self.labelList.append(labelCount) |
|
82 |
for data in dataList: |
|
83 |
if data.find('.xml') is not -1: |
|
84 |
labelPath = os.path.join(project.getTrainingSymbolFilePath(), data) |
|
85 |
xml = parse(labelPath) |
|
86 |
root = xml.getroot() |
|
87 |
objects = list(root.iter('object')) |
|
88 |
for object_node in objects: |
|
89 |
name = object_node.find('name').text |
|
90 |
matches = [_label for _label in self.labelList if _label[0] == name] |
|
91 |
if matches: |
|
92 |
matches[0][1] = matches[0][1] + 1 |
|
93 |
else: |
|
94 |
self.labelList.append([name, 1]) |
|
95 |
self.makeChart() |
|
96 |
|
|
97 |
''' |
|
98 |
@brief close dialog by button click |
|
99 |
@author euisung |
|
100 |
@date 2018.10.18 |
|
101 |
''' |
|
102 |
def pushButtonCloseClicked(self): |
|
103 |
QDialog.reject(self) |
|
104 |
|
|
105 |
''' |
|
106 |
@brief update image list |
|
107 |
@author euisung |
|
108 |
@date 2018.10.18 |
|
109 |
''' |
|
110 |
def listUpdate(self): |
|
111 |
appDocData = AppDocData.instance() |
|
112 |
project = appDocData.getCurrentProject() |
|
113 |
dataList = appDocData.getTrainingSymbolFileList() |
|
114 |
imgCount = 0 |
|
115 |
for data in dataList: |
|
116 |
if data.find('.png') is not -1: |
|
117 |
imgCount += 1 |
|
118 |
self.ui.tableWidgetList.setRowCount(imgCount) |
|
119 |
|
|
120 |
row = 0 |
|
121 |
for data in dataList: |
|
122 |
if data.find('.png') is not -1: |
|
123 |
self.ui.tableWidgetList.setItem(row, 0, QTableWidgetItem(str(row + 1))) |
|
124 |
self.ui.tableWidgetList.setItem(row, 1, QTableWidgetItem(data)) |
|
125 |
allDataList = appDocData.getTrainingSymbolFileList() |
|
126 |
for adata in allDataList: |
|
127 |
labelName = data.replace('.png', '.xml') |
|
128 |
if adata.find(labelName) is not -1: |
|
129 |
labelPath = os.path.join(project.getTrainingSymbolFilePath(), labelName) |
|
130 |
modifiedTime = str(datetime.datetime.strptime(time.ctime(os.path.getmtime(labelPath)), "%a %b %d %H:%M:%S %Y")) |
|
131 |
self.ui.tableWidgetList.setItem(row, 2, QTableWidgetItem(modifiedTime)) |
|
132 |
|
|
133 |
labels = [] |
|
134 |
xml = parse(labelPath) |
|
135 |
root = xml.getroot() |
|
136 |
objects = list(root.iter('object')) |
|
137 |
for object_node in objects: |
|
138 |
name = object_node.find('name').text |
|
139 |
if name not in labels: |
|
140 |
labels.append(name) |
|
141 |
labelContent = QTableWidgetItem(','.join(labels)) |
|
142 |
labelContent.setFont(QFont('Consolas', 9, QFont.Bold)) |
|
143 |
self.ui.tableWidgetList.setItem(row, 3, QTableWidgetItem(labelContent)) |
|
144 |
break |
|
145 |
else: |
|
146 |
self.ui.tableWidgetList.setItem(row, 2, QTableWidgetItem('')) |
|
147 |
self.ui.tableWidgetList.setItem(row, 3, QTableWidgetItem('')) |
|
148 |
row += 1 |
|
149 |
|
|
150 |
''' |
|
151 |
@brief delete training box only by button click |
|
152 |
@author euisung |
|
153 |
@date 2018.10.18 |
|
154 |
''' |
|
155 |
def pushButtonLabelDeleteClicked(self): |
|
156 |
try: |
|
157 |
row = self.ui.tableWidgetList.selectedIndexes()[0].row() |
|
158 |
col = self.ui.tableWidgetList.selectedIndexes()[0].column() |
|
159 |
drawingName = self.ui.tableWidgetList.item(row, 1).text() |
|
160 |
labelDate = self.ui.tableWidgetList.item(row, 2).text() |
|
161 |
if labelDate == '': |
|
162 |
return |
|
163 |
except Exception as ex: |
|
164 |
pass |
|
165 |
try: |
|
166 |
reply = QMessageBox.question(self, self.tr('Continue?'), self.tr('Are you sure you want to delete the label job? '), QMessageBox.Yes, QMessageBox.Cancel) |
|
167 |
if reply == QMessageBox.Yes: |
|
168 |
appDocData = AppDocData.instance() |
|
169 |
project = appDocData.getCurrentProject() |
|
170 |
|
|
171 |
drawingPath = os.path.join(project.getTrainingSymbolFilePath(), drawingName) |
|
172 |
labelName = drawingPath.replace('.png', '.xml') |
|
173 |
if os.path.isfile(labelName): |
|
174 |
os.remove(labelName) |
|
175 |
self.ui.tableWidgetList.item(row, 2).setText('') |
|
176 |
self.ui.tableWidgetList.item(row, 3).setText('') |
|
177 |
#self.listUpdate() |
|
178 |
except Exception as ex: |
|
179 |
from App import App |
|
180 |
from AppDocData import MessageType |
|
181 |
|
|
182 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
183 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
184 |
|
|
185 |
''' |
|
186 |
@brief delete training image and box by button click |
|
187 |
@author euisung |
|
188 |
@date 2018.10.18 |
|
189 |
''' |
|
190 |
def pushButtonImageDeleteClicked(self): |
|
191 |
try: |
|
192 |
row = self.ui.tableWidgetList.selectedIndexes()[0].row() |
|
193 |
col = self.ui.tableWidgetList.selectedIndexes()[0].column() |
|
194 |
drawingName = self.ui.tableWidgetList.item(row, 1).text() |
|
195 |
except Exception as ex: |
|
196 |
pass |
|
197 |
try: |
|
198 |
reply = QMessageBox.question(self, self.tr('Continue?'), self.tr('Are you sure you want to delete selected image? '), QMessageBox.Yes, QMessageBox.Cancel) |
|
199 |
if reply == QMessageBox.Yes: |
|
200 |
appDocData = AppDocData.instance() |
|
201 |
project = appDocData.getCurrentProject() |
|
202 |
|
|
203 |
drawingPath = os.path.join(project.getTrainingSymbolFilePath(), drawingName) |
|
204 |
if os.path.isfile(drawingPath): |
|
205 |
os.remove(drawingPath) |
|
206 |
labelName = drawingPath.replace('.png', '.xml') |
|
207 |
if os.path.isfile(labelName): |
|
208 |
os.remove(labelName) |
|
209 |
self.ui.tableWidgetList.removeRow(row) |
|
210 |
#self.listUpdate() |
|
211 |
except Exception as ex: |
|
212 |
from App import App |
|
213 |
from AppDocData import MessageType |
|
214 |
|
|
215 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
216 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
217 |
|
|
218 |
''' |
|
219 |
@brief make training data by button click |
|
220 |
@author euisung |
|
221 |
@date 2018.10.17 |
|
222 |
''' |
|
223 |
def makeTrainingImageClicked(self): |
|
224 |
from PIL import Image |
|
225 |
import math, uuid |
|
226 |
from random import shuffle |
|
227 |
|
|
228 |
try: |
|
229 |
appDocData = AppDocData.instance() |
|
230 |
project = appDocData.getCurrentProject() |
|
231 |
tilePath = os.path.join(project.getTempPath(), 'tile') |
|
232 |
rootList = os.listdir(tilePath) |
|
233 |
|
|
234 |
self.ui.progressBar.setValue(0) |
|
235 |
self.ui.progressBar.setMaximum(len(rootList)) |
|
236 |
|
|
237 |
maxsize = self.ui.spinBox_2.value() |
|
238 |
|
|
239 |
for root in rootList: |
|
240 |
images = [] |
|
241 |
|
|
242 |
rootPath = os.path.join(tilePath, root) |
|
243 |
imgList = os.listdir(rootPath) |
|
244 |
for img in imgList: |
|
245 |
imgPath = os.path.join(rootPath, img) |
|
246 |
|
|
247 |
img = Image.open(imgPath) |
|
248 |
images.append([img, imgPath]) |
|
249 |
|
|
250 |
grid_size = [None, None] |
|
251 |
for img in images: |
|
252 |
if grid_size[0] is None or grid_size[0] < img[0].size[0]: |
|
253 |
grid_size[0] = img[0].size[0] |
|
254 |
if grid_size[1] is None or grid_size[1] < img[0].size[1]: |
|
255 |
grid_size[1] = img[0].size[1] |
|
256 |
space = 5 |
|
257 |
grid_size[0] = grid_size[0] + space * 2 |
|
258 |
grid_size[1] = grid_size[1] + space * 2 |
|
259 |
|
|
260 |
dimension = [None, None] |
|
261 |
dimension[0] = int(maxsize / grid_size[0]) |
|
262 |
dimension[1] = int(maxsize / grid_size[1]) |
|
263 |
pages = int(len(images) / (dimension[0] * dimension[1])) + 1 |
|
264 |
|
|
265 |
for page in range(pages): |
|
266 |
merged_img = Image.new("RGB", (maxsize, maxsize), (256,256,256)) |
|
267 |
done = False |
|
268 |
for j in range(dimension[1]): |
|
269 |
for i in range(dimension[0]): |
|
270 |
index = (page * dimension[0] * dimension[1]) + j * dimension[0] + i |
|
271 |
if index >= len(images): |
|
272 |
done = True |
|
273 |
break |
|
274 |
|
|
275 |
loc = [i*(grid_size[0]), j*(grid_size[1])] |
|
276 |
label_image = images[index][0] |
|
277 |
|
|
278 |
x = loc[0] + space |
|
279 |
y = loc[1] + space |
|
280 |
|
|
281 |
merged_img.paste(label_image, (x, y, x + label_image.width, y + label_image.height)) |
|
282 |
if done: break |
|
283 |
|
|
284 |
train_image_path = os.path.join(project.getTrainingSymbolFilePath(), str(uuid.uuid4()) + '.png') |
|
285 |
merged_img.save(train_image_path) |
|
286 |
|
|
287 |
except Exception as ex: |
|
288 |
from App import App |
|
289 |
from AppDocData import MessageType |
|
290 |
|
|
291 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
292 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
293 |
return None |
|
294 |
|
|
295 |
try: |
|
296 |
|
|
297 |
QMessageBox.about(self, self.tr("Notice"), self.tr('Successfully applied. ')) |
|
298 |
except Exception as ex: |
|
299 |
from App import App |
|
300 |
from AppDocData import MessageType |
|
301 |
|
|
302 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
303 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
304 |
|
|
305 |
def makeChart(self): |
|
306 |
''' |
|
307 |
@brief make chart for trained charaters |
|
308 |
@author euisung |
|
309 |
@date 2018.11.19 |
|
310 |
''' |
|
311 |
try: |
|
312 |
barList = [] |
|
313 |
categories = [] |
|
314 |
for char in self.labelList: |
|
315 |
categories.append(char[0]) |
|
316 |
barList.append(char[1]) |
|
317 |
|
|
318 |
categoriesDict = [list(zip(range(len(categories)), categories))] |
|
319 |
|
|
320 |
if not hasattr(self, '_winChart'): |
|
321 |
self._winChart = pg.PlotWidget(background = 'w', title = 'Trained Symbols') |
|
322 |
self._winChart.setMouseEnabled(False, False) |
|
323 |
self._plot = pg.BarGraphItem(x = range(len(categories)), height = barList, width = 0.6, brush = 'b') |
|
324 |
self._winChart.addItem(self._plot) |
|
325 |
xax = self._winChart.getAxis('bottom') |
|
326 |
yax = self._winChart.getAxis('left') |
|
327 |
xax.setPen('k') |
|
328 |
yax.setPen('k') |
|
329 |
xax.setTicks(categoriesDict) |
|
330 |
self._winChart.showGrid(x = True, y = True) |
|
331 |
|
|
332 |
self.ui.horizontalLayoutChart.addWidget(self._winChart) |
|
333 |
else: |
|
334 |
self._winChart.removeItem(self._plot) |
|
335 |
|
|
336 |
self._plot = pg.BarGraphItem(x = range(len(categories)), height = barList, width = 0.6, brush = 'b') |
|
337 |
self._winChart.addItem(self._plot) |
|
338 |
xax = self._winChart.getAxis('bottom') |
|
339 |
yax = self._winChart.getAxis('left') |
|
340 |
xax.setPen('k') |
|
341 |
yax.setPen('k') |
|
342 |
xax.setTicks(categoriesDict) |
|
343 |
self._winChart.showGrid(x = True, y = True) |
|
344 |
except Exception as ex: |
|
345 |
from App import App |
|
346 |
from AppDocData import MessageType |
|
347 |
|
|
348 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
349 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
350 |
|
|
351 |
''' |
|
352 |
@brief make Box data by button click |
|
353 |
@author euisung |
|
354 |
@date 2018.10.16 |
|
355 |
''' |
|
356 |
def pushButtonLabelClicked(self): |
|
357 |
from PIL import Image |
|
358 |
|
|
359 |
try: |
|
360 |
row = self.ui.tableWidgetList.selectedIndexes()[0].row() |
|
361 |
col = self.ui.tableWidgetList.selectedIndexes()[0].column() |
|
362 |
drawingName = self.ui.tableWidgetList.item(row, 1).text() |
|
363 |
except: |
|
364 |
return |
|
365 |
|
|
366 |
try: |
|
367 |
appDocData = AppDocData.instance() |
|
368 |
project = appDocData.getCurrentProject() |
|
369 |
|
|
370 |
drawingPath = os.path.join(project.getTrainingSymbolFilePath(), drawingName) |
|
371 |
drawing = Image.open(drawingPath) |
|
372 |
|
|
373 |
labelName = drawingName.replace('.png', '.boxS') |
|
374 |
|
|
375 |
dataList = appDocData.getTrainingSymbolFileList() |
|
376 |
isBoxFile = False |
|
377 |
for data in dataList: |
|
378 |
if data.find(labelName) is not -1: |
|
379 |
isBoxFile = True |
|
380 |
traininglabelPath = os.path.join(project.getTrainingSymbolFilePath(), labelName) |
|
381 |
boundaryOcrData = None |
|
382 |
if not isBoxFile: |
|
383 |
docData = AppDocData.instance() |
|
384 |
### make contour |
|
385 |
|
|
386 |
except Exception as ex: |
|
387 |
from App import App |
|
388 |
from AppDocData import MessageType |
|
389 |
|
|
390 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
391 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
392 |
|
|
393 |
try: |
|
394 |
dialog = QTrainingSymbolEditorDialog(self, drawingPath, traininglabelPath, boundaryOcrData, self.ui.tableWidgetList.item(row, 2), self.ui.tableWidgetList.item(row, 3)) |
|
395 |
dialog.exec_() |
|
396 |
except Exception as ex: |
|
397 |
from App import App |
|
398 |
from AppDocData import MessageType |
|
399 |
|
|
400 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
401 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
402 |
|
|
403 |
return |
|
404 |
|
|
405 |
''' |
|
406 |
@brief add drawing to Selected by button click |
|
407 |
@author euisung |
|
408 |
@date 2018.09.28 |
|
409 |
''' |
|
410 |
def addListClicked(self): |
|
411 |
try: |
|
412 |
row = self.ui.tableWidgetList.selectedIndexes()[0].row() |
|
413 |
col = self.ui.tableWidgetList.selectedIndexes()[0].column() |
|
414 |
self.listCellDoubleClicked(row, col) |
|
415 |
except Exception as ex: |
|
416 |
pass |
|
417 |
''' |
|
418 |
@brief delete character in box data as batch |
|
419 |
@author euisung |
|
420 |
@date 2019.02.22 |
|
421 |
''' |
|
422 |
def pushButtonDeleteBatchLabelClicked(self): |
|
423 |
try: |
|
424 |
targetChar = self.ui.lineEditTargetLabel.text() |
|
425 |
if targetChar == '': |
|
426 |
return |
|
427 |
reply = QMessageBox.question(self, self.tr('Continue?'), self.tr('Are you sure you want to delete character "{}" in all box data?\nData can not be restored! '.format(targetChar)), QMessageBox.Yes, QMessageBox.Cancel) |
|
428 |
if reply == QMessageBox.Yes: |
|
429 |
appDocData = AppDocData.instance() |
|
430 |
project = appDocData.getCurrentProject() |
|
431 |
|
|
432 |
drawingPath = project.getTrainingSymbolFilePath() |
|
433 |
boxList = os.listdir(drawingPath) |
|
434 |
nonBoxList = [] |
|
435 |
|
|
436 |
for index in range(len(boxList)): |
|
437 |
if boxList[index][-4:] != 'boxS': |
|
438 |
nonBoxList.append(index) |
|
439 |
|
|
440 |
nonBoxList.sort(reverse=True) |
|
441 |
for index in nonBoxList: |
|
442 |
boxList.pop(index) |
|
443 |
|
|
444 |
for box in boxList: |
|
445 |
labelPath = os.path.join(drawingPath, box) |
|
446 |
fw = open(labelPath, 'r', encoding='utf8') |
|
447 |
labelContent = fw.read() |
|
448 |
fw.close() |
|
449 |
labelContent = labelContent.split('\n')[:-1] |
|
450 |
newlabelContent = [] |
|
451 |
for boxString in labelContent: |
|
452 |
if boxString[0] != targetChar: |
|
453 |
newlabelContent.append(boxString) |
|
454 |
|
|
455 |
outBox = '' |
|
456 |
for boxString in newlabelContent: |
|
457 |
outBox += boxString + '\n' |
|
458 |
fw = open(labelPath, 'w', encoding='utf8') |
|
459 |
fw.write(outBox) |
|
460 |
fw.close() |
|
461 |
|
|
462 |
#self.listUpdate() |
|
463 |
self.ui.lineEditTargetLabel.setText('') |
|
464 |
except Exception as ex: |
|
465 |
from App import App |
|
466 |
from AppDocData import MessageType |
|
467 |
|
|
468 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
469 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
470 |
|
|
471 |
''' |
|
472 |
@brief make Box data by cell double click |
|
473 |
@author euisung |
|
474 |
@date 2018.09.28 |
|
475 |
''' |
|
476 |
def listCellDoubleClicked(self, row, col): |
|
477 |
self.pushButtonLabelClicked() |
|
478 |
|
|
479 |
''' |
|
480 |
@brief key pressed event |
|
481 |
@author euisung |
|
482 |
@date 2018.11.05 |
|
483 |
''' |
|
484 |
def keyPressEvent(self, event): |
|
485 |
try: |
|
486 |
if event.key() == Qt.Key_Delete: |
|
487 |
try: |
|
488 |
col = self.ui.tableWidgetList.selectedIndexes()[0].column() |
|
489 |
if col == 1: |
|
490 |
self.pushButtonImageDeleteClicked() |
|
491 |
elif col == 2: |
|
492 |
self.pushButtonLabelDeleteClicked() |
|
493 |
except Exception as ex: |
|
494 |
pass |
|
495 |
|
|
496 |
QDialog.keyPressEvent(self, event) |
|
497 |
except Exception as ex: |
|
498 |
from App import App |
|
499 |
from AppDocData import MessageType |
|
500 |
|
|
501 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
502 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
503 |
return None |
DTI_PID/DTI_PID/TrainingSymbolImageList_UI.py | ||
---|---|---|
27 | 27 |
self.pushButtonDeleteBatchLabel = QtWidgets.QPushButton(TraingingSymbolImageListDialog) |
28 | 28 |
self.pushButtonDeleteBatchLabel.setObjectName("pushButtonDeleteBatchLabel") |
29 | 29 |
self.horizontalLayout_4.addWidget(self.pushButtonDeleteBatchLabel) |
30 |
self.lineEditTargetChar = QtWidgets.QLineEdit(TraingingSymbolImageListDialog)
|
|
31 |
self.lineEditTargetChar.setMaximumSize(QtCore.QSize(20, 16777215))
|
|
32 |
self.lineEditTargetChar.setMaxLength(1)
|
|
33 |
self.lineEditTargetChar.setObjectName("lineEditTargetChar")
|
|
34 |
self.horizontalLayout_4.addWidget(self.lineEditTargetChar)
|
|
30 |
self.lineEditTargetLabel = QtWidgets.QLineEdit(TraingingSymbolImageListDialog)
|
|
31 |
self.lineEditTargetLabel.setMaximumSize(QtCore.QSize(200, 16777215))
|
|
32 |
self.lineEditTargetLabel.setMaxLength(50)
|
|
33 |
self.lineEditTargetLabel.setObjectName("lineEditTargetLabel")
|
|
34 |
self.horizontalLayout_4.addWidget(self.lineEditTargetLabel)
|
|
35 | 35 |
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) |
36 | 36 |
self.horizontalLayout_4.addItem(spacerItem) |
37 | 37 |
self.pushButtonImageDelete = QtWidgets.QPushButton(TraingingSymbolImageListDialog) |
DTI_PID/DTI_PID/TrainingSymbolListDialog.py | ||
---|---|---|
1 |
import sys |
|
2 |
import os |
|
3 |
from PyQt5.QtCore import * |
|
4 |
from PyQt5.QtGui import * |
|
5 |
from PyQt5.QtWidgets import * |
|
6 |
from AppDocData import AppDocData, Source |
|
7 |
import pytesseract |
|
8 |
import TrainingList_UI |
|
9 |
|
|
10 |
|
|
11 |
pytesseract.pytesseract.tesseract_cmd = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Tesseract-OCR', 'tesseract.exe') |
|
12 |
tesseract_cmd = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Tesseract-OCR', 'tesseract.exe') |
|
13 |
|
|
14 |
DEFAULT_CONF = """ |
|
15 |
--psm 6 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-~.,/!@#$%&*(){}[]<>:;+=?\\"\\' |
|
16 |
""" |
|
17 |
|
|
18 |
class QTrainingListDialog(QDialog): |
|
19 |
|
|
20 |
trainingDataNumber = 0 |
|
21 |
|
|
22 |
def __init__(self, parent): |
|
23 |
QDialog.__init__(self, parent) |
|
24 |
|
|
25 |
self.ui = TrainingList_UI.Ui_TraingingListDialog() |
|
26 |
self.ui.setupUi(self) |
|
27 |
|
|
28 |
# for List |
|
29 |
self.ui.tableWidgetList.setSelectionMode(QAbstractItemView.SingleSelection) |
|
30 |
self.ui.tableWidgetList.setColumnCount(2) |
|
31 |
self.ui.tableWidgetList.setSortingEnabled(True) |
|
32 |
|
|
33 |
docData = AppDocData.instance() |
|
34 |
dataList = docData.getDrawingFileList() |
|
35 |
self.ui.tableWidgetList.setRowCount(len(dataList)) |
|
36 |
|
|
37 |
## column header 명 설정 |
|
38 |
headerLabel = docData.getCurrentProject().getName() |
|
39 |
self.ui.tableWidgetList.setHorizontalHeaderLabels(['No.', headerLabel]) |
|
40 |
self.ui.tableWidgetList.horizontalHeaderItem(1).setToolTip('도면 이름') # header tooltip |
|
41 |
self.ui.tableWidgetList.horizontalHeaderItem(1).setSizeHint(QSize(30, 30)) |
|
42 |
self.ui.tableWidgetList.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents) |
|
43 |
self.ui.tableWidgetList.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) |
|
44 |
self.ui.tableWidgetList.setEditTriggers(QAbstractItemView.NoEditTriggers) |
|
45 |
|
|
46 |
row = 0 |
|
47 |
for data in dataList: |
|
48 |
self.ui.tableWidgetList.setItem(row, 0, QTableWidgetItem(str(row + 1))) |
|
49 |
self.ui.tableWidgetList.setItem(row, 1, QTableWidgetItem(data)) |
|
50 |
row += 1 |
|
51 |
|
|
52 |
# for Selected |
|
53 |
self.ui.tableWidgetSelected.setSelectionMode(QAbstractItemView.SingleSelection) |
|
54 |
self.ui.tableWidgetSelected.setColumnCount(3) |
|
55 |
|
|
56 |
## column header 명 설정 |
|
57 |
headerLabel = docData.getCurrentProject().getName() |
|
58 |
self.ui.tableWidgetSelected.setHorizontalHeaderLabels(['No.', headerLabel, '작업 상태']) |
|
59 |
self.ui.tableWidgetSelected.horizontalHeaderItem(1).setToolTip('도면 이름') # header tooltip |
|
60 |
self.ui.tableWidgetSelected.horizontalHeaderItem(2).setToolTip('작업 상태') # header tooltip |
|
61 |
self.ui.tableWidgetSelected.horizontalHeaderItem(1).setSizeHint(QSize(30, 30)) |
|
62 |
self.ui.tableWidgetSelected.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeToContents) |
|
63 |
self.ui.tableWidgetSelected.horizontalHeader().setSectionResizeMode(1, QHeaderView.Stretch) |
|
64 |
self.ui.tableWidgetSelected.setEditTriggers(QAbstractItemView.NoEditTriggers) |
|
65 |
|
|
66 |
# connect signals and slots |
|
67 |
self.ui.tableWidgetList.cellDoubleClicked.connect(self.listCellDoubleClicked) |
|
68 |
self.ui.pushButtonAddList.clicked.connect(self.addListClicked) |
|
69 |
self.ui.pushButtonMakeTrainingData.clicked.connect(self.makeTrainingDataClicked) |
|
70 |
|
|
71 |
|
|
72 |
''' |
|
73 |
@brief make training data(text image + Box file) by button click |
|
74 |
@author euisung |
|
75 |
@date 2018.09.28 |
|
76 |
''' |
|
77 |
def makeTrainingDataClicked(self): |
|
78 |
from TextDetector import TextDetector |
|
79 |
from PIL import Image |
|
80 |
import cv2, math |
|
81 |
import numpy as np |
|
82 |
|
|
83 |
try: |
|
84 |
row = self.ui.tableWidgetSelected.selectedIndexes()[0].row() |
|
85 |
col = self.ui.tableWidgetSelected.selectedIndexes()[0].column() |
|
86 |
drawingName = self.ui.tableWidgetSelected.item(row, 1).text() |
|
87 |
except: |
|
88 |
return |
|
89 |
|
|
90 |
try: |
|
91 |
appDocData = AppDocData.instance() |
|
92 |
project = appDocData.getCurrentProject() |
|
93 |
textDetector = TextDetector() |
|
94 |
|
|
95 |
drawingPath = os.path.join(project.getDrawingFilePath(), drawingName) |
|
96 |
drawing = Source(Image.open(drawingPath)) |
|
97 |
|
|
98 |
_imgSrc = cv2.cvtColor(cv2.imread(drawingPath), cv2.COLOR_BGR2GRAY) |
|
99 |
blur = cv2.GaussianBlur(_imgSrc , (5,5),0) |
|
100 |
_imgSrc = cv2.threshold(_imgSrc , 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1] |
|
101 |
|
|
102 |
textAreas = textDetector.detectTextAreas(_imgSrc , (0,0)) |
|
103 |
|
|
104 |
areasNumber = len(textAreas) |
|
105 |
print('total text areas : ' + str(areasNumber)) |
|
106 |
maxW, maxH, sumW, sumH, count = 0, 0, 0, 0, 0 |
|
107 |
for textArea in textAreas: |
|
108 |
areaW = textArea.getW() |
|
109 |
areaH = textArea.getH() |
|
110 |
areaA = textArea.getAngle() |
|
111 |
if areaA is 90: |
|
112 |
areaW, areaH = areaH, areaW |
|
113 |
if areaA is not 0 and areaA is not 90: |
|
114 |
continue |
|
115 |
count += 1 |
|
116 |
sumW += areaW |
|
117 |
sumH += areaH |
|
118 |
if maxW < areaW: |
|
119 |
maxW = areaW |
|
120 |
if maxH < areaH: |
|
121 |
maxH = areaH |
|
122 |
|
|
123 |
print('count : ' + str(count)) |
|
124 |
print('max width : ' + str(maxW) + ', max height : ' + str(maxH)) |
|
125 |
argW = sumW / count |
|
126 |
argH = sumH / count |
|
127 |
print('arg width : ' + str(argW) + ', arg height : ' + str(argH)) |
|
128 |
totalArea = math.ceil(argW * argH * count) |
|
129 |
totalBaseWidth = math.ceil(math.sqrt(totalArea)) |
|
130 |
print('total area theory : ' + str(totalArea) + ', total width : ' + str(totalBaseWidth)) |
|
131 |
|
|
132 |
maxLineH, lineW, totalHeight = 0, 0, 0 |
|
133 |
for index in range(0, areasNumber): |
|
134 |
areaW = textAreas[index].getW() |
|
135 |
areaH = textAreas[index].getH() |
|
136 |
areaA = textAreas[index].getAngle() |
|
137 |
if areaA is 90: |
|
138 |
areaW, areaH = areaH, areaW |
|
139 |
if areaA is not 0 and areaA is not 90: |
|
140 |
continue |
|
141 |
|
|
142 |
if maxLineH < areaH: |
|
143 |
maxLineH = areaH |
|
144 |
if lineW + areaW < totalBaseWidth: |
|
145 |
lineW += areaW |
|
146 |
else: |
|
147 |
lineW = areaW |
|
148 |
totalHeight += maxLineH |
|
149 |
totalHeight += maxLineH |
|
150 |
print('total area real : ' + str(totalBaseWidth * totalHeight) +', total width : ' + str(totalBaseWidth) + ', total height : ' + str(totalHeight) + ', ratio : ' + str(totalHeight / totalBaseWidth)) |
|
151 |
|
|
152 |
trainingTextImg = Image.new("RGB", (totalBaseWidth, totalHeight), (256,256,256)) |
|
153 |
maxLineH, lineW, totalHeight, currentX, currentY = 0, 0, 0, 0, 0 |
|
154 |
for index in range(0, areasNumber): |
|
155 |
#print(index) |
|
156 |
areaW = textAreas[index].getW() |
|
157 |
areaH = textAreas[index].getH() |
|
158 |
areaA = textAreas[index].getAngle() |
|
159 |
|
|
160 |
textAreaImg = drawing.source.crop((textAreas[index].getX(), textAreas[index].getY(), textAreas[index].getX() + areaW, textAreas[index].getY() + areaH)) |
|
161 |
|
|
162 |
if areaA is 90: |
|
163 |
areaW, areaH = areaH, areaW |
|
164 |
textAreaImg = textAreaImg.transpose(Image.ROTATE_270) |
|
165 |
if areaA is not 0 and areaA is not 90: |
|
166 |
continue |
|
167 |
|
|
168 |
if maxLineH < areaH: |
|
169 |
maxLineH = areaH |
|
170 |
if lineW + areaW < totalBaseWidth: |
|
171 |
lineW += areaW |
|
172 |
trainingTextImg.paste(textAreaImg, (currentX, currentY, currentX + areaW, currentY + areaH)) |
|
173 |
currentX = lineW |
|
174 |
else: |
|
175 |
lineW = areaW |
|
176 |
totalHeight += maxLineH |
|
177 |
currentX = 0 |
|
178 |
currentY = totalHeight |
|
179 |
trainingTextImg.paste(textAreaImg, (currentX, currentY, currentX + areaW, currentY + areaH)) |
|
180 |
currentX = areaW |
|
181 |
#trainingTextImg.show() |
|
182 |
#trainingTextImg.show() |
|
183 |
boundaryOcrData = pytesseract.image_to_boxes(trainingTextImg, config=DEFAULT_CONF, lang='seed+eng') |
|
184 |
|
|
185 |
trainingImgPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.tif') |
|
186 |
trainingBoxPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.box') |
|
187 |
|
|
188 |
trainingTextImg.save(trainingImgPath, compression='tiff_lzw') |
|
189 |
fw = open(trainingBoxPath, 'w') #파일 있으면 새로 만듬 예외 처리 안됨, 임시 |
|
190 |
fw.write(boundaryOcrData) |
|
191 |
fw.close() |
|
192 |
|
|
193 |
except Exception as ex: |
|
194 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
195 |
return |
|
196 |
|
|
197 |
''' |
|
198 |
@brief add drawing to Selected by button click |
|
199 |
@author euisung |
|
200 |
@date 2018.09.28 |
|
201 |
''' |
|
202 |
def addListClicked(self): |
|
203 |
try: |
|
204 |
row = self.ui.tableWidgetList.selectedIndexes()[0].row() |
|
205 |
col = self.ui.tableWidgetList.selectedIndexes()[0].column() |
|
206 |
self.listCellDoubleClicked(row, col) |
|
207 |
except Exception as ex: |
|
208 |
pass |
|
209 |
return |
|
210 |
|
|
211 |
|
|
212 |
''' |
|
213 |
@brief add drawing to Selected by cell double click |
|
214 |
@author euisung |
|
215 |
@date 2018.09.28 |
|
216 |
''' |
|
217 |
def listCellDoubleClicked(self, row, col): |
|
218 |
#print('row : ' + str(row) + ', col : ' + str(col)) |
|
219 |
rowPosition = self.ui.tableWidgetSelected.rowCount() |
|
220 |
self.ui.tableWidgetSelected.setRowCount(rowPosition + 1) |
|
221 |
|
|
222 |
drawingName = self.ui.tableWidgetList.item(row, 1).text() |
|
223 |
#print(drawingName) |
|
224 |
self.trainingDataNumber = self.trainingDataNumber + 1 |
|
225 |
self.ui.tableWidgetSelected.setItem(rowPosition, 0, QTableWidgetItem(str(self.trainingDataNumber))) |
|
226 |
self.ui.tableWidgetSelected.setItem(rowPosition, 1, QTableWidgetItem(drawingName)) |
|
227 |
self.ui.tableWidgetSelected.setItem(rowPosition, 2, QTableWidgetItem('신규')) |
|
228 |
|
|
229 |
return |
|
230 |
|
|
231 |
|
|
232 |
|
DTI_PID/DTI_PID/UI/MainWindow.ui | ||
---|---|---|
95 | 95 |
<addaction name="actionOPCRelation"/> |
96 | 96 |
<addaction name="separator"/> |
97 | 97 |
<addaction name="actionCodeTable"/> |
98 |
<addaction name="separator"/> |
|
98 | 99 |
<addaction name="actionOCR_Training"/> |
100 |
<addaction name="actionSymbol_Training"/> |
|
99 | 101 |
</widget> |
100 | 102 |
<widget class="QMenu" name="menu_3"> |
101 | 103 |
<property name="title"> |
... | ... | |
1128 | 1130 |
<string>Export Equipment Datasheet</string> |
1129 | 1131 |
</property> |
1130 | 1132 |
</action> |
1133 |
<action name="actionSymbol_Training"> |
|
1134 |
<property name="text"> |
|
1135 |
<string>Symbol Training</string> |
|
1136 |
</property> |
|
1137 |
</action> |
|
1131 | 1138 |
</widget> |
1132 | 1139 |
<resources> |
1133 | 1140 |
<include location="../res/MainWindow.qrc"/> |
DTI_PID/DTI_PID/UI/TrainingSymbolImageList.ui | ||
---|---|---|
35 | 35 |
</widget> |
36 | 36 |
</item> |
37 | 37 |
<item> |
38 |
<widget class="QLineEdit" name="lineEditTargetChar">
|
|
38 |
<widget class="QLineEdit" name="lineEditTargetLabel">
|
|
39 | 39 |
<property name="maximumSize"> |
40 | 40 |
<size> |
41 |
<width>20</width> |
|
41 |
<width>200</width>
|
|
42 | 42 |
<height>16777215</height> |
43 | 43 |
</size> |
44 | 44 |
</property> |
45 | 45 |
<property name="maxLength"> |
46 |
<number>1</number>
|
|
46 |
<number>50</number>
|
|
47 | 47 |
</property> |
48 | 48 |
</widget> |
49 | 49 |
</item> |
... | ... | |
106 | 106 |
</property> |
107 | 107 |
<property name="font"> |
108 | 108 |
<font> |
109 |
<weight>50</weight>
|
|
110 |
<bold>false</bold>
|
|
109 |
<weight>75</weight>
|
|
110 |
<bold>true</bold>
|
|
111 | 111 |
</font> |
112 | 112 |
</property> |
113 | 113 |
<property name="text"> |
내보내기 Unified diff