개정판 eeb349d8
issue #665: new training process
DTI_PID/DTI_PID/AppDocData.py | ||
---|---|---|
150 | 150 |
return drawingFileList |
151 | 151 |
|
152 | 152 |
''' |
153 |
@brief Get Training file list |
|
154 |
@author euisung |
|
155 |
@date 2018.10.16 |
|
156 |
''' |
|
157 |
def getTrainingFileList(self): |
|
158 |
try: |
|
159 |
project = AppDocData.instance().getCurrentProject() |
|
160 |
path = project.getTrainingFilePath() |
|
161 |
drawingFileList = os.listdir(path) |
|
162 |
drawingFileList.sort() |
|
163 |
except Exception as ex: |
|
164 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
165 |
|
|
166 |
return drawingFileList |
|
167 |
|
|
168 |
''' |
|
153 | 169 |
@brief Get DB file path in ProgramData |
154 | 170 |
@author Jeongwoo |
155 | 171 |
@date 2018.06.27 |
DTI_PID/DTI_PID/TrainingEditorDialog.py | ||
---|---|---|
16 | 16 |
|
17 | 17 |
|
18 | 18 |
class QTrainingEditorDialog(QDialog): |
19 |
def __init__(self, parent): |
|
19 |
def __init__(self, parent, trainingImgPath, trainingBoxPath):
|
|
20 | 20 |
self.spinBoxFlag = False |
21 | 21 |
QDialog.__init__(self, parent) |
22 | 22 |
|
23 |
self.trainingImgPath = trainingImgPath |
|
24 |
self.trainingBoxPath = trainingBoxPath |
|
25 |
|
|
23 | 26 |
appDocData = AppDocData.instance() |
24 | 27 |
project = appDocData.getCurrentProject() |
25 | 28 |
|
... | ... | |
40 | 43 |
|
41 | 44 |
# 학습 이미지 읽어서 메인 뷰에 그림, 사이드 뷰에 추가 |
42 | 45 |
try: |
43 |
trainingImgPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.tif') |
|
46 |
#trainingImgPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.tif')
|
|
44 | 47 |
cvImg = cv2.cvtColor(cv2.imread(trainingImgPath), cv2.COLOR_BGR2GRAY) |
45 | 48 |
blur = cv2.GaussianBlur(cvImg, (5,5),0) |
46 | 49 |
cvImg = cv2.threshold(cvImg, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1] |
47 | 50 |
bytesPerLine = cvImg.shape[1] |
48 | 51 |
image = QImage(cvImg.data, cvImg.shape[1], cvImg.shape[0], bytesPerLine, QImage.Format_Indexed8) |
49 | 52 |
|
50 |
#img = cv2.imread(trainingImgPath) |
|
51 |
#image = QImage(img.data, img.shape[1], img.shape[0], img.shape[1], QImage.Format_Indexed8) |
|
52 |
|
|
53 | 53 |
self.graphicsViewTrainingDrawing.setImage(image) |
54 | 54 |
|
55 | 55 |
# 사이드 뷰 |
... | ... | |
73 | 73 |
|
74 | 74 |
# 박스 읽어서 메인 뷰에 그림 |
75 | 75 |
try: |
76 |
trainingBoxPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.box') |
|
76 |
#trainingBoxPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.box')
|
|
77 | 77 |
fBox = open(trainingBoxPath, 'r', encoding='utf8') |
78 | 78 |
SBox = fBox.read() |
79 | 79 |
fBox.close() |
... | ... | |
102 | 102 |
self.removedItems = [] |
103 | 103 |
|
104 | 104 |
self.ui.pushButtonZoom.clicked.connect(self.onAreaZoom) |
105 |
self.ui.pushButtonSave.clicked.connect(self.pushButtonSaveClicked) |
|
105 | 106 |
self.ui.spinBoxLeft.valueChanged.connect(self.spinBoxChangedEvent) |
106 | 107 |
self.ui.spinBoxTop.valueChanged.connect(self.spinBoxChangedEvent) |
107 | 108 |
self.ui.spinBoxWidth.valueChanged.connect(self.spinBoxChangedEvent) |
108 | 109 |
self.ui.spinBoxHeight.valueChanged.connect(self.spinBoxChangedEvent) |
109 | 110 |
|
111 |
def pushButtonSaveClicked(self): |
|
112 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
|
113 |
outBox = "" |
|
114 |
for item in items: |
|
115 |
rect = item.rect() |
|
116 |
char, x, y, width, height = item.char, str(rect.x()), str(rect.y()), str(rect.width()), str(rect.height()) |
|
117 |
outBox += char + " " + x + " " + y + " " + width + " " + height + "\n" |
|
118 |
fw = open(self.trainingBoxPath, 'w') |
|
119 |
fw.write(outBox) |
|
120 |
fw.close() |
|
121 |
|
|
122 |
|
|
123 |
|
|
110 | 124 |
def spinBoxChangedEvent(self, event): |
111 | 125 |
items = self.graphicsViewTrainingDrawing.scene.selectedItems() |
112 | 126 |
if(len(items) is not 1) or self.spinBoxFlag: |
DTI_PID/DTI_PID/TrainingImageListDialog.py | ||
---|---|---|
6 | 6 |
from AppDocData import AppDocData, Source |
7 | 7 |
import pytesseract |
8 | 8 |
import TrainingImageList_UI |
9 |
from TrainingEditorDialog import QTrainingEditorDialog |
|
9 | 10 |
|
10 | 11 |
|
11 | 12 |
pytesseract.pytesseract.tesseract_cmd = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'Tesseract-OCR', 'tesseract.exe') |
... | ... | |
22 | 23 |
def __init__(self, parent): |
23 | 24 |
QDialog.__init__(self, parent) |
24 | 25 |
|
25 |
self.ui = TrainingIamgeList_UI.Ui_TraingingImageListDialog()
|
|
26 |
self.ui = TrainingImageList_UI.Ui_TraingingImageListDialog()
|
|
26 | 27 |
self.ui.setupUi(self) |
27 | 28 |
|
28 | 29 |
# for List |
... | ... | |
30 | 31 |
self.ui.tableWidgetList.setColumnCount(3) |
31 | 32 |
|
32 | 33 |
docData = AppDocData.instance() |
33 |
dataList = docData.getDrawingFileList() |
|
34 |
self.ui.tableWidgetList.setRowCount(len(dataList)) |
|
34 |
dataList = docData.getTrainingFileList() |
|
35 |
imgCount = 0 |
|
36 |
for data in dataList: |
|
37 |
if data.find('.png') is not -1: |
|
38 |
imgCount += 1 |
|
39 |
self.ui.tableWidgetList.setRowCount(imgCount) |
|
35 | 40 |
|
36 | 41 |
## column header 명 설정 |
37 | 42 |
headerLabel = docData.getCurrentProject().getName() |
... | ... | |
45 | 50 |
|
46 | 51 |
row = 0 |
47 | 52 |
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 |
|
53 |
if data.find('.png') is not -1: |
|
54 |
self.ui.tableWidgetList.setItem(row, 0, QTableWidgetItem(str(row + 1))) |
|
55 |
self.ui.tableWidgetList.setItem(row, 1, QTableWidgetItem(data)) |
|
56 |
row += 1 |
|
51 | 57 |
|
52 | 58 |
# connect signals and slots |
53 | 59 |
self.ui.tableWidgetList.cellDoubleClicked.connect(self.listCellDoubleClicked) |
54 |
self.ui.pushButtonAddList.clicked.connect(self.addListClicked)
|
|
55 |
self.ui.pushButtonMakeTrainingData.clicked.connect(self.makeTrainingDataClicked) |
|
60 |
self.ui.pushButtonBox.clicked.connect(self.makeTrainingDataClicked)
|
|
61 |
#self.ui.pushButtonMakeTrainingData.clicked.connect(self.makeTrainingDataClicked)
|
|
56 | 62 |
|
57 | 63 |
''' |
58 | 64 |
@brief make training data(text image + Box file) by button click |
59 | 65 |
@author euisung |
60 |
@date 2018.09.28
|
|
66 |
@date 2018.10.16
|
|
61 | 67 |
''' |
62 | 68 |
def makeTrainingDataClicked(self): |
63 |
from TextDetector import TextDetector |
|
64 | 69 |
from PIL import Image |
65 |
import cv2, math |
|
66 | 70 |
|
67 | 71 |
try: |
68 |
row = self.ui.tableWidgetSelected.selectedIndexes()[0].row()
|
|
69 |
col = self.ui.tableWidgetSelected.selectedIndexes()[0].column()
|
|
70 |
drawingName = self.ui.tableWidgetSelected.item(row, 1).text()
|
|
72 |
row = self.ui.tableWidgetList.selectedIndexes()[0].row()
|
|
73 |
col = self.ui.tableWidgetList.selectedIndexes()[0].column()
|
|
74 |
drawingName = self.ui.tableWidgetList.item(row, 1).text()
|
|
71 | 75 |
except: |
72 | 76 |
return |
73 | 77 |
|
74 | 78 |
try: |
75 | 79 |
appDocData = AppDocData.instance() |
76 | 80 |
project = appDocData.getCurrentProject() |
77 |
textDetector = TextDetector() |
|
78 |
|
|
79 |
drawingPath = os.path.join(project.getDrawingFilePath(), drawingName) |
|
80 |
drawing = Source(Image.open(drawingPath)) |
|
81 |
|
|
82 |
_imgSrc = cv2.cvtColor(cv2.imread(drawingPath), cv2.COLOR_BGR2GRAY) |
|
83 |
blur = cv2.GaussianBlur(_imgSrc , (5,5),0) |
|
84 |
_imgSrc = cv2.threshold(_imgSrc , 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1] |
|
85 |
|
|
86 |
textAreas = textDetector.detectTextAreas(_imgSrc , (0,0)) |
|
87 |
|
|
88 |
areasNumber = len(textAreas) |
|
89 |
print('total text areas : ' + str(areasNumber)) |
|
90 |
maxW, maxH, sumW, sumH, count = 0, 0, 0, 0, 0 |
|
91 |
for textArea in textAreas: |
|
92 |
areaW = textArea.getW() |
|
93 |
areaH = textArea.getH() |
|
94 |
areaA = textArea.getAngle() |
|
95 |
if areaA is 90: |
|
96 |
areaW, areaH = areaH, areaW |
|
97 |
if areaA is not 0 and areaA is not 90: |
|
98 |
continue |
|
99 |
count += 1 |
|
100 |
sumW += areaW |
|
101 |
sumH += areaH |
|
102 |
if maxW < areaW: |
|
103 |
maxW = areaW |
|
104 |
if maxH < areaH: |
|
105 |
maxH = areaH |
|
106 |
|
|
107 |
print('count : ' + str(count)) |
|
108 |
print('max width : ' + str(maxW) + ', max height : ' + str(maxH)) |
|
109 |
argW = sumW / count |
|
110 |
argH = sumH / count |
|
111 |
print('arg width : ' + str(argW) + ', arg height : ' + str(argH)) |
|
112 |
totalArea = math.ceil(argW * argH * count) |
|
113 |
totalBaseWidth = math.ceil(math.sqrt(totalArea)) |
|
114 |
print('total area theory : ' + str(totalArea) + ', total width : ' + str(totalBaseWidth)) |
|
115 |
|
|
116 |
maxLineH, lineW, totalHeight = 0, 0, 0 |
|
117 |
for index in range(0, areasNumber): |
|
118 |
areaW = textAreas[index].getW() |
|
119 |
areaH = textAreas[index].getH() |
|
120 |
areaA = textAreas[index].getAngle() |
|
121 |
if areaA is 90: |
|
122 |
areaW, areaH = areaH, areaW |
|
123 |
if areaA is not 0 and areaA is not 90: |
|
124 |
continue |
|
125 |
|
|
126 |
if maxLineH < areaH: |
|
127 |
maxLineH = areaH |
|
128 |
if lineW + areaW < totalBaseWidth: |
|
129 |
lineW += areaW |
|
130 |
else: |
|
131 |
lineW = areaW |
|
132 |
totalHeight += maxLineH |
|
133 |
totalHeight += maxLineH |
|
134 |
print('total area real : ' + str(totalBaseWidth * totalHeight) +', total width : ' + str(totalBaseWidth) + ', total height : ' + str(totalHeight) + ', ratio : ' + str(totalHeight / totalBaseWidth)) |
|
135 |
|
|
136 |
trainingTextImg = Image.new("RGB", (totalBaseWidth, totalHeight), (256,256,256)) |
|
137 |
maxLineH, lineW, totalHeight, currentX, currentY = 0, 0, 0, 0, 0 |
|
138 |
for index in range(0, areasNumber): |
|
139 |
#print(index) |
|
140 |
areaW = textAreas[index].getW() |
|
141 |
areaH = textAreas[index].getH() |
|
142 |
areaA = textAreas[index].getAngle() |
|
143 |
|
|
144 |
textAreaImg = drawing.source.crop((textAreas[index].getX(), textAreas[index].getY(), textAreas[index].getX() + areaW, textAreas[index].getY() + areaH)) |
|
145 |
|
|
146 |
if areaA is 90: |
|
147 |
areaW, areaH = areaH, areaW |
|
148 |
textAreaImg = textAreaImg.transpose(Image.ROTATE_270) |
|
149 |
if areaA is not 0 and areaA is not 90: |
|
150 |
continue |
|
151 |
|
|
152 |
if maxLineH < areaH: |
|
153 |
maxLineH = areaH |
|
154 |
if lineW + areaW < totalBaseWidth: |
|
155 |
lineW += areaW |
|
156 |
trainingTextImg.paste(textAreaImg, (currentX, currentY, currentX + areaW, currentY + areaH)) |
|
157 |
currentX = lineW |
|
158 |
else: |
|
159 |
lineW = areaW |
|
160 |
totalHeight += maxLineH |
|
161 |
currentX = 0 |
|
162 |
currentY = totalHeight |
|
163 |
trainingTextImg.paste(textAreaImg, (currentX, currentY, currentX + areaW, currentY + areaH)) |
|
164 |
currentX = areaW |
|
165 |
#trainingTextImg.show() |
|
166 |
#trainingTextImg.show() |
|
167 |
boundaryOcrData = pytesseract.image_to_boxes(trainingTextImg, config=DEFAULT_CONF, lang='seed+eng') |
|
168 |
|
|
169 |
trainingImgPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.tif') |
|
170 |
trainingBoxPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.box') |
|
171 |
|
|
172 |
trainingTextImg.save(trainingImgPath, compression='tiff_lzw') |
|
81 |
|
|
82 |
drawingPath = os.path.join(project.getTrainingFilePath(), drawingName) |
|
83 |
drawing = Image.open(drawingPath) |
|
84 |
|
|
85 |
boundaryOcrData = pytesseract.image_to_boxes(drawing, config=DEFAULT_CONF, lang='seed+eng') |
|
86 |
|
|
87 |
boxName = drawingName.replace('.png', '.box') |
|
88 |
trainingBoxPath = os.path.join(project.getTrainingFilePath(), boxName) |
|
89 |
|
|
90 |
|
|
173 | 91 |
fw = open(trainingBoxPath, 'w') #파일 있으면 새로 만듬 예외 처리 안됨, 임시 |
174 | 92 |
fw.write(boundaryOcrData) |
175 | 93 |
fw.close() |
176 |
|
|
177 | 94 |
except Exception as ex: |
178 | 95 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
96 |
|
|
97 |
try: |
|
98 |
dialog = QTrainingEditorDialog(self, drawingPath, trainingBoxPath) |
|
99 |
dialog.exec_() |
|
100 |
except Exception as ex: |
|
101 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
102 |
|
|
179 | 103 |
return |
180 | 104 |
|
181 | 105 |
''' |
DTI_PID/DTI_PID/TrainingImageList_UI.py | ||
---|---|---|
8 | 8 |
|
9 | 9 |
from PyQt5 import QtCore, QtGui, QtWidgets |
10 | 10 |
|
11 |
class Ui_TraingingListDialog(object): |
|
12 |
def setupUi(self, TraingingListDialog): |
|
13 |
TraingingListDialog.setObjectName("TraingingListDialog")
|
|
14 |
TraingingListDialog.resize(943, 535) |
|
15 |
self.gridLayout = QtWidgets.QGridLayout(TraingingListDialog) |
|
11 |
class Ui_TraingingImageListDialog(object):
|
|
12 |
def setupUi(self, TraingingImageListDialog):
|
|
13 |
TraingingImageListDialog.setObjectName("TraingingImageListDialog")
|
|
14 |
TraingingImageListDialog.resize(943, 535)
|
|
15 |
self.gridLayout = QtWidgets.QGridLayout(TraingingImageListDialog)
|
|
16 | 16 |
self.gridLayout.setObjectName("gridLayout") |
17 | 17 |
self.verticalLayout = QtWidgets.QVBoxLayout() |
18 | 18 |
self.verticalLayout.setObjectName("verticalLayout") |
... | ... | |
20 | 20 |
self.horizontalLayout_2.setObjectName("horizontalLayout_2") |
21 | 21 |
self.verticalLayout_3 = QtWidgets.QVBoxLayout() |
22 | 22 |
self.verticalLayout_3.setObjectName("verticalLayout_3") |
23 |
self.label_2 = QtWidgets.QLabel(TraingingListDialog) |
|
23 |
self.label_2 = QtWidgets.QLabel(TraingingImageListDialog)
|
|
24 | 24 |
self.label_2.setAlignment(QtCore.Qt.AlignCenter) |
25 | 25 |
self.label_2.setObjectName("label_2") |
26 | 26 |
self.verticalLayout_3.addWidget(self.label_2) |
27 |
self.tableWidgetList = QtWidgets.QTableWidget(TraingingListDialog) |
|
27 |
self.tableWidgetList = QtWidgets.QTableWidget(TraingingImageListDialog)
|
|
28 | 28 |
self.tableWidgetList.setColumnCount(1) |
29 | 29 |
self.tableWidgetList.setObjectName("tableWidgetList") |
30 | 30 |
self.tableWidgetList.setRowCount(0) |
31 | 31 |
self.tableWidgetList.verticalHeader().setVisible(False) |
32 | 32 |
self.verticalLayout_3.addWidget(self.tableWidgetList) |
33 |
self.pushButtonAddList = QtWidgets.QPushButton(TraingingListDialog)
|
|
34 |
self.pushButtonAddList.setObjectName("pushButtonAddList")
|
|
35 |
self.verticalLayout_3.addWidget(self.pushButtonAddList)
|
|
36 |
self.pushButtonMakeTrainingData = QtWidgets.QPushButton(TraingingListDialog) |
|
33 |
self.pushButtonBox = QtWidgets.QPushButton(TraingingImageListDialog)
|
|
34 |
self.pushButtonBox.setObjectName("pushButtonBox")
|
|
35 |
self.verticalLayout_3.addWidget(self.pushButtonBox)
|
|
36 |
self.pushButtonMakeTrainingData = QtWidgets.QPushButton(TraingingImageListDialog)
|
|
37 | 37 |
self.pushButtonMakeTrainingData.setObjectName("pushButtonMakeTrainingData") |
38 | 38 |
self.verticalLayout_3.addWidget(self.pushButtonMakeTrainingData) |
39 | 39 |
self.horizontalLayout_2.addLayout(self.verticalLayout_3) |
... | ... | |
42 | 42 |
self.horizontalLayout.setObjectName("horizontalLayout") |
43 | 43 |
spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum) |
44 | 44 |
self.horizontalLayout.addItem(spacerItem) |
45 |
self.pushButton_2 = QtWidgets.QPushButton(TraingingListDialog) |
|
45 |
self.pushButton_2 = QtWidgets.QPushButton(TraingingImageListDialog)
|
|
46 | 46 |
self.pushButton_2.setObjectName("pushButton_2") |
47 | 47 |
self.horizontalLayout.addWidget(self.pushButton_2) |
48 |
self.pushButton = QtWidgets.QPushButton(TraingingListDialog) |
|
48 |
self.pushButton = QtWidgets.QPushButton(TraingingImageListDialog)
|
|
49 | 49 |
self.pushButton.setObjectName("pushButton") |
50 | 50 |
self.horizontalLayout.addWidget(self.pushButton) |
51 | 51 |
self.verticalLayout.addLayout(self.horizontalLayout) |
52 | 52 |
self.gridLayout.addLayout(self.verticalLayout, 0, 0, 1, 1) |
53 | 53 |
|
54 |
self.retranslateUi(TraingingListDialog) |
|
55 |
QtCore.QMetaObject.connectSlotsByName(TraingingListDialog) |
|
54 |
self.retranslateUi(TraingingImageListDialog)
|
|
55 |
QtCore.QMetaObject.connectSlotsByName(TraingingImageListDialog)
|
|
56 | 56 |
|
57 |
def retranslateUi(self, TraingingListDialog): |
|
57 |
def retranslateUi(self, TraingingImageListDialog):
|
|
58 | 58 |
_translate = QtCore.QCoreApplication.translate |
59 |
TraingingListDialog.setWindowTitle(_translate("TraingingListDialog", "Training List"))
|
|
60 |
self.label_2.setText(_translate("TraingingListDialog", "List")) |
|
61 |
self.pushButtonAddList.setText(_translate("TraingingListDialog", "추가"))
|
|
62 |
self.pushButtonMakeTrainingData.setText(_translate("TraingingListDialog", "학습 데이터 생성")) |
|
63 |
self.pushButton_2.setText(_translate("TraingingListDialog", "PushButton")) |
|
64 |
self.pushButton.setText(_translate("TraingingListDialog", "PushButton")) |
|
59 |
TraingingImageListDialog.setWindowTitle(_translate("TraingingImageListDialog", "Training Image List"))
|
|
60 |
self.label_2.setText(_translate("TraingingImageListDialog", "List"))
|
|
61 |
self.pushButtonBox.setText(_translate("TraingingImageListDialog", "문자 영역 수정"))
|
|
62 |
self.pushButtonMakeTrainingData.setText(_translate("TraingingImageListDialog", "학습 데이터 생성"))
|
|
63 |
self.pushButton_2.setText(_translate("TraingingImageListDialog", "PushButton"))
|
|
64 |
self.pushButton.setText(_translate("TraingingImageListDialog", "PushButton"))
|
|
65 | 65 |
|
66 | 66 |
|
67 | 67 |
if __name__ == "__main__": |
68 | 68 |
import sys |
69 | 69 |
app = QtWidgets.QApplication(sys.argv) |
70 |
TraingingListDialog = QtWidgets.QDialog() |
|
71 |
ui = Ui_TraingingListDialog() |
|
72 |
ui.setupUi(TraingingListDialog) |
|
73 |
TraingingListDialog.show() |
|
70 |
TraingingImageListDialog = QtWidgets.QDialog()
|
|
71 |
ui = Ui_TraingingImageListDialog()
|
|
72 |
ui.setupUi(TraingingImageListDialog)
|
|
73 |
TraingingImageListDialog.show()
|
|
74 | 74 |
sys.exit(app.exec_()) |
75 | 75 |
|
DTI_PID/DTI_PID/UI/TrainingImageList.ui | ||
---|---|---|
1 | 1 |
<?xml version="1.0" encoding="UTF-8"?> |
2 | 2 |
<ui version="4.0"> |
3 |
<class>TraingingListDialog</class> |
|
4 |
<widget class="QDialog" name="TraingingListDialog"> |
|
3 |
<class>TraingingImageListDialog</class>
|
|
4 |
<widget class="QDialog" name="TraingingImageListDialog">
|
|
5 | 5 |
<property name="geometry"> |
6 | 6 |
<rect> |
7 | 7 |
<x>0</x> |
... | ... | |
11 | 11 |
</rect> |
12 | 12 |
</property> |
13 | 13 |
<property name="windowTitle"> |
14 |
<string>Training List</string> |
|
14 |
<string>Training Image List</string>
|
|
15 | 15 |
</property> |
16 | 16 |
<layout class="QGridLayout" name="gridLayout"> |
17 | 17 |
<item row="0" column="0"> |
... | ... | |
42 | 42 |
</widget> |
43 | 43 |
</item> |
44 | 44 |
<item> |
45 |
<widget class="QPushButton" name="pushButtonAddList">
|
|
45 |
<widget class="QPushButton" name="pushButtonBox">
|
|
46 | 46 |
<property name="text"> |
47 |
<string>추가</string>
|
|
47 |
<string>문자 영역 수정</string>
|
|
48 | 48 |
</property> |
49 | 49 |
</widget> |
50 | 50 |
</item> |
내보내기 Unified diff