개정판 0096a1fc
issue #663: done generate symbol image and merged training image and labeling function
Change-Id: Ie1232b9b97cc45b5647f1cab66098367381e2541
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
2317 | 2317 |
|
2318 | 2318 |
imgNot = np.ones(imgDiff.shape, np.uint8) |
2319 | 2319 |
cv2.bitwise_not(imgDiff, imgNot) |
2320 |
imgNot = cv2.erode(imgNot, np.ones((2, 2), np.uint8))
|
|
2320 |
imgNot = cv2.erode(imgNot, np.ones((3, 3), np.uint8))
|
|
2321 | 2321 |
imgNot = cv2.dilate(imgNot, np.ones((10, 10), np.uint8)) |
2322 | 2322 |
|
2323 | 2323 |
contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) |
DTI_PID/DTI_PID/QtImageViewer.py | ||
---|---|---|
422 | 422 |
''' |
423 | 423 |
def keyPressEvent(self, event): |
424 | 424 |
from TrainingEditorDialog import QTrainingEditorDialog |
425 |
from TrainingSymbolEditorDialog import QTrainingSymbolEditorDialog |
|
425 | 426 |
|
426 | 427 |
try: |
427 | 428 |
if event.key() == Qt.Key_Delete: |
... | ... | |
435 | 436 |
if self.command is not None: |
436 | 437 |
self.command.execute(['keyPressEvent', event, []]) |
437 | 438 |
if self.command.isTreated: return |
438 |
if type(self.mainWindow) is QTrainingEditorDialog: |
|
439 |
if type(self.mainWindow) is QTrainingEditorDialog or type(self.mainWindow) is QTrainingSymbolEditorDialog:
|
|
439 | 440 |
self.mainWindow.keyPressEvent(event) |
440 | 441 |
|
441 | 442 |
if event.key() == Qt.Key_Up or event.key() == Qt.Key_Down or event.key() == Qt.Key_Left or event.key() == Qt.Key_Right: |
DTI_PID/DTI_PID/Shapes/TrainingBoxItem.py | ||
---|---|---|
95 | 95 |
self.textShowBox = QGraphicsTextItem(self.char) |
96 | 96 |
self.textShowBox.setFont(QFont('Consolas', 9, QFont.Bold)) |
97 | 97 |
self.textShowBox.setDefaultTextColor(Qt.green) |
98 |
self.textShowBox.setPos(self.rect().x() + round(self.rect().width() / 3), self.rect().y() - round(self.rect().height() / 2)) |
|
98 |
#self.textShowBox.setPos(self.rect().x() + round(self.rect().width() / 3), self.rect().y() - round(self.rect().height() / 2)) |
|
99 |
self.setPosCustom() |
|
99 | 100 |
self.textShowBox.setParentItem(self) |
100 | 101 |
except Exception as ex: |
101 | 102 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
102 | 103 |
|
104 |
def setPosCustom(self): |
|
105 |
self.textShowBox.setPos(self.rect().center().x(), self.rect().center().y()) |
|
106 |
|
|
103 | 107 |
class Transfer(QObject): |
104 | 108 |
onRemoved = pyqtSignal(QGraphicsItem) |
105 | 109 |
|
DTI_PID/DTI_PID/TrainingEditorDialog.py | ||
---|---|---|
50 | 50 |
try: |
51 | 51 |
#trainingImgPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.tif') |
52 | 52 |
cvImg = cv2.cvtColor(cv2.imread(trainingImgPath), cv2.COLOR_BGR2GRAY) |
53 |
blur = cv2.GaussianBlur(cvImg, (5,5),0) |
|
54 | 53 |
cvImg = cv2.threshold(cvImg, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1] |
55 | 54 |
bytesPerLine = cvImg.shape[1] |
56 | 55 |
image = QImage(cvImg.data, cvImg.shape[1], cvImg.shape[0], bytesPerLine, QImage.Format_Indexed8) |
... | ... | |
264 | 263 |
if spinBoxName == 'spinBoxLeft': |
265 | 264 |
spinBoxValue = self.ui.spinBoxLeft.value() |
266 | 265 |
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))
|
|
266 |
items[0].setPosCustom()
|
|
268 | 267 |
elif spinBoxName == 'spinBoxTop': |
269 | 268 |
spinBoxValue = self.ui.spinBoxTop.value() |
270 | 269 |
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))
|
|
270 |
items[0].setPosCustom()
|
|
272 | 271 |
elif spinBoxName == 'spinBoxWidth': |
273 | 272 |
spinBoxValue = self.ui.spinBoxWidth.value() |
274 | 273 |
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))
|
|
274 |
items[0].setPosCustom()
|
|
276 | 275 |
elif spinBoxName == 'spinBoxHeight': |
277 | 276 |
spinBoxValue = self.ui.spinBoxHeight.value() |
278 | 277 |
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))
|
|
278 |
items[0].setPosCustom()
|
|
280 | 279 |
|
281 | 280 |
rect = items[0].rect() |
282 | 281 |
bound.setRect(rect) |
DTI_PID/DTI_PID/TrainingSymbolEditorDialog.py | ||
---|---|---|
5 | 5 |
from PyQt5.QtGui import * |
6 | 6 |
from PyQt5.QtWidgets import * |
7 | 7 |
from AppDocData import * |
8 |
import TrainingEditor_UI |
|
8 |
import TrainingSymbolEditor_UI
|
|
9 | 9 |
import QtImageViewer |
10 | 10 |
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
11 | 11 |
from TrainingBoxItem import QTrainingBoxItem |
... | ... | |
14 | 14 |
from PIL import Image |
15 | 15 |
import AreaZoomCommand |
16 | 16 |
import PlaceLineCommand |
17 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse |
|
17 | 18 |
|
18 | 19 |
class QTrainingSymbolEditorDialog(QDialog): |
19 |
def __init__(self, parent, trainingImgPath, trainingBoxPath, boundaryOcrData, dateItem, boxItem):
|
|
20 |
def __init__(self, parent, trainingImgPath, trainingLabelPath, boundaryLabelData, dateItem, boxItem):
|
|
20 | 21 |
self.spinBoxFlag = False |
21 | 22 |
QDialog.__init__(self, parent) |
22 | 23 |
self.setWindowFlag(Qt.WindowMinMaxButtonsHint) |
23 | 24 |
|
24 | 25 |
self.trainingImgPath = trainingImgPath |
25 |
self.trainingBoxPath = trainingBoxPath
|
|
26 |
self.boundaryOcrData = boundaryOcrData
|
|
26 |
self.trainingLabelPath = trainingLabelPath
|
|
27 |
self.boundaryLabelData = boundaryLabelData
|
|
27 | 28 |
self.dateItem = dateItem |
28 | 29 |
self.boxItem = boxItem |
29 | 30 |
self.isChanged = False |
... | ... | |
31 | 32 |
appDocData = AppDocData.instance() |
32 | 33 |
project = appDocData.getCurrentProject() |
33 | 34 |
|
34 |
self.ui = TrainingEditor_UI.Ui_TrainingEditorDialog()
|
|
35 |
self.ui = TrainingSymbolEditor_UI.Ui_TrainingSymbolEditorDialog()
|
|
35 | 36 |
self.ui.setupUi(self) |
36 | 37 |
|
37 | 38 |
self.graphicsViewTrainingDrawing = QtImageViewer.QtImageViewer(self) |
... | ... | |
50 | 51 |
try: |
51 | 52 |
#trainingImgPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.tif') |
52 | 53 |
cvImg = cv2.cvtColor(cv2.imread(trainingImgPath), cv2.COLOR_BGR2GRAY) |
53 |
blur = cv2.GaussianBlur(cvImg, (5,5),0) |
|
54 | 54 |
cvImg = cv2.threshold(cvImg, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1] |
55 | 55 |
bytesPerLine = cvImg.shape[1] |
56 | 56 |
image = QImage(cvImg.data, cvImg.shape[1], cvImg.shape[0], bytesPerLine, QImage.Format_Indexed8) |
... | ... | |
77 | 77 |
self.graphicsViewZoomDrawing.scene().addItem(rect) |
78 | 78 |
|
79 | 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)) |
|
80 |
from App import App |
|
81 |
from AppDocData import MessageType |
|
82 |
|
|
83 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
84 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
81 | 85 |
|
82 | 86 |
# 박스 읽어서 메인 뷰에 그림 |
83 | 87 |
try: |
84 | 88 |
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') |
|
89 |
if self.boundaryLabelData is None: # already exist label file |
|
90 |
xml = parse(trainingLabelPath) |
|
91 |
root = xml.getroot() |
|
92 |
objects = list(root.iter('object')) |
|
93 |
for object_node in objects: |
|
94 |
name = object_node.find('name').text |
|
95 |
boxNode = object_node.find('bndbox') |
|
96 |
xMin = int(boxNode.find('xmin').text) |
|
97 |
yMin = int(boxNode.find('ymin').text) |
|
98 |
xMax = int(boxNode.find('xmax').text) |
|
99 |
yMax = int(boxNode.find('ymax').text) |
|
100 |
boxList.append([xMin, yMin, xMax - xMin, yMax - yMin, name]) |
|
90 | 101 |
else: |
91 |
boxList = boundaryOcrData.split('\n') |
|
102 |
for data in boundaryLabelData: |
|
103 |
boxList.append([data[0], data[1], data[2], data[3], 'None']) |
|
92 | 104 |
|
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])) |
|
105 |
for label in boxList: |
|
106 |
singleBox = QTrainingBoxItem(label[4], int(label[0]), int(label[1]), int(label[2]), int(label[3])) |
|
97 | 107 |
singleBox.transfer.onRemoved.connect(self.itemRemoved) |
98 | 108 |
singleBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag) |
99 | 109 |
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)) |
|
110 |
from App import App |
|
111 |
from AppDocData import MessageType |
|
101 | 112 |
|
102 |
self.removedItems = [] |
|
113 |
message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
114 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
|
103 | 115 |
|
116 |
# label table |
|
117 |
self.ui.tableWidget.setSelectionMode(QAbstractItemView.SingleSelection) |
|
118 |
self.ui.tableWidget.setColumnCount(1) |
|
119 |
self.ui.tableWidget.setSortingEnabled(True) |
|
120 |
|
|
121 |
self.ui.tableWidget.setHorizontalHeaderLabels([self.tr('Labels')]) |
|
122 |
self.ui.tableWidget.horizontalHeaderItem(0).setSizeHint(QSize(30, 30)) |
|
123 |
self.ui.tableWidget.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch) |
|
124 |
self.ui.tableWidget.resizeColumnsToContents() |
|
125 |
self.ui.tableWidget.setEditTriggers(QAbstractItemView.NoEditTriggers) |
|
126 |
self.ui.tableWidget.verticalHeader().hide() |
|
127 |
|
|
128 |
self.ui.tableWidget.setRowCount(len(parent.labelList)) |
|
129 |
row = 0 |
|
130 |
for label in parent.labelList: |
|
131 |
textWidget = QTableWidgetItem(label[0]) |
|
132 |
self.ui.tableWidget.setItem(row, 0, textWidget) |
|
133 |
row += 1 |
|
134 |
|
|
135 |
self.ui.tableWidget.cellClicked.connect(self.listCellClicked) |
|
104 | 136 |
self.ui.pushButtonZoom.clicked.connect(self.onAreaZoom) |
105 | 137 |
self.ui.pushButtonSave.clicked.connect(self.pushButtonSaveClicked) |
106 | 138 |
self.ui.pushButtonCancel.clicked.connect(self.pushButtonCancelClicked) |
... | ... | |
113 | 145 |
self.ui.spinBoxHeight.valueChanged.connect(self.spinBoxChangedEvent) |
114 | 146 |
self.ui.lineEditChar.returnPressed.connect(self.pushButtonChangeClicked) |
115 | 147 |
|
148 |
self.removedItems = [] |
|
149 |
|
|
150 |
def listCellClicked(self, row, col): |
|
151 |
self.isChanged = True |
|
152 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
|
153 |
if (len(items) is not 1): |
|
154 |
return |
|
155 |
label = self.ui.tableWidget.item(row, col).text() |
|
156 |
self.onCharChanged(label) |
|
157 |
|
|
116 | 158 |
''' |
117 | 159 |
@brief split boxitem by button click |
118 | 160 |
@author euisung |
... | ... | |
193 | 235 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
194 | 236 |
if len(items) is not 1: |
195 | 237 |
return |
196 |
items[0].char = self.ui.lineEditChar.text() |
|
197 |
items[0].textShowBox.setHtml(self.ui.lineEditChar.text()) |
|
238 |
|
|
239 |
label = self.ui.lineEditChar.text() |
|
240 |
if label != '' and label != 'None': |
|
241 |
return |
|
242 |
|
|
243 |
items[0].char = label |
|
244 |
items[0].textShowBox.setHtml(label) |
|
245 |
|
|
246 |
rowCount = self.ui.tableWidget.rowCount() |
|
247 |
for index in range(rowCount): |
|
248 |
if self.ui.tableWidget.item(index, 0).text() == label: |
|
249 |
return |
|
250 |
|
|
251 |
self.ui.tableWidget.setRowCount(rowCount + 1) |
|
252 |
textWidget = QTableWidgetItem(label) |
|
253 |
self.ui.tableWidget.setItem(rowCount, 0, textWidget) |
|
198 | 254 |
|
199 | 255 |
''' |
200 | 256 |
@brief close dialog by button click |
... | ... | |
215 | 271 |
@date 2018.10.16 |
216 | 272 |
''' |
217 | 273 |
def pushButtonSaveClicked(self): |
274 |
xml = Element('annotation') |
|
275 |
SubElement(xml, 'folder').text = 'None' |
|
276 |
SubElement(xml, 'filename').text = os.path.basename(self.trainingImgPath) |
|
277 |
|
|
278 |
pathNode = Element('path') |
|
279 |
pathNode.text = self.trainingImgPath.replace('/', '\\') |
|
280 |
xml.append(pathNode) |
|
281 |
|
|
282 |
sourceNode = Element('source') |
|
283 |
databaseNode = Element('database') |
|
284 |
databaseNode.text = 'Unknown' |
|
285 |
sourceNode.append(databaseNode) |
|
286 |
xml.append(sourceNode) |
|
287 |
|
|
218 | 288 |
items = self.graphicsViewTrainingDrawing.scene.items() |
219 |
outBox = "" |
|
220 | 289 |
for item in items: |
221 | 290 |
if type(item) is QGraphicsPixmapItem: |
222 |
imgHeight = int(item.boundingRect().height()) |
|
223 |
imgWidth = int(item.boundingRect().width()) |
|
291 |
back = item |
|
292 |
break |
|
293 |
|
|
294 |
sizeNode = Element('size') |
|
295 |
widthNode = Element('width') |
|
296 |
widthNode.text = str(int(back.boundingRect().width())) |
|
297 |
sizeNode.append(widthNode) |
|
298 |
heightNode = Element('height') |
|
299 |
heightNode.text = str(int(back.boundingRect().height())) |
|
300 |
sizeNode.append(heightNode) |
|
301 |
depthNode = Element('depth') |
|
302 |
depthNode.text = '3' |
|
303 |
sizeNode.append(depthNode) |
|
304 |
xml.append(sizeNode) |
|
305 |
|
|
306 |
segmentedNode = Element('segmented') |
|
307 |
segmentedNode.text = '0' |
|
308 |
xml.append(segmentedNode) |
|
309 |
|
|
310 |
labelContent = [] |
|
224 | 311 |
for item in items: |
225 | 312 |
if type(item) is QTrainingBoxItem: |
226 | 313 |
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")) |
|
314 |
label, xMin, yMin, xMax, yMax = item.char, int(rect.x()), int(rect.y()), int(rect.x()) + int(rect.width()), int(rect.y()) + int(rect.height()) |
|
315 |
|
|
316 |
if label not in labelContent: |
|
317 |
labelContent.append(label) |
|
318 |
|
|
319 |
objectNode = Element('object') |
|
320 |
nameNode = Element('name') |
|
321 |
nameNode.text = label |
|
322 |
objectNode.append(nameNode) |
|
323 |
poseNode = Element('pose') |
|
324 |
poseNode.text = 'Unspecified' |
|
325 |
objectNode.append(poseNode) |
|
326 |
truncatedNode = Element('truncated') |
|
327 |
truncatedNode.text = '0' |
|
328 |
objectNode.append(truncatedNode) |
|
329 |
difficultNode = Element('difficult') |
|
330 |
difficultNode.text = '0' |
|
331 |
objectNode.append(difficultNode) |
|
332 |
|
|
333 |
bndboxNode = Element('bndbox') |
|
334 |
xminNode = Element('xmin') |
|
335 |
xminNode.text = str(xMin) |
|
336 |
bndboxNode.append(xminNode) |
|
337 |
yminNode = Element('ymin') |
|
338 |
yminNode.text = str(yMin) |
|
339 |
bndboxNode.append(yminNode) |
|
340 |
xmaxNode = Element('xmax') |
|
341 |
xmaxNode.text = str(xMax) |
|
342 |
bndboxNode.append(xmaxNode) |
|
343 |
ymaxNode = Element('ymax') |
|
344 |
ymaxNode.text = str(yMax) |
|
345 |
bndboxNode.append(ymaxNode) |
|
346 |
objectNode.append(bndboxNode) |
|
347 |
|
|
348 |
xml.append(objectNode) |
|
349 |
|
|
350 |
ElementTree(xml).write(self.trainingLabelPath) |
|
351 |
|
|
352 |
modifiedTime = str(datetime.datetime.strptime(time.ctime(os.path.getmtime(self.trainingLabelPath)), "%a %b %d %H:%M:%S %Y")) |
|
236 | 353 |
self.dateItem.setText(modifiedTime) |
237 | 354 |
|
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) |
|
355 |
labels = ','.join(labelContent) |
|
356 |
self.boxItem.setText(labels) |
|
244 | 357 |
|
245 | 358 |
self.isChanged = False |
246 | 359 |
reply = QMessageBox.information(self, self.tr('Information'), self.tr('Save Success!'), QMessageBox.Ok, QMessageBox.Cancel) |
... | ... | |
264 | 377 |
if spinBoxName == 'spinBoxLeft': |
265 | 378 |
spinBoxValue = self.ui.spinBoxLeft.value() |
266 | 379 |
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))
|
|
380 |
items[0].setPosCustom()
|
|
268 | 381 |
elif spinBoxName == 'spinBoxTop': |
269 | 382 |
spinBoxValue = self.ui.spinBoxTop.value() |
270 | 383 |
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))
|
|
384 |
items[0].setPosCustom()
|
|
272 | 385 |
elif spinBoxName == 'spinBoxWidth': |
273 | 386 |
spinBoxValue = self.ui.spinBoxWidth.value() |
274 | 387 |
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))
|
|
388 |
items[0].setPosCustom()
|
|
276 | 389 |
elif spinBoxName == 'spinBoxHeight': |
277 | 390 |
spinBoxValue = self.ui.spinBoxHeight.value() |
278 | 391 |
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))
|
|
392 |
items[0].setPosCustom()
|
|
280 | 393 |
|
281 | 394 |
rect = items[0].rect() |
282 | 395 |
bound.setRect(rect) |
... | ... | |
348 | 461 |
self.ui.spinBoxWidth.setValue(self.ui.spinBoxWidth.value() - 1) |
349 | 462 |
elif event.key() == Qt.Key_Return: |
350 | 463 |
pass |
351 |
elif selectedItem: |
|
352 |
text = event.text() |
|
353 |
if text: self.onCharChanged(text) |
|
354 | 464 |
except Exception as ex: |
355 | 465 |
print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
356 | 466 |
from App import App |
DTI_PID/DTI_PID/TrainingSymbolEditor_UI.py | ||
---|---|---|
8 | 8 |
|
9 | 9 |
from PyQt5 import QtCore, QtGui, QtWidgets |
10 | 10 |
|
11 |
class Ui_TrainingEditorDialog(object): |
|
12 |
def setupUi(self, TrainingEditorDialog): |
|
13 |
TrainingEditorDialog.setObjectName("TrainingEditorDialog")
|
|
14 |
TrainingEditorDialog.resize(1088, 780)
|
|
15 |
self.gridLayout = QtWidgets.QGridLayout(TrainingEditorDialog) |
|
11 |
class Ui_TrainingSymbolEditorDialog(object):
|
|
12 |
def setupUi(self, TrainingSymbolEditorDialog):
|
|
13 |
TrainingSymbolEditorDialog.setObjectName("TrainingSymbolEditorDialog")
|
|
14 |
TrainingSymbolEditorDialog.resize(1130, 780)
|
|
15 |
self.gridLayout = QtWidgets.QGridLayout(TrainingSymbolEditorDialog)
|
|
16 | 16 |
self.gridLayout.setObjectName("gridLayout") |
17 | 17 |
self.verticalLayout_6 = QtWidgets.QVBoxLayout() |
18 | 18 |
self.verticalLayout_6.setObjectName("verticalLayout_6") |
... | ... | |
20 | 20 |
self.horizontalLayout_2.setObjectName("horizontalLayout_2") |
21 | 21 |
self.horizontalLayout = QtWidgets.QHBoxLayout() |
22 | 22 |
self.horizontalLayout.setObjectName("horizontalLayout") |
23 |
self.pushButtonZoom = QtWidgets.QPushButton(TrainingEditorDialog) |
|
23 |
self.pushButtonZoom = QtWidgets.QPushButton(TrainingSymbolEditorDialog)
|
|
24 | 24 |
self.pushButtonZoom.setMinimumSize(QtCore.QSize(64, 32)) |
25 | 25 |
self.pushButtonZoom.setMaximumSize(QtCore.QSize(64, 32)) |
26 | 26 |
self.pushButtonZoom.setCheckable(True) |
27 | 27 |
self.pushButtonZoom.setAutoDefault(False) |
28 | 28 |
self.pushButtonZoom.setObjectName("pushButtonZoom") |
29 | 29 |
self.horizontalLayout.addWidget(self.pushButtonZoom) |
30 |
self.pushButtonAdd = QtWidgets.QPushButton(TrainingEditorDialog) |
|
30 |
self.pushButtonAdd = QtWidgets.QPushButton(TrainingSymbolEditorDialog)
|
|
31 | 31 |
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) |
32 | 32 |
sizePolicy.setHorizontalStretch(0) |
33 | 33 |
sizePolicy.setVerticalStretch(0) |
... | ... | |
38 | 38 |
self.pushButtonAdd.setAutoDefault(False) |
39 | 39 |
self.pushButtonAdd.setObjectName("pushButtonAdd") |
40 | 40 |
self.horizontalLayout.addWidget(self.pushButtonAdd) |
41 |
self.pushButtonDelete = QtWidgets.QPushButton(TrainingEditorDialog) |
|
41 |
self.pushButtonDelete = QtWidgets.QPushButton(TrainingSymbolEditorDialog)
|
|
42 | 42 |
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) |
43 | 43 |
sizePolicy.setHorizontalStretch(0) |
44 | 44 |
sizePolicy.setVerticalStretch(0) |
... | ... | |
49 | 49 |
self.pushButtonDelete.setAutoDefault(False) |
50 | 50 |
self.pushButtonDelete.setObjectName("pushButtonDelete") |
51 | 51 |
self.horizontalLayout.addWidget(self.pushButtonDelete) |
52 |
self.pushButtonSplit = QtWidgets.QPushButton(TrainingEditorDialog) |
|
52 |
self.pushButtonSplit = QtWidgets.QPushButton(TrainingSymbolEditorDialog)
|
|
53 | 53 |
sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Maximum, QtWidgets.QSizePolicy.Maximum) |
54 | 54 |
sizePolicy.setHorizontalStretch(0) |
55 | 55 |
sizePolicy.setVerticalStretch(0) |
... | ... | |
66 | 66 |
self.verticalLayout_6.addLayout(self.horizontalLayout_2) |
67 | 67 |
self.horizontalLayout_4 = QtWidgets.QHBoxLayout() |
68 | 68 |
self.horizontalLayout_4.setObjectName("horizontalLayout_4") |
69 |
self.centralWidget = QtWidgets.QWidget(TrainingEditorDialog) |
|
69 |
self.verticalLayout = QtWidgets.QVBoxLayout() |
|
70 |
self.verticalLayout.setObjectName("verticalLayout") |
|
71 |
self.tableWidget = QtWidgets.QTableWidget(TrainingSymbolEditorDialog) |
|
72 |
self.tableWidget.setObjectName("tableWidget") |
|
73 |
self.tableWidget.setColumnCount(0) |
|
74 |
self.tableWidget.setRowCount(0) |
|
75 |
self.verticalLayout.addWidget(self.tableWidget) |
|
76 |
self.horizontalLayout_4.addLayout(self.verticalLayout) |
|
77 |
self.centralWidget = QtWidgets.QWidget(TrainingSymbolEditorDialog) |
|
70 | 78 |
self.centralWidget.setObjectName("centralWidget") |
71 | 79 |
self.verticalLayout_5 = QtWidgets.QVBoxLayout(self.centralWidget) |
72 | 80 |
self.verticalLayout_5.setObjectName("verticalLayout_5") |
... | ... | |
76 | 84 |
spacerItem1 = QtWidgets.QSpacerItem(4000, 0, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) |
77 | 85 |
self.verticalLayout_5.addItem(spacerItem1) |
78 | 86 |
self.horizontalLayout_4.addWidget(self.centralWidget) |
79 |
self.leftSideWidget = QtWidgets.QWidget(TrainingEditorDialog) |
|
87 |
self.leftSideWidget = QtWidgets.QWidget(TrainingSymbolEditorDialog)
|
|
80 | 88 |
self.leftSideWidget.setObjectName("leftSideWidget") |
81 | 89 |
self.sideWidget = QtWidgets.QVBoxLayout(self.leftSideWidget) |
82 | 90 |
self.sideWidget.setObjectName("sideWidget") |
... | ... | |
116 | 124 |
font = QtGui.QFont() |
117 | 125 |
font.setFamily("Consolas") |
118 | 126 |
self.lineEditChar.setFont(font) |
119 |
self.lineEditChar.setMaxLength(1)
|
|
127 |
self.lineEditChar.setMaxLength(50)
|
|
120 | 128 |
self.lineEditChar.setObjectName("lineEditChar") |
121 | 129 |
self.gridLayout_2.addWidget(self.lineEditChar, 2, 1, 1, 1) |
122 | 130 |
self.label_6 = QtWidgets.QLabel(self.leftSideWidget) |
... | ... | |
171 | 179 |
self.verticalLayout_6.addLayout(self.horizontalLayout_4) |
172 | 180 |
self.gridLayout.addLayout(self.verticalLayout_6, 0, 0, 1, 1) |
173 | 181 |
|
174 |
self.retranslateUi(TrainingEditorDialog) |
|
175 |
QtCore.QMetaObject.connectSlotsByName(TrainingEditorDialog) |
|
182 |
self.retranslateUi(TrainingSymbolEditorDialog)
|
|
183 |
QtCore.QMetaObject.connectSlotsByName(TrainingSymbolEditorDialog)
|
|
176 | 184 |
|
177 |
def retranslateUi(self, TrainingEditorDialog): |
|
185 |
def retranslateUi(self, TrainingSymbolEditorDialog):
|
|
178 | 186 |
_translate = QtCore.QCoreApplication.translate |
179 |
TrainingEditorDialog.setWindowTitle(_translate("TrainingEditorDialog", "Training Editor"))
|
|
180 |
self.pushButtonZoom.setText(_translate("TrainingEditorDialog", "Zoom")) |
|
181 |
self.pushButtonAdd.setText(_translate("TrainingEditorDialog", "Add")) |
|
182 |
self.pushButtonDelete.setText(_translate("TrainingEditorDialog", "Delete")) |
|
183 |
self.pushButtonSplit.setText(_translate("TrainingEditorDialog", "Divide")) |
|
184 |
self.label_6.setText(_translate("TrainingEditorDialog", "Top")) |
|
185 |
self.label_7.setText(_translate("TrainingEditorDialog", "Height")) |
|
186 |
self.label_3.setText(_translate("TrainingEditorDialog", "Left")) |
|
187 |
self.label_4.setText(_translate("TrainingEditorDialog", "Character"))
|
|
188 |
self.label_5.setText(_translate("TrainingEditorDialog", "Width")) |
|
189 |
self.pushButtonSave.setText(_translate("TrainingEditorDialog", "Save")) |
|
190 |
self.pushButtonCancel.setText(_translate("TrainingEditorDialog", "Close")) |
|
187 |
TrainingSymbolEditorDialog.setWindowTitle(_translate("TrainingSymbolEditorDialog", "Training Editor"))
|
|
188 |
self.pushButtonZoom.setText(_translate("TrainingSymbolEditorDialog", "Zoom"))
|
|
189 |
self.pushButtonAdd.setText(_translate("TrainingSymbolEditorDialog", "Add"))
|
|
190 |
self.pushButtonDelete.setText(_translate("TrainingSymbolEditorDialog", "Delete"))
|
|
191 |
self.pushButtonSplit.setText(_translate("TrainingSymbolEditorDialog", "Divide"))
|
|
192 |
self.label_6.setText(_translate("TrainingSymbolEditorDialog", "Top"))
|
|
193 |
self.label_7.setText(_translate("TrainingSymbolEditorDialog", "Height"))
|
|
194 |
self.label_3.setText(_translate("TrainingSymbolEditorDialog", "Left"))
|
|
195 |
self.label_4.setText(_translate("TrainingSymbolEditorDialog", "Label"))
|
|
196 |
self.label_5.setText(_translate("TrainingSymbolEditorDialog", "Width"))
|
|
197 |
self.pushButtonSave.setText(_translate("TrainingSymbolEditorDialog", "Save"))
|
|
198 |
self.pushButtonCancel.setText(_translate("TrainingSymbolEditorDialog", "Close"))
|
|
191 | 199 |
|
192 | 200 |
|
193 | 201 |
if __name__ == "__main__": |
194 | 202 |
import sys |
195 | 203 |
app = QtWidgets.QApplication(sys.argv) |
196 |
TrainingEditorDialog = QtWidgets.QDialog() |
|
197 |
ui = Ui_TrainingEditorDialog() |
|
198 |
ui.setupUi(TrainingEditorDialog) |
|
199 |
TrainingEditorDialog.show() |
|
204 |
TrainingSymbolEditorDialog = QtWidgets.QDialog()
|
|
205 |
ui = Ui_TrainingSymbolEditorDialog()
|
|
206 |
ui.setupUi(TrainingSymbolEditorDialog)
|
|
207 |
TrainingSymbolEditorDialog.show()
|
|
200 | 208 |
sys.exit(app.exec_()) |
201 | 209 |
|
DTI_PID/DTI_PID/TrainingSymbolImageListDialog.py | ||
---|---|---|
61 | 61 |
self.ui.pushButtonDeleteBatchLabel.clicked.connect(self.pushButtonDeleteBatchLabelClicked) |
62 | 62 |
|
63 | 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)
|
|
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 | 68 |
self.ui.pushButtonDeleteBatchLabel.setEnabled(True) |
69 | 69 |
self.ui.pushButtonDeleteBatchLabel.setHidden(False) |
70 | 70 |
self.ui.lineEditTargetLabel.setEnabled(True) |
... | ... | |
247 | 247 |
img = Image.open(imgPath) |
248 | 248 |
images.append([img, imgPath]) |
249 | 249 |
|
250 |
print(len(images)) |
|
251 |
if len(images) is 0: |
|
252 |
continue |
|
253 |
|
|
250 | 254 |
grid_size = [None, None] |
251 | 255 |
for img in images: |
252 | 256 |
if grid_size[0] is None or grid_size[0] < img[0].size[0]: |
... | ... | |
283 | 287 |
|
284 | 288 |
train_image_path = os.path.join(project.getTrainingSymbolFilePath(), str(uuid.uuid4()) + '.png') |
285 | 289 |
merged_img.save(train_image_path) |
290 |
print(train_image_path) |
|
291 |
|
|
292 |
self.ui.progressBar.setValue(self.ui.progressBar.value() + 1) |
|
293 |
QApplication.processEvents() |
|
286 | 294 |
|
295 |
self.listUpdate() |
|
287 | 296 |
except Exception as ex: |
288 | 297 |
from App import App |
289 | 298 |
from AppDocData import MessageType |
... | ... | |
370 | 379 |
drawingPath = os.path.join(project.getTrainingSymbolFilePath(), drawingName) |
371 | 380 |
drawing = Image.open(drawingPath) |
372 | 381 |
|
373 |
labelName = drawingName.replace('.png', '.boxS')
|
|
382 |
labelName = drawingName.replace('.png', '.xml')
|
|
374 | 383 |
|
375 | 384 |
dataList = appDocData.getTrainingSymbolFileList() |
376 | 385 |
isBoxFile = False |
... | ... | |
378 | 387 |
if data.find(labelName) is not -1: |
379 | 388 |
isBoxFile = True |
380 | 389 |
traininglabelPath = os.path.join(project.getTrainingSymbolFilePath(), labelName) |
381 |
boundaryOcrData = None
|
|
390 |
boundarySymbolData = None
|
|
382 | 391 |
if not isBoxFile: |
383 |
docData = AppDocData.instance()
|
|
384 |
### make contour
|
|
392 |
boundarySymbolData = []
|
|
393 |
img = np.array(drawing)
|
|
385 | 394 |
|
395 |
img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
|
396 |
imgNot = np.ones(img.shape, np.uint8) |
|
397 |
cv2.bitwise_not(img, imgNot) |
|
398 |
imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8)) |
|
399 |
|
|
400 |
contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) |
|
401 |
if len(contours) is 0: |
|
402 |
pass |
|
403 |
else: |
|
404 |
for cnt in contours: |
|
405 |
x, y, w, h = cv2.boundingRect(cnt) |
|
406 |
boundarySymbolData.append([x, y, w, h]) |
|
386 | 407 |
except Exception as ex: |
387 | 408 |
from App import App |
388 | 409 |
from AppDocData import MessageType |
... | ... | |
391 | 412 |
App.mainWnd().addMessage.emit(MessageType.Error, message) |
392 | 413 |
|
393 | 414 |
try: |
394 |
dialog = QTrainingSymbolEditorDialog(self, drawingPath, traininglabelPath, boundaryOcrData, self.ui.tableWidgetList.item(row, 2), self.ui.tableWidgetList.item(row, 3))
|
|
415 |
dialog = QTrainingSymbolEditorDialog(self, drawingPath, traininglabelPath, boundarySymbolData, self.ui.tableWidgetList.item(row, 2), self.ui.tableWidgetList.item(row, 3))
|
|
395 | 416 |
dialog.exec_() |
396 | 417 |
except Exception as ex: |
397 | 418 |
from App import App |
DTI_PID/DTI_PID/UI/TrainingSymbolEditor.ui | ||
---|---|---|
1 | 1 |
<?xml version="1.0" encoding="UTF-8"?> |
2 | 2 |
<ui version="4.0"> |
3 |
<class>TrainingEditorDialog</class> |
|
4 |
<widget class="QDialog" name="TrainingEditorDialog"> |
|
3 |
<class>TrainingSymbolEditorDialog</class>
|
|
4 |
<widget class="QDialog" name="TrainingSymbolEditorDialog">
|
|
5 | 5 |
<property name="geometry"> |
6 | 6 |
<rect> |
7 | 7 |
<x>0</x> |
8 | 8 |
<y>0</y> |
9 |
<width>1088</width>
|
|
9 |
<width>1130</width>
|
|
10 | 10 |
<height>780</height> |
11 | 11 |
</rect> |
12 | 12 |
</property> |
... | ... | |
152 | 152 |
<item> |
153 | 153 |
<layout class="QHBoxLayout" name="horizontalLayout_4"> |
154 | 154 |
<item> |
155 |
<layout class="QVBoxLayout" name="verticalLayout"> |
|
156 |
<item> |
|
157 |
<widget class="QTableWidget" name="tableWidget"/> |
|
158 |
</item> |
|
159 |
</layout> |
|
160 |
</item> |
|
161 |
<item> |
|
155 | 162 |
<widget class="QWidget" name="centralWidget" native="true"> |
156 | 163 |
<layout class="QVBoxLayout" name="verticalLayout_5"> |
157 | 164 |
<item> |
... | ... | |
290 | 297 |
</font> |
291 | 298 |
</property> |
292 | 299 |
<property name="maxLength"> |
293 |
<number>1</number>
|
|
300 |
<number>50</number>
|
|
294 | 301 |
</property> |
295 | 302 |
</widget> |
296 | 303 |
</item> |
... | ... | |
356 | 363 |
<item row="2" column="0"> |
357 | 364 |
<widget class="QLabel" name="label_4"> |
358 | 365 |
<property name="text"> |
359 |
<string>Character</string>
|
|
366 |
<string>Label</string>
|
|
360 | 367 |
</property> |
361 | 368 |
</widget> |
362 | 369 |
</item> |
내보내기 Unified diff