프로젝트

일반

사용자정보

통계
| 개정판:

hytos / DTI_PID / DTI_PID / TrainingEditorDialog.py @ 99e0f49b

이력 | 보기 | 이력해설 | 다운로드 (15.3 KB)

1 c96518e7 esham21
import sys
2 d89b1f19 esham21
import os, time
3 c96518e7 esham21
from PyQt5.QtCore import *
4
from PyQt5.QtGui import *
5
from PyQt5.QtWidgets import *
6
from AppDocData import AppDocData, Source
7
import TrainingEditor_UI
8
import QtImageViewer
9
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
10
from TrainingBoxItem import QTrainingBoxItem
11
import cv2
12 6913dbc8 esham21
from PIL import Image
13 c96518e7 esham21
import AreaZoomCommand
14
import PlaceLineCommand
15
16
class QTrainingEditorDialog(QDialog):
17 d89b1f19 esham21
    def __init__(self, parent, trainingImgPath, trainingBoxPath, boundaryOcrData, cellItem):
18 d45df999 esham21
        self.spinBoxFlag = False
19 c96518e7 esham21
        QDialog.__init__(self, parent)
20 63c55b90 esham21
        self.setWindowFlag(Qt.WindowMinMaxButtonsHint)
21 c96518e7 esham21
22 eeb349d8 esham21
        self.trainingImgPath = trainingImgPath
23
        self.trainingBoxPath = trainingBoxPath
24 726d4cf2 esham21
        self.boundaryOcrData = boundaryOcrData
25 d89b1f19 esham21
        self.cellItem = cellItem
26 53953154 esham21
        self.isChanged = False
27 eeb349d8 esham21
28 c96518e7 esham21
        appDocData = AppDocData.instance()
29
        project = appDocData.getCurrentProject()
30
31
        self.ui = TrainingEditor_UI.Ui_TrainingEditorDialog()
32
        self.ui.setupUi(self)
33
34
        self.graphicsViewTrainingDrawing = QtImageViewer.QtImageViewer(self)
35
        self.graphicsViewTrainingDrawing.setParent(self.ui.centralWidget)
36
        self.graphicsViewTrainingDrawing.useDefaultCommand()
37
        self.ui.verticalLayoutTrainingDrawing.addWidget(self.graphicsViewTrainingDrawing)
38 6913dbc8 esham21
39
        self.graphicsViewZoomDrawing = QGraphicsView(self)
40 d45df999 esham21
        self.graphicsViewZoomDrawing.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
41
        self.graphicsViewZoomDrawing.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
42 6913dbc8 esham21
        self.graphicsViewZoomDrawing.setParent(self.ui.leftSideWidget)
43
        self.ui.horizontalLayoutZoomDrawing.addWidget(self.graphicsViewZoomDrawing)
44
        
45 c96518e7 esham21
        
46 d45df999 esham21
        # 학습 이미지 읽어서 메인 뷰에 그림, 사이드 뷰에 추가
47 c96518e7 esham21
        try:
48 eeb349d8 esham21
            #trainingImgPath = os.path.join(project.getTrainingFilePath(), 'seed.seedF.exp0.tif')
49 c96518e7 esham21
            cvImg = cv2.cvtColor(cv2.imread(trainingImgPath), cv2.COLOR_BGR2GRAY)
50
            blur = cv2.GaussianBlur(cvImg, (5,5),0)
51
            cvImg = cv2.threshold(cvImg, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
52
            bytesPerLine = cvImg.shape[1]
53
            image = QImage(cvImg.data, cvImg.shape[1], cvImg.shape[0], bytesPerLine, QImage.Format_Indexed8)
54
55
            self.graphicsViewTrainingDrawing.setImage(image)
56 d45df999 esham21
57
            # 사이드 뷰
58
            if type(image) is QPixmap:
59
                pixmap = image
60
            elif type(image) is QImage:
61
                pixmap = QPixmap.fromImage(image)
62
            scene = QGraphicsScene()
63
            self.graphicsViewZoomDrawing.setScene(scene)
64
            self._pixmapHandle = self.graphicsViewZoomDrawing.scene().addPixmap(pixmap)
65 b7d5317e esham21
            self.graphicsViewZoomDrawing.scene().setSceneRect(0, 0, pixmap.width(), pixmap.height())
66
            self.graphicsViewZoomDrawing.fitInView(self.graphicsViewZoomDrawing.scene().sceneRect(), Qt.KeepAspectRatioByExpanding)
67 d45df999 esham21
            rect = QGraphicsRectItem(0, 0, 0, 0)
68
            pen = QPen(Qt.SolidLine)
69
            pen.setColor(Qt.green)
70
            pen.setWidthF(1)
71
            pen.setJoinStyle(Qt.MiterJoin)
72
            rect.setPen(pen)
73 59e764f3 esham21
            rect.setOpacity(0.7)
74 d45df999 esham21
            self.graphicsViewZoomDrawing.scene().addItem(rect)
75
76 c96518e7 esham21
        except Exception as ex:
77
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
78
79 d45df999 esham21
        # 박스 읽어서 메인 뷰에 그림
80 c96518e7 esham21
        try:
81
            boxList = []
82 726d4cf2 esham21
            if self.boundaryOcrData is None:
83
                fBox = open(trainingBoxPath, 'r', encoding='utf8')
84
                SBox = fBox.read()
85
                fBox.close()
86
                boxList = SBox.split('\n')
87
            else:
88
                boxList = boundaryOcrData.split('\n')
89 c96518e7 esham21
90
            for box in boxList:
91 726d4cf2 esham21
                if box == '': continue
92 c96518e7 esham21
                boxComponent = box.split(' ')
93 1669b150 esham21
                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]))
94 c96518e7 esham21
                singleBox.transfer.onRemoved.connect(self.itemRemoved)
95 d45df999 esham21
                singleBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag)
96 c96518e7 esham21
        except Exception as ex:
97
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
98
99
        #'''test'''
100
        #item = QGraphicsBoundingBoxItem(0, 0, 30, 30)
101
        #item.isSymbol = True
102
        #item.angle = 0
103
        #item.setPen(QPen(Qt.red, 1, Qt.SolidLine))
104
        #self.graphicsViewTrainingDrawing.scene.addItem(item)
105
106
        self.removedItems = []
107
108
        self.ui.pushButtonZoom.clicked.connect(self.onAreaZoom)
109 eeb349d8 esham21
        self.ui.pushButtonSave.clicked.connect(self.pushButtonSaveClicked)
110 83575689 esham21
        self.ui.pushButtonCancel.clicked.connect(self.pushButtonCancelClicked)
111
        self.ui.pushButtonChange.clicked.connect(self.pushButtonChangeClicked)
112 726d4cf2 esham21
        self.ui.pushButtonDelete.clicked.connect(self.pushButtonDeleteClicked)
113
        self.ui.pushButtonAdd.clicked.connect(self.pushButtonAddClicked)
114 6fa02c93 esham21
        self.ui.pushButtonSplit.clicked.connect(self.pushButtonSplitClicked)
115 d45df999 esham21
        self.ui.spinBoxLeft.valueChanged.connect(self.spinBoxChangedEvent)
116
        self.ui.spinBoxTop.valueChanged.connect(self.spinBoxChangedEvent)
117
        self.ui.spinBoxWidth.valueChanged.connect(self.spinBoxChangedEvent)
118
        self.ui.spinBoxHeight.valueChanged.connect(self.spinBoxChangedEvent)
119 6913dbc8 esham21
120 726d4cf2 esham21
    '''
121 6fa02c93 esham21
        @brief      split boxitem by button click
122
        @author     euisung
123
        @date       2018.10.31
124
    '''
125
    def pushButtonSplitClicked(self):
126
        self.isChanged = True
127
        items = self.graphicsViewTrainingDrawing.scene.selectedItems()
128
        if len(items) is not 1:
129
            return
130
        rect = items[0].rect()
131
        secondBox = QTrainingBoxItem('', rect.x() + round(rect.width() / 2), rect.y(), round(rect.width() / 2), rect.height())
132
        secondBox.transfer.onRemoved.connect(self.itemRemoved)
133
        secondBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag)
134
        items[0].setRect(rect.x(), rect.y(), round(rect.width() / 2), rect.height())
135
136
    '''
137 726d4cf2 esham21
        @brief      add boxitem by button click
138
        @author     euisung
139
        @date       2018.10.17
140
    '''
141
    def pushButtonAddClicked(self):
142 53953154 esham21
        self.isChanged = True
143 726d4cf2 esham21
        items = self.graphicsViewTrainingDrawing.scene.selectedItems()
144
        allItems = self.graphicsViewTrainingDrawing.scene.items()
145
        totalWidth = 0
146
        totalHeight = 0
147
        count = 0
148
        if len(items) is 1:
149
            rect = items[0].rect()
150
        elif len(allItems) > 1:
151
            for item in allItems:
152
                if type(item) is QGraphicsPixmapItem:
153
                    x = int(item.boundingRect().width() / 2)
154
                    y = int(item.boundingRect().height()/ 2)
155
                else:
156
                    count += 1
157
                    totalWidth += item.rect().width()
158
                    totalHeight += item.rect().height()
159
            rect = QRectF(x, y, round(totalWidth / count), round(totalHeight / count))
160
        else:
161
            for item in allItems:
162
                if type(item) is QGraphicsPixmapItem:
163
                    x = int(item.boundingRect().width() / 2)
164
                    y = int(item.boundingRect().height()/ 2)
165
            rect = QRectF(x, y, 5, 10)
166
        singleBox = QTrainingBoxItem('', rect.x() + 3, rect.y(), rect.width(), rect.height())
167
        singleBox.transfer.onRemoved.connect(self.itemRemoved)
168
        singleBox.addTextItemToScene(self.ui, self.graphicsViewTrainingDrawing, self.graphicsViewZoomDrawing, self.spinBoxFlag)
169
170
    '''
171
        @brief      delete boxitem by button click
172
        @author     euisung
173
        @date       2018.10.17
174
    '''
175
    def pushButtonDeleteClicked(self):
176 53953154 esham21
        self.isChanged = True
177 726d4cf2 esham21
        items = self.graphicsViewTrainingDrawing.scene.selectedItems()
178
        for item in items:
179
            item.transfer.onRemoved.emit(item)
180
181
    '''
182
        @brief      change boxitem char by button click
183
        @author     euisung
184
        @date       2018.10.17
185
    '''
186 83575689 esham21
    def pushButtonChangeClicked(self):
187 53953154 esham21
        self.isChanged = True
188 eeb349d8 esham21
        items = self.graphicsViewTrainingDrawing.scene.selectedItems()
189 726d4cf2 esham21
        if len(items) is not 1:
190 83575689 esham21
            return
191
        items[0].char = self.ui.lineEditChar.text()
192 b9091c43 esham21
        items[0].textShowBox.setHtml(self.ui.lineEditChar.text())
193 83575689 esham21
194 726d4cf2 esham21
    '''
195
        @brief      close dialog by button click
196
        @author     euisung
197
        @date       2018.10.17
198
    '''
199 83575689 esham21
    def pushButtonCancelClicked(self):
200 53953154 esham21
        if self.isChanged:
201
            reply = QMessageBox.question(self, 'Continue?', '변경사항이 저장되지 않았을 수 있습니다.', QMessageBox.Ignore, QMessageBox.Cancel)
202
            if reply == QMessageBox.Ignore:
203
                QDialog.reject(self)
204
        else:
205
            QDialog.reject(self)
206 83575689 esham21
207 726d4cf2 esham21
    '''
208
        @brief      save box item by button click
209
        @author     euisung
210
        @date       2018.10.16
211
    '''
212 83575689 esham21
    def pushButtonSaveClicked(self):
213
        items = self.graphicsViewTrainingDrawing.scene.items()
214 eeb349d8 esham21
        outBox = ""
215
        for item in items:
216 83575689 esham21
            if type(item) is QGraphicsPixmapItem:
217
                imgHeight = int(item.boundingRect().height())
218
                imgWidth = int(item.boundingRect().width())
219
        for item in items:
220
            if type(item) is QTrainingBoxItem:
221
                rect = item.rect()
222
                char, x, y, width, height = item.char, int(rect.x()), int(rect.y()), int(rect.width()), int(rect.height())
223 726d4cf2 esham21
                bx, by, bx2, by2 = str(x), str(imgHeight - y - height), str(x + width), str(imgHeight - y)
224
                if char == '':
225
                    continue
226 83575689 esham21
                outBox += char + " " + bx + " " + by + " " + bx2 + " " + by2 + "\n"
227 eeb349d8 esham21
        fw = open(self.trainingBoxPath, 'w')
228
        fw.write(outBox)
229
        fw.close()
230 d89b1f19 esham21
        modifiedTime = time.ctime(os.path.getmtime(self.trainingBoxPath))
231
        self.cellItem.setText(modifiedTime)
232
233 53953154 esham21
        self.isChanged = False
234 452e4adb esham21
        QMessageBox.about(self, "알림", '저장하였습니다.')
235 eeb349d8 esham21
236 726d4cf2 esham21
    '''
237
        @brief      chane box item's rect by button click
238
        @author     euisung
239
        @date       2018.10.16
240
    '''
241 d45df999 esham21
    def spinBoxChangedEvent(self, event):
242 53953154 esham21
        self.isChanged = True
243 6913dbc8 esham21
        items = self.graphicsViewTrainingDrawing.scene.selectedItems()
244 726d4cf2 esham21
        if (len(items) is not 1) or self.spinBoxFlag:
245 6913dbc8 esham21
            return
246 d45df999 esham21
        spinBoxName = self.sender().objectName()
247 6913dbc8 esham21
        rect = items[0].rect()
248 d45df999 esham21
        bound = self.graphicsViewZoomDrawing.scene().items()[0]
249
250
        if spinBoxName == 'spinBoxLeft':
251
            spinBoxValue = self.ui.spinBoxLeft.value()
252
            items[0].setRect(QRectF(spinBoxValue, rect.y(), rect.width(), rect.height()))
253 99e0f49b esham21
            items[0].textShowBox.setPos(items[0].rect().x() + round(items[0].rect().width() / 3), items[0].rect().y() - round(items[0].rect().height() / 2))
254 d45df999 esham21
        elif spinBoxName == 'spinBoxTop':
255
            spinBoxValue = self.ui.spinBoxTop.value()
256
            items[0].setRect(QRectF(rect.x(), spinBoxValue, rect.width(), rect.height()))
257 99e0f49b esham21
            items[0].textShowBox.setPos(items[0].rect().x() + round(items[0].rect().width() / 3), items[0].rect().y() - round(items[0].rect().height() / 2))
258 d45df999 esham21
        elif spinBoxName == 'spinBoxWidth':
259
            spinBoxValue = self.ui.spinBoxWidth.value()
260
            items[0].setRect(QRectF(rect.x(),  rect.y(), spinBoxValue, rect.height()))
261 99e0f49b esham21
            items[0].textShowBox.setPos(items[0].rect().x() + round(items[0].rect().width() / 3), items[0].rect().y() - round(items[0].rect().height() / 2))
262 d45df999 esham21
        elif spinBoxName == 'spinBoxHeight':
263
            spinBoxValue = self.ui.spinBoxHeight.value()
264
            items[0].setRect(QRectF(rect.x(), rect.y(), rect.width(), spinBoxValue))
265 99e0f49b esham21
            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
267 d45df999 esham21
        rect = items[0].rect()        
268
        bound.setRect(rect)
269 99e0f49b esham21
        rectSide = QRectF(rect.x() - 3, rect.y() - 3, rect.width() + 6,  rect.height() + 6)
270 d45df999 esham21
        self.graphicsViewZoomDrawing.fitInView(rectSide)
271 6913dbc8 esham21
        self.graphicsViewTrainingDrawing.scene.update()
272
    
273 c96518e7 esham21
    def onAreaZoom(self, action):
274
        if self.ui.pushButtonZoom.isChecked():
275
            cmd = AreaZoomCommand.AreaZoomCommand(self.graphicsViewTrainingDrawing)
276
            cmd.onRejected.connect(self.onCommandRejected)
277
            self.graphicsViewTrainingDrawing.command = cmd
278
279
    def onCommandRejected(self, cmd):
280
        try:
281
            if type(cmd) is AreaZoomCommand.AreaZoomCommand:
282
                self.ui.pushButtonZoom.setChecked(False)
283
        finally:
284
            self.graphicsViewTrainingDrawing.useDefaultCommand()
285
286
    def itemRemoved(self, item):
287
        try:
288
            if type(item) is QTrainingBoxItem:
289
                self.removedItems.append(str(item.uid))
290
291 83575689 esham21
            if item.scene is not None: item.scene.removeItem(item)
292 c96518e7 esham21
        except Exception as ex:
293
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
294
295 13502b99 esham21
    '''
296
        @brief      key pressed event
297
        @author     euisung
298
        @date       2018.11.05
299
    '''
300
    def keyPressEvent(self, event):
301
        try:
302 a247f3fd esham21
            items = self.graphicsViewTrainingDrawing.scene.selectedItems()
303
            if len(items) is not 1 or type(items[0]) is not QTrainingBoxItem:
304
                return
305
            seletedItem = items[0]
306
            closestItem = None
307
            x = seletedItem.rect().x()
308 13502b99 esham21
            if event.key() == Qt.Key_Left:
309 a247f3fd esham21
                dx =  sys.maxsize
310 13502b99 esham21
                for item in self.graphicsViewTrainingDrawing.scene.items():
311
                    if type(item) is QTrainingBoxItem:
312 a247f3fd esham21
                        if x - item.rect().x() > 0 and x - item.rect().x() < dx:
313
                            closestItem = item
314
                            dx = x - item.rect().x()
315
                if closestItem is not None:
316
                    closestItem.setSelected(True)
317
                    seletedItem.setSelected(False)
318
                    closestItem.mousePressEvent('arrow key')
319
                        
320 13502b99 esham21
            elif event.key() == Qt.Key_Right:
321 a247f3fd esham21
                dx = -sys.maxsize
322
                for item in self.graphicsViewTrainingDrawing.scene.items():
323
                    if type(item) is QTrainingBoxItem:
324
                        if x - item.rect().x() < 0 and x - item.rect().x() > dx:
325
                            closestItem = item
326
                            dx = x - item.rect().x()
327
                if closestItem is not None:
328
                    closestItem.setSelected(True)
329
                    seletedItem.setSelected(False)
330
                    closestItem.mousePressEvent('arrow key')
331 13502b99 esham21
                
332
        except Exception as ex:
333
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
334
            from App import App
335
            from AppDocData import MessageType
336
337
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
338
            App.mainWnd().addMessage.emit(MessageType.Error, message)
339
            return None
340
341 c96518e7 esham21
        
342
        
343
344
        
클립보드 이미지 추가 (최대 크기: 500 MB)