프로젝트

일반

사용자정보

개정판 02519509

ID02519509ce1477e3881802671af9f502af765a1d
상위 752b0432
하위 d03f6dc2, da1aeb27

백흠경이(가) 약 5년 전에 추가함

issue 366: 텍스트 영역 인식 및 텍스트 인식 속도 개선
issue 479: 심볼 인식 후 hit ratio를 툴팁에 표기
기타 - tesseract version 표기

Change-Id: I7c41eb524de4919bce6aed18c361dcacc09f8aeb

차이점 보기:

DTI_PID/DTI_PID/AppDocData.py
1358 1358
    '''
1359 1359

  
1360 1360
    def saveConfigs(self, configs):
1361
        conn = self.project.database.connect()
1362
        with conn:
1361
        with self.project.database.connect() as conn:
1363 1362
            try:
1364 1363
                # Get a cursor object
1365 1364
                cursor = conn.cursor()
1365
                if self.project.database.db_type == 'SQLite':
1366
                    cursor.execute('begin')
1366 1367

  
1367 1368
                for config in configs:
1368 1369
                    if type(config) is Config:
......
1388 1389
                            if sql is not None and 2 == len(sql):
1389 1390
                                cursor.execute(self.project.database.to_sql(sql[0]), sql[1])
1390 1391
                self._configs = None  # reset config table
1391
                conn.commit()
1392

  
1393
                if self.project.database.db_type == 'SQLite':
1394
                    cursor.execute('commit')
1395
                else:
1396
                    conn.commit()
1392 1397
            # Catch the exception
1393 1398
            except Exception as ex:
1394 1399
                # Roll back any change if something goes wrong
......
1648 1653
    def getSymbolListByType(self, field_name=None, param=None):
1649 1654
        ret = []
1650 1655

  
1651
        conn = self.project.database.connect()
1652
        with conn:
1656
        with self.project.database.connect() as conn:
1653 1657
            cursor = conn.cursor()
1654 1658
            if field_name is not None and param is not None:
1655 1659
                sql = """SELECT a.UID,a.Name,b.Type,a.Threshold,a.MinMatchPoint,a.IsDetectOrigin,a.RotationCount,a.OCROption,a.IsContainChild,a.OriginalPoint,a.ConnectionPoint,
......
3639 3643
    def getSymbolTypeList(self):
3640 3644
        symbolTypeList = []
3641 3645

  
3642
        conn = self.project.database.connect()
3643
        with conn:
3646
        with self.project.database.connect() as conn:
3644 3647
            cursor = conn.cursor()
3645 3648
            sql = 'SELECT * FROM SymbolType ORDER BY Type ASC'
3646 3649
            try:
......
3691 3694

  
3692 3695
    def isEquipmentType(self, type):
3693 3696
        category = self.getSymbolCategoryByType(type)
3694
        return (category is not None and category == 'Equipment')
3697
        return category is not None and category == 'Equipment'
3695 3698

  
3696 3699
    '''
3697 3700
        @brief      Return Symbol Type Items with "None"
......
3701 3704
    '''
3702 3705

  
3703 3706
    def getSymbolTypeComboBoxItems(self):
3704
        symbolTypeList = self.getSymbolTypeList()
3707
        symbolTypeList = [symbol_type for symbol_type in self.getSymbolTypeList() if symbol_type[1]]
3705 3708
        symbolTypeList.insert(0, ('None', 'None', 'None'))
3706 3709

  
3707 3710
        return symbolTypeList
DTI_PID/DTI_PID/Commands/RemoveTextCommand.py
1 1
import os.path
2 2
import AbstractCommand
3

  
3 4
try:
4 5
    from PyQt5.QtCore import Qt, QPoint, QPointF, QRectF, pyqtSignal, QT_VERSION_STR, QBuffer, QRect, QRegExp
5
    from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QPainter, QColor, QPen, QBrush, QCursor, QTransform, QFont, QRegExpValidator, QValidator
6
    from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QPainter, QColor, QPen, QBrush, QCursor, QTransform, QFont, \
7
        QRegExpValidator, QValidator
6 8
    from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog, QMessageBox
7 9
except ImportError:
8 10
    try:
9 11
        from PyQt4.QtCore import Qt, QPoint, QPointF, QRectF, pyqtSignal, QT_VERSION_STR, QBuffer, QRect, QRegExp
10
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QPainter, QColor, QPen, QBrush, QCursor, QTransform, QFont, QRegExpValidator, QValidator
12
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QPainter, \
13
            QColor, QPen, QBrush, QCursor, QTransform, QFont, QRegExpValidator, QValidator
11 14
    except ImportError:
12 15
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
13 16
import sys
......
18 21
import io
19 22
import cv2
20 23

  
24

  
21 25
class RemoveTextCommand(AbstractCommand.AbstractCommand):
22 26
    '''
23 27
        @history    2018.05.09  Jeongwoo    Draw Rect on ±1 area
24 28
                    2018.06.11  Jeongwoo    Change method to set image (setImage → setPixmap/updateViewer)
25 29
    '''
30

  
26 31
    def __init__(self, imageViewer):
27 32
        super(RemoveTextCommand, self).__init__(imageViewer)
28
        self.name = 'RemoveText' 
29
        #self.imageViewer.setCursor(QCursor(Qt.ArrowCursor))
33
        self.name = 'RemoveText'
34
        # self.imageViewer.setCursor(QCursor(Qt.ArrowCursor))
30 35
        image = self.imageViewer.image()
31 36
        buffer = QBuffer()
32 37
        buffer.open(QBuffer.ReadWrite)
......
34 39
        pyImage = Image.open(io.BytesIO(buffer.data()))
35 40
        dst = cv2.cvtColor(np.array(pyImage), cv2.COLOR_BGR2GRAY)
36 41
        textDetector = TextDetector()
37
        self.textInfoList = textDetector.detectTextAreas(dst, (0, 0))
42
        self.textInfoList, _ = textDetector.detectTextAreas(dst, (0, 0))
38 43
        pixmap = self.imageViewer.pixmap()
39 44
        ADJUST = 1
40 45
        for textInfo in self.textInfoList:
......
42 47
            painter.begin(pixmap)
43 48
            painter.setPen(QColor(255, 255, 255))
44 49
            painter.setBrush(QColor(255, 255, 255))
45
            painter.drawRect(QRect(textInfo.getX()-ADJUST, textInfo.getY()-ADJUST, textInfo.getW()+ADJUST, textInfo.getH()+ADJUST))
50
            painter.drawRect(QRect(textInfo.getX() - ADJUST, textInfo.getY() - ADJUST, textInfo.getW() + ADJUST,
51
                                   textInfo.getH() + ADJUST))
46 52
            painter.end()
47 53
        pixmapHandle = self.imageViewer.getPixmapHandle()
48 54
        if pixmapHandle is not None:
49 55
            pixmapHandle.setPixmap(pixmap)
50 56
            self.imageViewer.setSceneRect(QRectF(pixmap.rect()))
51 57
            self.imageViewer.updateViewer()
52
    
58

  
53 59
    def execute(self, param):
54 60
        event = param[1]
55 61
        scenePos = param[2]
......
59 65
        pass
60 66

  
61 67
    def redo(self):
62
        pass
68
        pass
DTI_PID/DTI_PID/ConfigurationDialog.py
12 12
from AppDocData import Color
13 13
from EngineeringAbstractItem import QEngineeringAbstractItem
14 14
import Configuration_UI
15
import pytesseract
15 16
import tesseract_ocr_module as TOCR
16 17

  
17 18

  
......
60 61
            self.ui.comboBoxOCRData.setCurrentIndex(at)
61 62
        else:
62 63
            self.ui.comboBoxOCRData.selectedIndex = 0
64
        self.ui.labelTesseractVersion.setText(f"tesseract={str(pytesseract.get_tesseract_version())}")
63 65

  
64 66
        configs = docData.getConfigs('Text Recognition', 'Expand Size')
65
        self.ui.spinBoxExpandSize.setValue(int(configs[0].value)) if 1 == len(
66
            configs) else self.ui.spinBoxExpandSize.setValue(10)
67
        self.ui.spinBoxExpandSize.setValue(int(configs[0].value)) if 1 == len(configs) else \
68
            self.ui.spinBoxExpandSize.setValue(10)
67 69
        configs = docData.getConfigs('Text Recognition', 'Shrink Size')
68
        self.ui.spinBoxShrinkSize.setValue(int(configs[0].value)) if 1 == len(
69
            configs) else self.ui.spinBoxShrinkSize.setValue(0)
70
        self.ui.spinBoxShrinkSize.setValue(int(configs[0].value)) if 1 == len(configs) else \
71
            self.ui.spinBoxShrinkSize.setValue(0)
70 72
        configs = docData.getConfigs('Text Recognition', 'Merge Size')
71
        self.ui.spinBoxMergeSize.setValue(int(configs[0].value)) if 1 == len(
72
            configs) else self.ui.spinBoxMergeSize.setValue(10)
73
        self.ui.spinBoxMergeSize.setValue(int(configs[0].value)) if 1 == len(configs) else \
74
            self.ui.spinBoxMergeSize.setValue(10)
73 75
        configs = docData.getConfigs('Text Recognition', 'White Character List')
74
        self.ui.lineEditWhiteCharList.setText(configs[0].value) if 1 == len(configs) else self.ui.lineEditWhiteCharList.setText(TOCR.DEFAULT_CONF[40:])
76
        self.ui.lineEditWhiteCharList.setText(configs[0].value) if 1 == len(configs) else \
77
            self.ui.lineEditWhiteCharList.setText(TOCR.DEFAULT_CONF[40:])
78
        self.set_page_segmentation_modes()
75 79
        configs = docData.getConfigs('Text Recognition', 'White Single Text')
76
        self.ui.lineEditSingleText.setText(configs[0].value) if 1 == len(configs) else self.ui.lineEditSingleText.setText('H,L')
80
        self.ui.lineEditSingleText.setText(configs[0].value) if 1 == len(configs) else \
81
            self.ui.lineEditSingleText.setText('H,L')
77 82

  
78 83
        configs = docData.getConfigs('Text Size', 'Min Text Size')
79 84
        self.ui.minTextSizeSpinBox.setValue(int(configs[0].value)) if 1 == len(
......
405 410
        self.ui.listWidgetTagNo.itemDoubleClicked.connect(self.tagNoItemDoubleCliced)
406 411
        self.ui.pushButtonClearAccessInfo.clicked.connect(self.clear_drawing_access_info_clicked)
407 412

  
413
    def set_page_segmentation_modes(self):
414
        """show page segmentation modes"""
415
        try:
416
            model = QStandardItemModel()
417

  
418
            items = [('0', 'Orientation and script detection(OSD) only.'),
419
                     ('1', 'Automatic page segmentation with OSD.'),
420
                     ('2', 'Automatic page segmentation, but no OSD, or OCR.'),
421
                     ('3', 'Fully automatic page segmentation, but no OSD.(Default)'),
422
                     ('4', 'Assume a single column of text of variable sizes.'),
423
                     ('5', 'Assume a single uniform block of vertically aligned text.'),
424
                     ('6', 'Assume a single uniform block of text.'),
425
                     ('7', 'Treat the image as a single text line.'),
426
                     ('8', 'Treat the image as a single word.'),
427
                     ('9', 'Treat the image as a single word in a circle.'),
428
                     ('10', 'Treat the image as a single character.'),
429
                     ('11', 'Sparse text.Find as much text as possible in no particular order.'),
430
                     ('12', 'Sparse text with OSD.'),
431
                     ('13', 'Raw line.Treat the image as a single text line, bypassing hacks that are Tesseract - '
432
                            'specific.')]
433

  
434
            for value, label in items:
435
                value_item = QStandardItem(value)
436
                label_item = QStandardItem(label)
437
                model.appendRow([value_item, label_item])
438

  
439
            model.setHorizontalHeaderLabels(['Value', 'Desc.'])
440

  
441
            view = QTableView(self)
442
            view.verticalHeader().hide()
443

  
444
            self.ui.comboBoxPageSegmentationModes.setModel(model)
445
            self.ui.comboBoxPageSegmentationModes.setView(view)
446
            view.resizeColumnsToContents()
447

  
448
            app_doc_data = AppDocData.instance()
449
            configs = app_doc_data.getConfigs('Text Recognition', 'Page Segmentation Modes')
450
            if configs:
451
                self.ui.comboBoxPageSegmentationModes.setCurrentIndex(int(configs[0].value))
452
            else:
453
                self.ui.comboBoxPageSegmentationModes.setCurrentIndex(3)
454
        except Exception as ex:
455
            from App import App
456
            from AppDocData import MessageType
457

  
458
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
459
                                                           sys.exc_info()[-1].tb_lineno)
460
            App.mainWnd().addMessage.emit(MessageType.Error, message)
461

  
408 462
    def clear_drawing_access_info_clicked(self):
409 463
        reply = QMessageBox.question(self, self.tr('Continue?'),
410 464
                                     self.tr('Are you sure you want to clear drawing access information?'),
......
812 866
            configs.append(Config('Drain Size Rule', 'Size', docData.drain_size))
813 867
            configs.append(Config('Text Recognition', 'White Character List', self.ui.lineEditWhiteCharList.text()))
814 868
            configs.append(Config('Text Recognition', 'White Single Text', self.ui.lineEditSingleText.text()))
869
            configs.append(Config('Text Recognition', 'Page Segmentation Modes',
870
                                  str(self.ui.comboBoxPageSegmentationModes.currentIndex())))
815 871
            # Add Line Color Option - 2018.07.06 by kyouho
816 872
            rbRandomValue = self.ui.radioButtonRandom.isChecked()
817 873

  
DTI_PID/DTI_PID/Configuration_UI.py
13 13
class Ui_ConfigurationDialog(object):
14 14
    def setupUi(self, ConfigurationDialog):
15 15
        ConfigurationDialog.setObjectName("ConfigurationDialog")
16
        ConfigurationDialog.resize(632, 616)
16
        ConfigurationDialog.resize(648, 631)
17 17
        font = QtGui.QFont()
18 18
        font.setFamily("맑은 고딕")
19 19
        ConfigurationDialog.setFont(font)
......
90 90
        self.gridLayout_14.setObjectName("gridLayout_14")
91 91
        self.gridLayout_25 = QtWidgets.QGridLayout()
92 92
        self.gridLayout_25.setObjectName("gridLayout_25")
93
        self.maxTextSizeSpinBox = QtWidgets.QSpinBox(self.groupBoxText)
94
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
95
        sizePolicy.setHorizontalStretch(0)
96
        sizePolicy.setVerticalStretch(0)
97
        sizePolicy.setHeightForWidth(self.maxTextSizeSpinBox.sizePolicy().hasHeightForWidth())
98
        self.maxTextSizeSpinBox.setSizePolicy(sizePolicy)
99
        self.maxTextSizeSpinBox.setProperty("value", 60)
100
        self.maxTextSizeSpinBox.setObjectName("maxTextSizeSpinBox")
101
        self.gridLayout_25.addWidget(self.maxTextSizeSpinBox, 4, 3, 1, 1)
102 93
        self.minTextSizeSpinBox = QtWidgets.QSpinBox(self.groupBoxText)
103 94
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
104 95
        sizePolicy.setHorizontalStretch(0)
......
108 99
        self.minTextSizeSpinBox.setMaximumSize(QtCore.QSize(16777215, 16777215))
109 100
        self.minTextSizeSpinBox.setProperty("value", 30)
110 101
        self.minTextSizeSpinBox.setObjectName("minTextSizeSpinBox")
111
        self.gridLayout_25.addWidget(self.minTextSizeSpinBox, 4, 1, 1, 1)
112
        self.label_18 = QtWidgets.QLabel(self.groupBoxText)
113
        self.label_18.setObjectName("label_18")
114
        self.gridLayout_25.addWidget(self.label_18, 4, 2, 1, 1)
115
        self.label_17 = QtWidgets.QLabel(self.groupBoxText)
116
        self.label_17.setObjectName("label_17")
117
        self.gridLayout_25.addWidget(self.label_17, 4, 0, 1, 1)
102
        self.gridLayout_25.addWidget(self.minTextSizeSpinBox, 5, 1, 1, 1)
103
        self.maxTextSizeSpinBox = QtWidgets.QSpinBox(self.groupBoxText)
104
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
105
        sizePolicy.setHorizontalStretch(0)
106
        sizePolicy.setVerticalStretch(0)
107
        sizePolicy.setHeightForWidth(self.maxTextSizeSpinBox.sizePolicy().hasHeightForWidth())
108
        self.maxTextSizeSpinBox.setSizePolicy(sizePolicy)
109
        self.maxTextSizeSpinBox.setProperty("value", 60)
110
        self.maxTextSizeSpinBox.setObjectName("maxTextSizeSpinBox")
111
        self.gridLayout_25.addWidget(self.maxTextSizeSpinBox, 5, 3, 1, 1)
118 112
        self.label_21 = QtWidgets.QLabel(self.groupBoxText)
119 113
        self.label_21.setObjectName("label_21")
120
        self.gridLayout_25.addWidget(self.label_21, 3, 2, 1, 1)
121
        self.spinBoxShrinkSize = QtWidgets.QSpinBox(self.groupBoxText)
122
        self.spinBoxShrinkSize.setMinimumSize(QtCore.QSize(100, 0))
123
        self.spinBoxShrinkSize.setObjectName("spinBoxShrinkSize")
124
        self.gridLayout_25.addWidget(self.spinBoxShrinkSize, 3, 3, 1, 1)
114
        self.gridLayout_25.addWidget(self.label_21, 4, 2, 1, 1)
115
        self.label_17 = QtWidgets.QLabel(self.groupBoxText)
116
        self.label_17.setObjectName("label_17")
117
        self.gridLayout_25.addWidget(self.label_17, 5, 0, 1, 1)
118
        self.label_18 = QtWidgets.QLabel(self.groupBoxText)
119
        self.label_18.setObjectName("label_18")
120
        self.gridLayout_25.addWidget(self.label_18, 5, 2, 1, 1)
125 121
        self.spinBoxExpandSize = QtWidgets.QSpinBox(self.groupBoxText)
126 122
        self.spinBoxExpandSize.setMinimumSize(QtCore.QSize(100, 0))
127 123
        self.spinBoxExpandSize.setObjectName("spinBoxExpandSize")
128
        self.gridLayout_25.addWidget(self.spinBoxExpandSize, 3, 1, 1, 1)
124
        self.gridLayout_25.addWidget(self.spinBoxExpandSize, 4, 1, 1, 1)
125
        self.spinBoxShrinkSize = QtWidgets.QSpinBox(self.groupBoxText)
126
        self.spinBoxShrinkSize.setMinimumSize(QtCore.QSize(100, 0))
127
        self.spinBoxShrinkSize.setObjectName("spinBoxShrinkSize")
128
        self.gridLayout_25.addWidget(self.spinBoxShrinkSize, 4, 3, 1, 1)
129 129
        self.label_19 = QtWidgets.QLabel(self.groupBoxText)
130 130
        self.label_19.setObjectName("label_19")
131 131
        self.gridLayout_25.addWidget(self.label_19, 0, 0, 1, 1)
132
        self.label_20 = QtWidgets.QLabel(self.groupBoxText)
133
        self.label_20.setObjectName("label_20")
134
        self.gridLayout_25.addWidget(self.label_20, 4, 0, 1, 1)
132 135
        self.label_7 = QtWidgets.QLabel(self.groupBoxText)
133 136
        self.label_7.setObjectName("label_7")
134 137
        self.gridLayout_25.addWidget(self.label_7, 1, 0, 1, 1)
135
        self.label_20 = QtWidgets.QLabel(self.groupBoxText)
136
        self.label_20.setObjectName("label_20")
137
        self.gridLayout_25.addWidget(self.label_20, 3, 0, 1, 1)
138 138
        self.label_37 = QtWidgets.QLabel(self.groupBoxText)
139 139
        self.label_37.setObjectName("label_37")
140
        self.gridLayout_25.addWidget(self.label_37, 2, 0, 1, 1)
140
        self.gridLayout_25.addWidget(self.label_37, 3, 0, 1, 1)
141 141
        self.label_22 = QtWidgets.QLabel(self.groupBoxText)
142 142
        self.label_22.setObjectName("label_22")
143
        self.gridLayout_25.addWidget(self.label_22, 5, 0, 1, 1)
143
        self.gridLayout_25.addWidget(self.label_22, 6, 0, 1, 1)
144
        self.lineEditWhiteCharList = QtWidgets.QLineEdit(self.groupBoxText)
145
        self.lineEditWhiteCharList.setObjectName("lineEditWhiteCharList")
146
        self.gridLayout_25.addWidget(self.lineEditWhiteCharList, 1, 1, 1, 3)
147
        self.lineEditSingleText = QtWidgets.QLineEdit(self.groupBoxText)
148
        self.lineEditSingleText.setObjectName("lineEditSingleText")
149
        self.gridLayout_25.addWidget(self.lineEditSingleText, 3, 1, 1, 1)
144 150
        self.spinBoxMergeSize = QtWidgets.QSpinBox(self.groupBoxText)
145 151
        self.spinBoxMergeSize.setMinimumSize(QtCore.QSize(100, 0))
146 152
        self.spinBoxMergeSize.setObjectName("spinBoxMergeSize")
147
        self.gridLayout_25.addWidget(self.spinBoxMergeSize, 5, 1, 1, 1)
153
        self.gridLayout_25.addWidget(self.spinBoxMergeSize, 6, 1, 1, 1)
148 154
        self.comboBoxOCRData = QtWidgets.QComboBox(self.groupBoxText)
149 155
        self.comboBoxOCRData.setMinimumSize(QtCore.QSize(200, 0))
150 156
        self.comboBoxOCRData.setMaximumSize(QtCore.QSize(200, 16777215))
151 157
        self.comboBoxOCRData.setObjectName("comboBoxOCRData")
152 158
        self.gridLayout_25.addWidget(self.comboBoxOCRData, 0, 1, 1, 1)
153
        self.lineEditSingleText = QtWidgets.QLineEdit(self.groupBoxText)
154
        self.lineEditSingleText.setObjectName("lineEditSingleText")
155
        self.gridLayout_25.addWidget(self.lineEditSingleText, 2, 1, 1, 1)
156
        self.lineEditWhiteCharList = QtWidgets.QLineEdit(self.groupBoxText)
157
        self.lineEditWhiteCharList.setObjectName("lineEditWhiteCharList")
158
        self.gridLayout_25.addWidget(self.lineEditWhiteCharList, 1, 1, 1, 3)
159
        self.label_39 = QtWidgets.QLabel(self.groupBoxText)
160
        self.label_39.setObjectName("label_39")
161
        self.gridLayout_25.addWidget(self.label_39, 2, 0, 1, 1)
162
        self.comboBoxPageSegmentationModes = QtWidgets.QComboBox(self.groupBoxText)
163
        self.comboBoxPageSegmentationModes.setObjectName("comboBoxPageSegmentationModes")
164
        self.gridLayout_25.addWidget(self.comboBoxPageSegmentationModes, 2, 1, 1, 3)
165
        self.labelTesseractVersion = QtWidgets.QLabel(self.groupBoxText)
166
        self.labelTesseractVersion.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
167
        self.labelTesseractVersion.setObjectName("labelTesseractVersion")
168
        self.gridLayout_25.addWidget(self.labelTesseractVersion, 0, 2, 1, 2)
159 169
        self.gridLayout_14.addLayout(self.gridLayout_25, 0, 0, 1, 1)
160 170
        self.gridLayout_2.addWidget(self.groupBoxText, 0, 1, 1, 1)
161 171
        self.groupBoxAttribute = QtWidgets.QGroupBox(self.Recognition)
......
647 657
        self.buttonBox.accepted.connect(ConfigurationDialog.accept)
648 658
        self.buttonBox.rejected.connect(ConfigurationDialog.reject)
649 659
        QtCore.QMetaObject.connectSlotsByName(ConfigurationDialog)
660
        ConfigurationDialog.setTabOrder(self.comboBoxOCRData, self.lineEditWhiteCharList)
661
        ConfigurationDialog.setTabOrder(self.lineEditWhiteCharList, self.comboBoxPageSegmentationModes)
662
        ConfigurationDialog.setTabOrder(self.comboBoxPageSegmentationModes, self.lineEditSingleText)
663
        ConfigurationDialog.setTabOrder(self.lineEditSingleText, self.spinBoxExpandSize)
664
        ConfigurationDialog.setTabOrder(self.spinBoxExpandSize, self.spinBoxShrinkSize)
665
        ConfigurationDialog.setTabOrder(self.spinBoxShrinkSize, self.minTextSizeSpinBox)
666
        ConfigurationDialog.setTabOrder(self.minTextSizeSpinBox, self.maxTextSizeSpinBox)
667
        ConfigurationDialog.setTabOrder(self.maxTextSizeSpinBox, self.spinBoxMergeSize)
668
        ConfigurationDialog.setTabOrder(self.spinBoxMergeSize, self.lineEditSizeDelimiter)
669
        ConfigurationDialog.setTabOrder(self.lineEditSizeDelimiter, self.doubleSpinBoxDetectionRange)
670
        ConfigurationDialog.setTabOrder(self.doubleSpinBoxDetectionRange, self.spinBoxFlowMarkPosition)
671
        ConfigurationDialog.setTabOrder(self.spinBoxFlowMarkPosition, self.spinBoxFlowMarkLength)
672
        ConfigurationDialog.setTabOrder(self.spinBoxFlowMarkLength, self.spinBoxMinimumSize)
673
        ConfigurationDialog.setTabOrder(self.spinBoxMinimumSize, self.spinBoxUnrecognitionIgnoreStep)
674
        ConfigurationDialog.setTabOrder(self.spinBoxUnrecognitionIgnoreStep, self.spinBoxDilateSize)
675
        ConfigurationDialog.setTabOrder(self.spinBoxDilateSize, self.spinBoxFlatSize)
676
        ConfigurationDialog.setTabOrder(self.spinBoxFlatSize, self.radioButtonMode1)
677
        ConfigurationDialog.setTabOrder(self.radioButtonMode1, self.radioButtonMode2)
678
        ConfigurationDialog.setTabOrder(self.radioButtonMode2, self.spinBoxMinArea)
679
        ConfigurationDialog.setTabOrder(self.spinBoxMinArea, self.spinBoxMaxArea)
680
        ConfigurationDialog.setTabOrder(self.spinBoxMaxArea, self.spinBoxWidth)
681
        ConfigurationDialog.setTabOrder(self.spinBoxWidth, self.spinBoxHeight)
682
        ConfigurationDialog.setTabOrder(self.spinBoxHeight, self.smallLineMinLengthSpinBox)
683
        ConfigurationDialog.setTabOrder(self.smallLineMinLengthSpinBox, self.spinBoxLengthToConnectLine)
684
        ConfigurationDialog.setTabOrder(self.spinBoxLengthToConnectLine, self.comboBoxLineType)
685
        ConfigurationDialog.setTabOrder(self.comboBoxLineType, self.radioButtonDiagonalYes)
686
        ConfigurationDialog.setTabOrder(self.radioButtonDiagonalYes, self.radioButtonDiagonalNo)
687
        ConfigurationDialog.setTabOrder(self.radioButtonDiagonalNo, self.pushButtonLineNoAttribute)
688
        ConfigurationDialog.setTabOrder(self.pushButtonLineNoAttribute, self.pushButtonAddProperty)
689
        ConfigurationDialog.setTabOrder(self.pushButtonAddProperty, self.pushButtonDeleteProperty)
690
        ConfigurationDialog.setTabOrder(self.pushButtonDeleteProperty, self.listWidgetLineNo)
691
        ConfigurationDialog.setTabOrder(self.listWidgetLineNo, self.pushButtonTagNoAttribute)
692
        ConfigurationDialog.setTabOrder(self.pushButtonTagNoAttribute, self.pushButtonAddTagProperty)
693
        ConfigurationDialog.setTabOrder(self.pushButtonAddTagProperty, self.pushButtonDeleteTagProperty)
694
        ConfigurationDialog.setTabOrder(self.pushButtonDeleteTagProperty, self.listWidgetTagNo)
695
        ConfigurationDialog.setTabOrder(self.listWidgetTagNo, self.checkBoxNoteNoSymbolName)
696
        ConfigurationDialog.setTabOrder(self.checkBoxNoteNoSymbolName, self.lineEditNoteNoSymbolName)
697
        ConfigurationDialog.setTabOrder(self.lineEditNoteNoSymbolName, self.lineEditNoteNoExpression)
698
        ConfigurationDialog.setTabOrder(self.lineEditNoteNoExpression, self.lineEditOPCFromPrefix)
699
        ConfigurationDialog.setTabOrder(self.lineEditOPCFromPrefix, self.lineEditOPCToPrefix)
700
        ConfigurationDialog.setTabOrder(self.lineEditOPCToPrefix, self.lineEditByVendor)
701
        ConfigurationDialog.setTabOrder(self.lineEditByVendor, self.lineEditDrainSize)
702
        ConfigurationDialog.setTabOrder(self.lineEditDrainSize, self.lineEdit_2)
650 703
        ConfigurationDialog.setTabOrder(self.lineEdit_2, self.tableWidgetLineTypes)
651
        ConfigurationDialog.setTabOrder(self.tableWidgetLineTypes, self.tabWidget)
704
        ConfigurationDialog.setTabOrder(self.tableWidgetLineTypes, self.pushButtonInstrumentColor)
705
        ConfigurationDialog.setTabOrder(self.pushButtonInstrumentColor, self.pushButtonEquipColor)
706
        ConfigurationDialog.setTabOrder(self.pushButtonEquipColor, self.spinBoxSymbolOpacity)
707
        ConfigurationDialog.setTabOrder(self.spinBoxSymbolOpacity, self.fontComboBox)
708
        ConfigurationDialog.setTabOrder(self.fontComboBox, self.radioButtonAutoSize)
709
        ConfigurationDialog.setTabOrder(self.radioButtonAutoSize, self.radioButtonFixedSize)
710
        ConfigurationDialog.setTabOrder(self.radioButtonFixedSize, self.spinBoxFontSize)
711
        ConfigurationDialog.setTabOrder(self.spinBoxFontSize, self.radioButtonRandom)
712
        ConfigurationDialog.setTabOrder(self.radioButtonRandom, self.radioButtonProperty)
713
        ConfigurationDialog.setTabOrder(self.radioButtonProperty, self.comboBoxColorOption)
714
        ConfigurationDialog.setTabOrder(self.comboBoxColorOption, self.tableWidgetColorProperty)
715
        ConfigurationDialog.setTabOrder(self.tableWidgetColorProperty, self.radioButtonLoadXmlYes)
716
        ConfigurationDialog.setTabOrder(self.radioButtonLoadXmlYes, self.radioButtonLoadXmlNo)
717
        ConfigurationDialog.setTabOrder(self.radioButtonLoadXmlNo, self.radioButtonSaveUnknownYes)
718
        ConfigurationDialog.setTabOrder(self.radioButtonSaveUnknownYes, self.radioButtonSaveUnknownNo)
719
        ConfigurationDialog.setTabOrder(self.radioButtonSaveUnknownNo, self.pushButtonClearAccessInfo)
720
        ConfigurationDialog.setTabOrder(self.pushButtonClearAccessInfo, self.radioButtonBackTextYes)
721
        ConfigurationDialog.setTabOrder(self.radioButtonBackTextYes, self.radioButtonBackTextNo)
722
        ConfigurationDialog.setTabOrder(self.radioButtonBackTextNo, self.tabWidget)
652 723

  
653 724
    def retranslateUi(self, ConfigurationDialog):
654 725
        _translate = QtCore.QCoreApplication.translate
......
662 733
        self.radioButtonMode1.setText(_translate("ConfigurationDialog", "Default"))
663 734
        self.radioButtonMode2.setText(_translate("ConfigurationDialog", "Advanced"))
664 735
        self.groupBoxText.setTitle(_translate("ConfigurationDialog", "Text Detection"))
665
        self.label_18.setText(_translate("ConfigurationDialog", "Maximum Text Size : "))
666
        self.label_17.setText(_translate("ConfigurationDialog", "Minimum Text Size : "))
667 736
        self.label_21.setText(_translate("ConfigurationDialog", "Erosion Size : "))
737
        self.label_17.setText(_translate("ConfigurationDialog", "Minimum Text Size : "))
738
        self.label_18.setText(_translate("ConfigurationDialog", "Maximum Text Size : "))
668 739
        self.label_19.setText(_translate("ConfigurationDialog", "OCR Source : "))
669
        self.label_7.setText(_translate("ConfigurationDialog", "Detected string : "))
670 740
        self.label_20.setText(_translate("ConfigurationDialog", "Expansion Size : "))
741
        self.label_7.setText(_translate("ConfigurationDialog", "Detected string : "))
671 742
        self.label_37.setText(_translate("ConfigurationDialog", "Allowed Single Text : "))
672 743
        self.label_22.setText(_translate("ConfigurationDialog", "Merge Size : "))
744
        self.label_39.setText(_translate("ConfigurationDialog", "Page segmentations modes"))
745
        self.labelTesseractVersion.setText(_translate("ConfigurationDialog", "TextLabel"))
673 746
        self.groupBoxAttribute.setTitle(_translate("ConfigurationDialog", "Attribute"))
674 747
        self.label_6.setText(_translate("ConfigurationDialog", "Size Delimiter : "))
675 748
        self.label_24.setText(_translate("ConfigurationDialog", "Line Flow Mark Position(Percent) : "))
DTI_PID/DTI_PID/LineDetector.py
582 582

  
583 583
        return None
584 584

  
585
    def detectLineWithoutSymbol(self, area):  # path, offsetX, offsetY):
585
    def detectLineWithoutSymbol(self):  # path, offsetX, offsetY):
586 586
        '''
587 587
            @brief  detect remain line after detection using symbol info
588 588
            @author euisung
......
593 593
        from HoughBundler import HoughBundler
594 594

  
595 595
        docData = AppDocData.instance()
596
        img = area.img
597 596

  
598 597
        if True:
599 598
            imgNot = np.ones(self._image.shape, np.uint8) * 255
DTI_PID/DTI_PID/MainWindow.py
2350 2350
                svgFilePath = os.path.join(project.getSvgFilePath(), _type, name + '.svg')
2351 2351
                if os.path.isfile(svgFilePath):
2352 2352
                    svg = SymbolSvgItem.createItem(_type, None, svgFilePath, owner=None, flip=flip)
2353
                    svg.hit_ratio = symbol.hitRate
2353 2354
                    svg.buildItem(name, _type, angle, pt, size, origin, connPts, parentSymbol, childSymbol,
2354 2355
                                  hasInstrumentLabel)
2355 2356
                    svg.reCalculationRotatedItem()
DTI_PID/DTI_PID/OPCRelationDialog.py
11 11
sys.path.insert(0, os.path.dirname(os.path.realpath(__file__)) + '\\UI')
12 12
import OPCRelation_UI
13 13

  
14

  
14 15
class QOPCRelationDialog(QDialog):
15 16
    """ This OPC Relation dialog class """
16 17

  
......
31 32
        from AppDocData import AppDocData
32 33

  
33 34
        self.ui.tableWidgetSource.setColumnCount(6)
34
        self.ui.tableWidgetSource.setHorizontalHeaderLabels([self.tr('Drawing'), self.tr('Line No'), self.tr('OPC'), self.tr('Drawing'), self.tr('Line No'), self.tr('OPC')])
35
        self.ui.tableWidgetSource.setHorizontalHeaderLabels(
36
            [self.tr('Drawing'), self.tr('Line No'), self.tr('OPC'), self.tr('Drawing'), self.tr('Line No'),
37
             self.tr('OPC')])
35 38
        self.ui.tableWidgetSource.horizontalHeaderItem(0).setSizeHint(QSize(25, 25))
36 39
        self.ui.tableWidgetSource.verticalHeader().hide()
37 40
        self.ui.tableWidgetSource.horizontalHeader().setStretchLastSection(True)
......
79 82
        target_opc = item.text() if item else None
80 83
        self.ui.tableWidgetTarget.setRowCount(0)
81 84
        if self._opcs:
82
            opcs = [opc for opc in self._opcs if opc['Drawing'] != drawing and opc['Line No'] == line_no and opc['OPC'] != target_opc]
85
            opcs = [opc for opc in self._opcs if
86
                    opc['Drawing'] != drawing and opc['Line No'] == line_no and opc['OPC'] != target_opc]
83 87
            self.ui.tableWidgetTarget.setRowCount(len(opcs))
84 88
            row = 0
85 89
            for opc in opcs:
......
122 126
        """ assign target opc with double clicked item """
123 127
        current = self.ui.tableWidgetSource.currentItem()
124 128
        if current:
125
            self.ui.tableWidgetSource.item(current.row(), 3).setText(self.ui.tableWidgetTarget.item(item.row(), 0).text())
126
            self.ui.tableWidgetSource.item(current.row(), 4).setText(self.ui.tableWidgetTarget.item(item.row(), 1).text())
127
            self.ui.tableWidgetSource.item(current.row(), 5).setText(self.ui.tableWidgetTarget.item(item.row(), 2).text())
129
            self.ui.tableWidgetSource.item(current.row(), 3).setText(
130
                self.ui.tableWidgetTarget.item(item.row(), 0).text())
131
            self.ui.tableWidgetSource.item(current.row(), 4).setText(
132
                self.ui.tableWidgetTarget.item(item.row(), 1).text())
133
            self.ui.tableWidgetSource.item(current.row(), 5).setText(
134
                self.ui.tableWidgetTarget.item(item.row(), 2).text())
128 135

  
129 136
    def eventFilter(self, source, event):
130 137
        """ display mouse position of graphics view """
......
144 151

  
145 152
        except Exception as ex:
146 153
            from App import App
147
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
154
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
155
                                                           sys.exc_info()[-1].tb_lineno)
148 156
            App.mainWnd().addMessage.emit(MessageType.Error, message)
149 157

  
150 158
    def accept(self):
......
165 173
                to_line_no = self.ui.tableWidgetSource.item(row, 4).text()
166 174
                to_opc = self.ui.tableWidgetSource.item(row, 5).text()
167 175
                opcs.append([from_drawing, from_line_no, from_opc, to_drawing, to_line_no, to_opc])
168
            
176

  
169 177
            app_doc_data.save_opc_relations(opcs)
170 178

  
171 179
            QDialog.accept(self)
172 180
        except Exception as ex:
173 181
            from App import App
174
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
182
            message = 'error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
183
                                                           sys.exc_info()[-1].tb_lineno)
175 184
            App.mainWnd().addMessage.emit(MessageType.Error, message)
176 185
        finally:
177
            QApplication.restoreOverrideCursor()
186
            QApplication.restoreOverrideCursor()
DTI_PID/DTI_PID/OcrResultDialog.py
63 63
        self.ui.setupUi(self)
64 64
        self.ui.detectResultTextEdit = SpellTextEdit()
65 65
        self.ui.detectResultTextEdit.setFont(QFont('Consolas', 15, QFont.Bold))
66
        self.ui.horizontalLayoutTextEdit.addWidget(self.ui.detectResultTextEdit)
66
        self.ui.horizontalLayoutTextEdit.addWidget(self.ui.detectResultTextEdit, 0)
67 67

  
68 68
        appDocData = AppDocData.instance()
69 69
        configs = appDocData.getAppConfigs('app', 'mode')
......
80 80
        self.graphicsView.setImage(self.image)
81 81
        self.graphicsView.zoomImage(False, event=None)
82 82
        self.ui.horizontalLayoutGraphicsView.addWidget(self.graphicsView)
83
        self.setLayout(self.ui.horizontalLayoutGraphicsView)
83 84

  
84 85
        self.ui.counterClockPushButton_2.clicked.connect(lambda: self.rotateImage(True))
85 86
        self.ui.clockPushButton_2.clicked.connect(lambda: self.rotateImage(False))
DTI_PID/DTI_PID/RecognitionDialog.py
338 338
                    pool.shutdown(wait=True)
339 339
                    # up to here
340 340

  
341
                    pool = futures.ThreadPoolExecutor(max_workers=THREAD_MAX_WORKER)
342
                    for symbol in targetSymbolList[2]:
343
                        if type(symbol) is list:
344
                            pool.submit(Worker.detectSymbolsOnPid, mainRes, symbol, listWidget, worker)
345
                        else:
346
                            pool.submit(Worker.detectSymbolOnPid, mainRes, symbol, listWidget, worker)
347
                    pool.shutdown(wait=True)
341
                    with futures.ThreadPoolExecutor(max_workers=THREAD_MAX_WORKER) as pool:
342
                        future_symbol = {pool.submit(Worker.detectSymbolsOnPid, mainRes, symbol, listWidget, worker):
343
                                           symbol for symbol in targetSymbolList[2]}
344
                        futures.wait(future_symbol)
348 345

  
349 346
                    if worker.isTrainingChecked:
350 347
                        import uuid
......
362 359
                        continue
363 360

  
364 361
                    pool = futures.ThreadPoolExecutor(max_workers=THREAD_MAX_WORKER)
365

  
366 362
                    searchedTextSymList = []
367 363
                    for sym in searchedSymbolList:
368
                        """
369
                        if sym.getHasInstrumentLabel() >= 1:
370
                            searchedTextSymList.append(sym)
371
                            continue
372
                        """
373 364
                        pool.submit(Worker.remove_detected_symbol_image, sym, app_doc_data.imgSrc)
374 365
                    pool.shutdown(wait=True)
375 366
                else:
......
449 440
                titleBlockTextInfoList = None
450 441
                textInfoList = []
451 442
                if worker.isTextChecked:
452
                    textAreas = textDetector.detectTextAreas(area.img if area is not None else app_doc_data.imgSrc,
443
                    textAreas, ocr_image = textDetector.detectTextAreas(area.img if area is not None else app_doc_data.imgSrc,
453 444
                                                             offset)
454 445
                    if maxProgressValue < 2 * len(textAreas):
455 446
                        for _ in range(len(textAreas) - int(maxProgressValue * 0.5)):
......
459 450
                        maxProgressValue = int(maxProgressValue * 0.5) + len(textAreas)
460 451

  
461 452
                    worker.displayTitle.emit(worker.tr('Detecting texts...'))
462
                    textDetector.recognizeText(app_doc_data.imgSrc, (0, 0), textAreas, searchedSymbolList, worker,
453
                    textDetector.recognizeText(ocr_image, offset, textAreas, searchedSymbolList, worker,
463 454
                                               listWidget, maxProgressValue)
464 455
                    textInfoList = textDetector.textInfoList.copy() if textDetector.textInfoList is not None else None
465 456
                    otherTextInfoList = textDetector.otherTextInfoList.copy() if textDetector.otherTextInfoList is not None else None
......
699 690
            # line detection without symbol connection point info
700 691
            configs = app_doc_data.getConfigs('Line', 'Diagonal')
701 692
            if configs and int(configs[0].value) is 1:
702
                remainLines = detector.detectLineWithoutSymbol(area)
693
                remainLines = detector.detectLineWithoutSymbol()
703 694
                windowSize = app_doc_data.getSlidingWindowSize()
704 695
                thickness = int(windowSize[1])
705 696
                for line in remainLines:
......
1581 1572

  
1582 1573
    @staticmethod
1583 1574
    def detectSymbolsOnPid(mainRes, targetSymbols, listWidget, updateProgressSignal):
1584
        for detailTarget in targetSymbols:
1585
            Worker.detectSymbolOnPid(mainRes, detailTarget, listWidget, updateProgressSignal)
1575
        if type(targetSymbols) is list:
1576
            for detailTarget in targetSymbols:
1577
                Worker.detectSymbolOnPid(mainRes, detailTarget, listWidget, updateProgressSignal)
1578
        else:
1579
            Worker.detectSymbolOnPid(mainRes, targetSymbols, listWidget, updateProgressSignal)
1586 1580

  
1587 1581
    @staticmethod
1588 1582
    def convertDirectionCodeToValue(directionCode):
......
1683 1677
    @staticmethod
1684 1678
    def remove_detected_symbol_image(sym, imgSrc):
1685 1679
        """remove detected symbol image from drawing image"""
1686
        global ocrCompletedSrc
1687 1680
        global threadLock
1688 1681

  
1689 1682
        path = sym.getPath()
DTI_PID/DTI_PID/Shapes/SymbolSvgItem.py
57 57
        self.childSymbol = ''
58 58
        self.hasInstrumentLabel = 0
59 59
        self.flip = flip
60
        self.hit_ratio = None
60 61
        # attributeType uid
61 62
        self.attribute = ''
62 63
        self._properties = {SymbolProp(None, 'Supplied By', 'String'): None}
......
648 649
            self.currentPointModeIndex = 0
649 650
            self.special_item_type = SpecialItemTypes.instance().find_match_exactly(self)
650 651

  
651
            tooltip = '<b>{}</b><br>{}={}'.format(str(self.uid), self.type, self.name)
652
            tooltip = f"<b>{str(self.uid)}</b><br>{self.type}={self.name}"
653
            if self.hit_ratio:
654
                tooltip += f"<br><li>recognition ratio={self.hit_ratio}"
652 655
            self.setToolTip(tooltip)
653 656

  
654 657
            return True
DTI_PID/DTI_PID/SymbolTreeWidget.py
72 72
                    editSymbolAction = QAction(self.tr("Edit Symbol"))
73 73
                    editSymbolAction.triggered.connect(lambda: self.editSymbolActionClickEvent(item, 0))
74 74
                    menu.addAction(editSymbolAction)
75
                    editDisplaySymbolAction = QAction(self.tr("Edit Symbol for Dispay"))
75
                    editDisplaySymbolAction = QAction(self.tr("Edit Symbol for Display"))
76 76
                    editDisplaySymbolAction.triggered.connect(lambda: self.editDisplaySymbolActionClickEvent(item, 0))
77 77
                    menu.addAction(editDisplaySymbolAction)
78 78
                displaySymbolAction = QAction(self.tr("Display Symbol"))
......
200 200
        try:
201 201
            app_doc_data = AppDocData.instance()
202 202

  
203
            symbolTypeList = AppDocData.instance().getSymbolTypeList()
203
            symbolTypeList = app_doc_data.getSymbolTypeList()
204 204
            for symbolType in symbolTypeList:
205 205
                if not symbolType[1]: continue  # skip if category is empty
206 206
                parent = QTreeWidgetItem(self, [symbolType[2]])
207 207
                parent.setData(0, self.TREE_DATA_ROLE, symbolType)
208
                symbolList = AppDocData.instance().getSymbolListByType('UID', symbolType[0])
208
                symbolList = app_doc_data.getSymbolListByType('UID', symbolType[0])
209 209
                for symbol in symbolList:
210 210
                    symbolItem = QTreeWidgetItem(parent, [symbol.getName()])
211 211
                    symbolItem.setData(0, self.TREE_DATA_ROLE, symbol)
DTI_PID/DTI_PID/TextDetector.py
38 38
    '''
39 39

  
40 40
    def detectTextAreas(self, img, offset):
41
        tInfoList = []
42 41
        try:
43
            tInfoList = self.getTextAreaInfo(img, offset[0], offset[1])
42
            return self.getTextAreaInfo(img, offset[0], offset[1])
44 43
        except Exception as ex:
45 44
            print('error occurred({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename,
46 45
                                                       sys.exc_info()[-1].tb_lineno))
47 46

  
48
        return tInfoList
47
        return None, None
49 48

  
50 49
    '''
51 50
        @brief      Get Text Area info by contour
......
58 57
    def getTextAreaInfo(self, imgGray, offsetX, offsetY):
59 58
        from AppDocData import AppDocData
60 59

  
61
        appDocData = AppDocData.instance()
62
        project = appDocData.getCurrentProject()
60
        app_doc_data = AppDocData.instance()
61
        project = app_doc_data.getCurrentProject()
63 62

  
64
        configs = appDocData.getConfigs('Text Size', 'Max Text Size')
63
        configs = app_doc_data.getConfigs('Text Size', 'Max Text Size')
65 64
        maxTextSize = int(configs[0].value) if 1 == len(configs) else 100
66 65
        minSize = 5
67 66

  
68
        contourImg = np.ones(imgGray.shape, np.uint8) * 255
67
        ocr_image = np.ones(imgGray.shape, np.uint8) * 255
69 68
        binaryImg, mask = cv2.threshold(imgGray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
70 69

  
71 70
        contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)
......
76 75

  
77 76
            # skip one which size is greater than max size or less then minimum size
78 77
            if area >= 0:
79
                if (w > maxTextSize or h > maxTextSize) or (w <= minSize and h <= minSize): continue
78
                if (w > maxTextSize or h > maxTextSize) or (w <= minSize and h <= minSize):
79
                    continue
80 80

  
81 81
            if area >= 0:
82
                cv2.drawContours(contourImg, [contour], -1, (0, 0, 0), -1)
83
                cv2.drawContours(contourImg, [contour], -1, (255, 255, 255), 1)
82
                cv2.drawContours(ocr_image, [contour], -1, (0, 0, 0), -1)
83
                cv2.drawContours(ocr_image, [contour], -1, (255, 255, 255), 1)
84 84
            else:
85
                cv2.drawContours(contourImg, [contour], -1, (255, 255, 255), -1)
85
                cv2.drawContours(ocr_image, [contour], -1, (255, 255, 255), -1)
86 86

  
87
        path = os.path.join(project.getTempPath(), 'OCR_{}.png'.format(appDocData.imgName))
88
        cv2.imwrite(path, contourImg)
87
        path = os.path.join(project.getTempPath(), 'OCR_{}.png'.format(app_doc_data.imgName))
88
        cv2.imwrite(path, ocr_image)
89 89

  
90 90
        rects = []
91
        configs = appDocData.getConfigs('Text Recognition', 'Expand Size')
91
        configs = app_doc_data.getConfigs('Text Recognition', 'Expand Size')
92 92
        expandSize = int(configs[0].value) if 1 == len(configs) else 10
93
        configs = appDocData.getConfigs('Text Recognition', 'Shrink Size')
93
        configs = app_doc_data.getConfigs('Text Recognition', 'Shrink Size')
94 94
        shrinkSize = int(configs[0].value) if 1 == len(configs) else 0
95 95

  
96
        eroded = cv2.erode(contourImg, np.ones((expandSize, expandSize), np.uint8))
97
        # path = os.path.join(project.getTempPath(), 'ERODED_OCR_{}.png'.format(appDocData.imgName))
98
        # cv2.imwrite(path, eroded)
99

  
96
        eroded = cv2.erode(ocr_image, np.ones((expandSize, expandSize), np.uint8))
100 97
        eroded = cv2.bitwise_not(eroded)
101
        # path = os.path.join(project.getTempPath(), 'bitwise_not_{}.png'.format(appDocData.imgName))
102
        # cv2.imwrite(path, eroded)
103 98

  
99
        bboxes = []
104 100
        contours, hierarchy = cv2.findContours(eroded, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
105 101
        for contour in contours:
106 102
            area = cv2.contourArea(contour, True)
107 103
            if area < 0:
108 104
                [x, y, w, h] = cv2.boundingRect(contour)
109

  
110
                img = contourImg[y:y + h, x:x + w]
111
                img = cv2.bitwise_not(img)
112

  
113
                horizontal, max_width = 0, 0
114
                vertical, max_height = 0, 0
115
                _contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
116
                for xx in _contours:
117
                    [_x, _y, _w, _h] = cv2.boundingRect(xx)
118
                    cv2.rectangle(img, (_x, _y), (_x + _w, _y + _h), 255, 1)
119

  
120
                    max_width = _x if _x > max_width else max_width
121
                    max_height = _y if _y > max_height else max_height
122

  
123
                    if (_w < _h) or (_w > maxTextSize and _h < maxTextSize):  # width is greater than height
124
                        horizontal += 1 + (_w * _h) / (w * h)
125
                    else:
126
                        vertical += 1 + (_w * _h) / (w * h)
127

  
128
                if (w < 10 and h < 10) or (
129
                        max_width > maxTextSize and max_height > maxTextSize): continue;  # skip too small or big one
130

  
131
                """
132
                if w > maxTextSize:
133
                    horizontal = 1
134
                elif h > maxTextSize:
135
                    vertical = 1
105
                bboxes.append(QRect(x, y, w, h))
106

  
107
        # exclude bounding boxes contains child bounding box
108
        not_containing_bbox = []
109
        for bbox in bboxes:
110
            matches = [_bbox for _bbox in bboxes if bbox != _bbox and bbox.contains(_bbox)]
111
            if not matches:
112
                not_containing_bbox.append(bbox)
113
        # up to here
114

  
115
        for bbox in not_containing_bbox:
116
            x, y = bbox.left(), bbox.top()
117
            w, h = bbox.width(), bbox.height()
118
            img = ocr_image[bbox.top():bbox.bottom(), bbox.left():bbox.right()]
119
            img = cv2.bitwise_not(img)
120

  
121
            horizontal, max_width = 0, 0
122
            vertical, max_height = 0, 0
123
            _contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
124
            for xx in _contours:
125
                [_x, _y, _w, _h] = cv2.boundingRect(xx)
126

  
127
                max_width = _x if _x > max_width else max_width
128
                max_height = _y if _y > max_height else max_height
129

  
130
                if (_w < _h) or (_w > maxTextSize > _h):  # width is greater than height
131
                    horizontal += 1 + (_w * _h) / (w * h)
136 132
                else:
137
                    if shrinkSize > 0:
138
                        img = cv2.erode(img, np.ones((shrinkSize,shrinkSize), np.uint8))
133
                    vertical += 1 + (_w * _h) / (w * h)
139 134

  
140
                    _contours, _ = cv2.findContours(img, cv2.RETR_CCOMP, cv2.CHAIN_APPROX_SIMPLE)
141
                    for xx in _contours:
142
                        [_x, _y, _w, _h] = cv2.boundingRect(xx)
143
                        cv2.rectangle(img, (_x, _y), (_x+_w, _y+_h), 255, 1)
135
            if (w < minSize and h < minSize) or (max_width > maxTextSize and max_height > maxTextSize):
136
                continue  # skip too small or big one
144 137

  
145
                        if (_w < _h) or (_w > maxTextSize and _h < maxTextSize): # width is greater than height
146
                            horizontal += 1 + (_w*_h)/(w*h)
147
                        else:
148
                            vertical += 1 + (_w*_h)/(w*h)
149
                """
150

  
151
                """
152
                if horizontal > vertical:
153
                    filePath = os.path.join(project.getTempPath(), "Tile", "H-{}-{}-{}-{}.png".format(x,y,w,h))
154
                else:
155
                    filePath = os.path.join(project.getTempPath(), "Tile", "V-{}-{}-{}-{}.png".format(x,y,w,h))
156
                cv2.imwrite(filePath, img)
157
                """
138
            rects.append([0 if horizontal > vertical else 90, QRect(x, y, w, h)])
158 139

  
159
                rects.append([0 if horizontal > vertical else 90, QRect(x, y, w, h)])
160

  
161
        configs = appDocData.getConfigs('Text Recognition', 'Merge Size')
140
        configs = app_doc_data.getConfigs('Text Recognition', 'Merge Size')
162 141
        mergeSize = int(configs[0].value) if 1 == len(configs) else 10
163 142
        # merge rectangles
164
        intersected = True
165
        while intersected:
166
            intersected = False
167
            for rect in rects[:]:  # clone rects
168
                if 0 == rect[0]:
169
                    rectExpand = rect[1].adjusted(-mergeSize, 0, mergeSize, 0)
170
                else:
171
                    rectExpand = rect[1].adjusted(0, -mergeSize, 0, mergeSize)
172

  
173
                matches = [x for x in rects if (x[0] == rect[0]) and rectExpand.intersects(x[1])]
174
                if len(matches) > 1:
175
                    united = matches[0]
176
                    for _rect in matches:
177
                        united[1] = united[1].united(_rect[1])
178
                        if _rect in rects: rects.remove(_rect)
179
                    rects.append(united)
180
                    intersected = True
181
                    break
143
        interestings = []
144
        while rects:
145
            rect = rects.pop()
146

  
147
            if 0 == rect[0]:    # x-direction text
148
                rectExpand = rect[1].adjusted(-mergeSize, 0, mergeSize, 0)
149
                matches = [x for x in rects if (x[0] == rect[0]) and
150
                           abs(x[1].height() - rect[1].height()) < (x[1].height() + rect[1].height())*0.5 and
151
                           abs(x[1].center().y() - rect[1].center().y()) < rect[1].height()*0.5 and
152
                           rectExpand.intersects(x[1])]
153
            else:               # y -direction text
154
                rectExpand = rect[1].adjusted(0, -mergeSize, 0, mergeSize)
155
                matches = [x for x in rects if (x[0] == rect[0]) and
156
                           abs(x[1].width() - rect[1].width()) < (x[1].width() + rect[1].width())*0.5 and
157
                           abs(x[1].center().x() - rect[1].center().x()) < rect[1].width()*0.5 and
158
                           rectExpand.intersects(x[1])]
159

  
160
            if matches:
161
                for _rect in matches:
162
                    rect[1] = rect[1].united(_rect[1])
163
                    if _rect in rects:
164
                        rects.remove(_rect)
165
                rects.append(rect)
166
            else:
167
                interestings.append(rect)
182 168

  
183 169
        list = []
184
        for rect in rects:
170
        for rect in interestings:
185 171
            angle = rect[0]
186 172
            list.append(ti.TextInfo('', round(offsetX) + rect[1].x(), round(offsetY) + rect[1].y(), rect[1].width(),
187 173
                                    rect[1].height(), angle))
188 174

  
189
            x = rect[1].x()
190
            y = rect[1].y()
191
            w = rect[1].width()
192
            h = rect[1].height()
193
            img = contourImg[y:y + h, x:x + w]
194
            ## DEBUG
195
            # if angle == 0:
196
            #    filePath = os.path.join(project.getTempPath(), "Tile", "H-{}-{}-{}-{}.png".format(x,y,w,h))
197
            # else:
198
            #    filePath = os.path.join(project.getTempPath(), "Tile", "V-{}-{}-{}-{}.png".format(x,y,w,h))
199
            # cv2.imwrite(filePath, img)
200
            ## up to here
201

  
202
        return list
175
        return list, ocr_image
203 176

  
204 177
    '''
205 178
        @brief      recognize text of given text info
......
300 273
            project = app_doc_data.getCurrentProject()
301 274

  
302 275
            text_info_array = np.array_split(tInfoList, THREAD_MAX_WORKER)
303
            pool = futures.ThreadPoolExecutor(max_workers=THREAD_MAX_WORKER)
304
            for tInfo in text_info_array:
276
            with futures.ThreadPoolExecutor(max_workers=THREAD_MAX_WORKER) as pool:
277
                future_text = {pool.submit(TextDetector.recognizeTextFromImage, tInfo, imgSrc, offset,
278
                                       searchedSymbolList, worker, listWidget, maxProgressValue):
279
                               tInfo for tInfo in text_info_array}
280
                """
305 281
                future = pool.submit(TextDetector.recognizeTextFromImage, tInfo, imgSrc, offset,
306 282
                                     searchedSymbolList, worker, listWidget, maxProgressValue)
307
                data = future.result()
308
                if data:
309
                    self.textInfoList.extend(data)
310
            pool.shutdown(wait=True)
283
                """
284
                for future in futures.as_completed(future_text):
285
                    try:
286
                        data = future.result()
287
                        if data:
288
                            self.textInfoList.extend(data)
289
                    except Exception as ex:
290
                        message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
291
                                                                       sys.exc_info()[-1].tb_lineno)
292
                        worker.displayLog.emit(MessageType.Error, message)
311 293

  
312 294
            if onlyTextArea:
313 295
                return
......
325 307
                                                     conf=whiteCharList[0].value)
326 308
                        self.otherTextInfoList.append([area.name, texts])
327 309
                else:
328
                    img = imgSrc[round(area.y):round(area.y + area.height),
310
                    img = app_doc_data.imgSrc[round(area.y):round(area.y + area.height),
329 311
                          round(area.x):round(area.x + area.width)]
330 312
                    if len(whiteCharList) is 0:
331 313
                        texts = TOCR.getTextInfo(img, (area.x, area.y), 0, language='eng')
......
343 325
                    area = Area(titleBlockProp[0])
344 326
                    area.parse(titleBlockProp[2])
345 327
                    if not (titleBlockProp[3] and titleBlockProp[3] != ''):
346
                        img = imgSrc[round(area.y):round(area.y + area.height),
328
                        img = app_doc_data.imgSrc[round(area.y):round(area.y + area.height),
347 329
                              round(area.x):round(area.x + area.width)]
348 330
                        if len(whiteCharList) is 0:
349 331
                            texts = TOCR.getTextInfo(img, (area.x, area.y), 0, language=app_doc_data.OCRData)
......
357 339
                    self.titleBlockTextInfoList.append([area.name, texts])
358 340

  
359 341
            if worker is not None: worker.updateProgress.emit(maxProgressValue, None)
342

  
343
            """
344
            for text_box in tInfoList:
345
                x = text_box.getX()
346
                y = text_box.getY()
347
                cv2.rectangle(imgSrc, (x - offset[0], y - offset[1]),
348
                              (x - offset[0] + text_box.getW(), y - offset[1] + text_box.getH()), 1, 1)
349
            cv2.imwrite('c:\\Temp\\text_box.png', imgSrc)
350
            """
360 351
        except Exception as ex:
361 352
            message = 'error occurred({}) in {}:{}'.format(repr(ex), sys.exc_info()[-1].tb_frame.f_code.co_filename,
362 353
                                                           sys.exc_info()[-1].tb_lineno)
DTI_PID/DTI_PID/UI/Configuration.ui
6 6
   <rect>
7 7
    <x>0</x>
8 8
    <y>0</y>
9
    <width>632</width>
10
    <height>616</height>
9
    <width>648</width>
10
    <height>631</height>
11 11
   </rect>
12 12
  </property>
13 13
  <property name="font">
......
166 166
         <layout class="QGridLayout" name="gridLayout_14">
167 167
          <item row="0" column="0">
168 168
           <layout class="QGridLayout" name="gridLayout_25">
169
            <item row="4" column="3">
170
             <widget class="QSpinBox" name="maxTextSizeSpinBox">
169
            <item row="5" column="1">
170
             <widget class="QSpinBox" name="minTextSizeSpinBox">
171 171
              <property name="sizePolicy">
172 172
               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
173 173
                <horstretch>0</horstretch>
174 174
                <verstretch>0</verstretch>
175 175
               </sizepolicy>
176 176
              </property>
177
              <property name="maximumSize">
178
               <size>
179
                <width>16777215</width>
180
                <height>16777215</height>
181
               </size>
182
              </property>
177 183
              <property name="value">
178
               <number>60</number>
184
               <number>30</number>
179 185
              </property>
180 186
             </widget>
181 187
            </item>
182
            <item row="4" column="1">
183
             <widget class="QSpinBox" name="minTextSizeSpinBox">
188
            <item row="5" column="3">
189
             <widget class="QSpinBox" name="maxTextSizeSpinBox">
184 190
              <property name="sizePolicy">
185 191
               <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
186 192
                <horstretch>0</horstretch>
187 193
                <verstretch>0</verstretch>
188 194
               </sizepolicy>
189 195
              </property>
190
              <property name="maximumSize">
191
               <size>
192
                <width>16777215</width>
193
                <height>16777215</height>
194
               </size>
195
              </property>
196 196
              <property name="value">
197
               <number>30</number>
197
               <number>60</number>
198 198
              </property>
199 199
             </widget>
200 200
            </item>
201 201
            <item row="4" column="2">
202
             <widget class="QLabel" name="label_18">
202
             <widget class="QLabel" name="label_21">
203 203
              <property name="text">
204
               <string>Maximum Text Size : </string>
204
               <string>Erosion Size : </string>
205 205
              </property>
206 206
             </widget>
207 207
            </item>
208
            <item row="4" column="0">
208
            <item row="5" column="0">
209 209
             <widget class="QLabel" name="label_17">
210 210
              <property name="text">
211 211
               <string>Minimum Text Size : </string>
212 212
              </property>
213 213
             </widget>
214 214
            </item>
215
            <item row="3" column="2">
216
             <widget class="QLabel" name="label_21">
215
            <item row="5" column="2">
216
             <widget class="QLabel" name="label_18">
217 217
              <property name="text">
218
               <string>Erosion Size : </string>
218
               <string>Maximum Text Size : </string>
219 219
              </property>
220 220
             </widget>
221 221
            </item>
222
            <item row="3" column="3">
223
             <widget class="QSpinBox" name="spinBoxShrinkSize">
222
            <item row="4" column="1">
223
             <widget class="QSpinBox" name="spinBoxExpandSize">
224 224
              <property name="minimumSize">
225 225
               <size>
226 226
                <width>100</width>
......
229 229
              </property>
230 230
             </widget>
231 231
            </item>
232
            <item row="3" column="1">
233
             <widget class="QSpinBox" name="spinBoxExpandSize">
232
            <item row="4" column="3">
233
             <widget class="QSpinBox" name="spinBoxShrinkSize">
234 234
              <property name="minimumSize">
235 235
               <size>
236 236
                <width>100</width>
......
246 246
              </property>
247 247
             </widget>
248 248
            </item>
249
            <item row="1" column="0">
250
             <widget class="QLabel" name="label_7">
249
            <item row="4" column="0">
250
             <widget class="QLabel" name="label_20">
251 251
              <property name="text">
252
               <string>Detected string : </string>
252
               <string>Expansion Size : </string>
253 253
              </property>
254 254
             </widget>
255 255
            </item>
256
            <item row="3" column="0">
257
             <widget class="QLabel" name="label_20">
256
            <item row="1" column="0">
257
             <widget class="QLabel" name="label_7">
258 258
              <property name="text">
259
               <string>Expansion Size : </string>
259
               <string>Detected string : </string>
260 260
              </property>
261 261
             </widget>
262 262
            </item>
263
            <item row="2" column="0">
263
            <item row="3" column="0">
264 264
             <widget class="QLabel" name="label_37">
265 265
              <property name="text">
266 266
               <string>Allowed Single Text : </string>
267 267
              </property>
268 268
             </widget>
269 269
            </item>
270
            <item row="5" column="0">
270
            <item row="6" column="0">
271 271
             <widget class="QLabel" name="label_22">
272 272
              <property name="text">
273 273
               <string>Merge Size : </string>
274 274
              </property>
275 275
             </widget>
276 276
            </item>
277
            <item row="5" column="1">
277
            <item row="1" column="1" colspan="3">
278
             <widget class="QLineEdit" name="lineEditWhiteCharList"/>
279
            </item>
280
            <item row="3" column="1">
281
             <widget class="QLineEdit" name="lineEditSingleText"/>
282
            </item>
283
            <item row="6" column="1">
278 284
             <widget class="QSpinBox" name="spinBoxMergeSize">
279 285
              <property name="minimumSize">
280 286
               <size>
......
300 306
              </property>
301 307
             </widget>
302 308
            </item>
303
            <item row="2" column="1">
304
             <widget class="QLineEdit" name="lineEditSingleText"/>
309
            <item row="2" column="0">
310
             <widget class="QLabel" name="label_39">
311
              <property name="text">
312
               <string>Page segmentations modes</string>
313
              </property>
314
             </widget>
305 315
            </item>
306
            <item row="1" column="1" colspan="3">
307
             <widget class="QLineEdit" name="lineEditWhiteCharList"/>
316
            <item row="2" column="1" colspan="3">
317
             <widget class="QComboBox" name="comboBoxPageSegmentationModes"/>
318
            </item>
319
            <item row="0" column="2" colspan="2">
320
             <widget class="QLabel" name="labelTesseractVersion">
321
              <property name="text">
322
               <string>TextLabel</string>
323
              </property>
324
              <property name="alignment">
325
               <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
326
              </property>
327
             </widget>
308 328
            </item>
309 329
           </layout>
310 330
          </item>
......
1373 1393
  </layout>
1374 1394
 </widget>
1375 1395
 <tabstops>
1396
  <tabstop>comboBoxOCRData</tabstop>
1397
  <tabstop>lineEditWhiteCharList</tabstop>
1398
  <tabstop>comboBoxPageSegmentationModes</tabstop>
1399
  <tabstop>lineEditSingleText</tabstop>
1400
  <tabstop>spinBoxExpandSize</tabstop>
1401
  <tabstop>spinBoxShrinkSize</tabstop>
1402
  <tabstop>minTextSizeSpinBox</tabstop>
1403
  <tabstop>maxTextSizeSpinBox</tabstop>
1404
  <tabstop>spinBoxMergeSize</tabstop>
1405
  <tabstop>lineEditSizeDelimiter</tabstop>
1406
  <tabstop>doubleSpinBoxDetectionRange</tabstop>
1407
  <tabstop>spinBoxFlowMarkPosition</tabstop>
1408
  <tabstop>spinBoxFlowMarkLength</tabstop>
1409
  <tabstop>spinBoxMinimumSize</tabstop>
1410
  <tabstop>spinBoxUnrecognitionIgnoreStep</tabstop>
1411
  <tabstop>spinBoxDilateSize</tabstop>
1412
  <tabstop>spinBoxFlatSize</tabstop>
1413
  <tabstop>radioButtonMode1</tabstop>
1414
  <tabstop>radioButtonMode2</tabstop>
1415
  <tabstop>spinBoxMinArea</tabstop>
1416
  <tabstop>spinBoxMaxArea</tabstop>
1417
  <tabstop>spinBoxWidth</tabstop>
1418
  <tabstop>spinBoxHeight</tabstop>
1419
  <tabstop>smallLineMinLengthSpinBox</tabstop>
1420
  <tabstop>spinBoxLengthToConnectLine</tabstop>
1421
  <tabstop>comboBoxLineType</tabstop>
1422
  <tabstop>radioButtonDiagonalYes</tabstop>
1423
  <tabstop>radioButtonDiagonalNo</tabstop>
1424
  <tabstop>pushButtonLineNoAttribute</tabstop>
1425
  <tabstop>pushButtonAddProperty</tabstop>
1426
  <tabstop>pushButtonDeleteProperty</tabstop>
1427
  <tabstop>listWidgetLineNo</tabstop>
1428
  <tabstop>pushButtonTagNoAttribute</tabstop>
1429
  <tabstop>pushButtonAddTagProperty</tabstop>
1430
  <tabstop>pushButtonDeleteTagProperty</tabstop>
1431
  <tabstop>listWidgetTagNo</tabstop>
1432
  <tabstop>checkBoxNoteNoSymbolName</tabstop>
1433
  <tabstop>lineEditNoteNoSymbolName</tabstop>
1434
  <tabstop>lineEditNoteNoExpression</tabstop>
1435
  <tabstop>lineEditOPCFromPrefix</tabstop>
1436
  <tabstop>lineEditOPCToPrefix</tabstop>
1437
  <tabstop>lineEditByVendor</tabstop>
1438
  <tabstop>lineEditDrainSize</tabstop>
1376 1439
  <tabstop>lineEdit_2</tabstop>
1377 1440
  <tabstop>tableWidgetLineTypes</tabstop>
1441
  <tabstop>pushButtonInstrumentColor</tabstop>
1442
  <tabstop>pushButtonEquipColor</tabstop>
1443
  <tabstop>spinBoxSymbolOpacity</tabstop>
1444
  <tabstop>fontComboBox</tabstop>
1445
  <tabstop>radioButtonAutoSize</tabstop>
1446
  <tabstop>radioButtonFixedSize</tabstop>
1447
  <tabstop>spinBoxFontSize</tabstop>
1448
  <tabstop>radioButtonRandom</tabstop>
1449
  <tabstop>radioButtonProperty</tabstop>
1450
  <tabstop>comboBoxColorOption</tabstop>
1451
  <tabstop>tableWidgetColorProperty</tabstop>
1452
  <tabstop>radioButtonLoadXmlYes</tabstop>
1453
  <tabstop>radioButtonLoadXmlNo</tabstop>
1454
  <tabstop>radioButtonSaveUnknownYes</tabstop>
1455
  <tabstop>radioButtonSaveUnknownNo</tabstop>
1456
  <tabstop>pushButtonClearAccessInfo</tabstop>
1457
  <tabstop>radioButtonBackTextYes</tabstop>
1458
  <tabstop>radioButtonBackTextNo</tabstop>
1378 1459
  <tabstop>tabWidget</tabstop>
1379 1460
 </tabstops>
1380 1461
 <resources>
......
1416 1497
 </connections>
1417 1498
 <buttongroups>
1418 1499
  <buttongroup name="buttonGroup_3"/>
1500
  <buttongroup name="buttonGroup_2"/>
1501
  <buttongroup name="buttonGroup_5"/>
1419 1502
  <buttongroup name="buttonGroup_4"/>
1420 1503
  <buttongroup name="buttonGroup"/>
1421
  <buttongroup name="buttonGroup_5"/>
1422
  <buttongroup name="buttonGroup_2"/>
1423 1504
 </buttongroups>
1424 1505
</ui>
DTI_PID/DTI_PID/tesseract_ocr_module.py
38 38

  
39 39
tesseract_path = os.path.join(os.getenv('ALLUSERSPROFILE'), 'Digital PID', 'Tesseract-OCR')
40 40
DEFAULT_CONF = """
41
    --psm 6 -c tessedit_char_whitelist=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-~.,/!@#$%&*(){}[]<>:;+=?\\"
41
    --psm {} -c tessedit_char_whitelist=abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-~.,/!@#$%&*(){}[]<>:;+=?\\"
42 42
"""
43
DEFAULT_CONF_COMM = "--psm 6 -c preserve_interword_spaces=1"
43
DEFAULT_CONF_COMM = "--psm {} -c preserve_interword_spaces=1"
44 44

  
45 45

  
46 46
def exist_trained_data():
......
80 80
        os.environ['TESSDATA_PREFIX'] = os.path.join(tesseract_path, 'tessdata')
81 81
        textInfoList = []
82 82

  
83
        app_doc_data = AppDocData.instance()
84
        configs = app_doc_data.getConfigs('Text Recognition', 'Page Segmentation Modes')
85
        _conf = DEFAULT_CONF_COMM.format(configs[0].value if configs else '3')
83 86
        if conf:
84
            _conf = DEFAULT_CONF_COMM + f" tessedit_char_whitelist=\"{conf}\""
85
        else:
86
            _conf = DEFAULT_CONF_COMM
87
            _conf += f" tessedit_char_whitelist=\"{conf}\""
87 88

  
88
        app_doc_data = AppDocData.instance()
89 89
        oCRLang = language
90 90

  
91 91
        configs = app_doc_data.getConfigs('Text Size', 'Min Text Size')
......
102 102

  
103 103
        thickness = 3
104 104
        im = Image.fromarray(img)
105
        # add padding to increase text recognition
105 106
        im = ImageOps.expand(im, border=thickness, fill='white')
106 107
        im = im.rotate(-angle, expand=True)
107 108
        imgWidth = im.width
......
202 203

  
203 204
        for rect in merged_boxes:
204 205
            if not rect.isValid() or \
205
                    rect.left() < 0 or rect.top() < 0 or rect.right() > imgWidth or rect.bottom() > imgHeight: continue
206
                    rect.left() < 0 or rect.top() < 0 or rect.right() > imgWidth or rect.bottom() > imgHeight:
207
                continue
206 208
            if len(merged_boxes) == 1:
207 209
                cropped = im
208 210
            else:
209
                # recognition rate is increased when image has border
210
                cropped = im.crop((rect.left() - 1, imgHeight - rect.bottom() - 1, rect.right() + 1,
211
                                   imgHeight - rect.top() + 1))
211
                cropped = im.crop((rect.left(), imgHeight - rect.bottom(), rect.right(), imgHeight - rect.top()))
212
                # add padding to increase text recognition
213
                cropped = ImageOps.expand(cropped, border=thickness, fill='white')
212 214

  
213 215
            if cropped.width == 0 or cropped.height == 0:
214 216
                continue
......
231 233
                                        text_rect.width(), text_rect.height(), angle)
232 234
                textInfoList.append(text_info)
233 235

  
236
        del im
237

  
234 238
        return textInfoList
235 239
    except Exception as ex:
236 240
        from App import App

내보내기 Unified diff

클립보드 이미지 추가 (최대 크기: 500 MB)