프로젝트

일반

사용자정보

개정판 2281dace

ID2281dace3016b7b12545cdcc0f945dc732f469e4
상위 2f394152
하위 3f8f5d19

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

issue #000: remove opencv module

Change-Id: I269f4ccc5449d46c5b12f57b440b526c8441cad9

차이점 보기:

HYTOS/HYTOS/AppDocData.py
89 89
        self.imgWidth = 0
90 90
        self.imgHeight = 0
91 91
        self._OCRData = None
92
        self._imgSrc = None
93 92

  
94 93
        self._areas = []
95 94
        self.equipments = []
......
139 138
        self.imgName = None
140 139
        self.imgWidth = 0
141 140
        self.imgHeight = 0
142
        self._imgSrc = None
143 141

  
144 142
        self._areas.clear()
145 143
        self.equipments.clear()
......
270 268
        self.imgName = os.path.splitext(os.path.basename(self._imgFilePath))[0]
271 269

  
272 270
    '''
273
        @brief      getter of imgSrc
274
        @author     humkyung
275
        @date       2018.07.30
276
    '''
277
    @property
278
    def imgSrc(self):
279
        import cv2
280

  
281
        if self._imgSrc is None and self._imgFilePath is not None and os.path.isfile(self._imgFilePath):
282
            self._imgSrc = cv2.cvtColor(cv2.imread(self._imgFilePath), cv2.COLOR_BGR2GRAY)
283
            kernel = np.array([[-1,-1,-1], 
284
                   [-1, 9,-1],
285
                   [-1,-1,-1]])
286
            self._imgSrc = cv2.filter2D(self._imgSrc, -1, kernel)
287
            #blur = cv2.GaussianBlur(self._imgSrc , (5,5), 0)
288
            #smooth = cv2.addWeighted(blur, 1.5, self._imgSrc, -0.5, 0)
289
            #self._imgSrc = cv2.threshold(smooth, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
290
            self._imgSrc = cv2.threshold(self._imgSrc, 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
291
        
292
        return self._imgSrc
293

  
294
    '''
295
        @brief      setter of imgSrc
296
        @author     humkyung
297
        @date       2018.07.30
298
    '''
299
    @imgSrc.setter
300
    def imgSrc(self, value):
301
        self._imgSrc = value
302

  
303
    '''
304
        @brief      reset imgSrc
305
        @author     humkyung
306
        @date       2018.07.30
307
    '''
308
    def resetImgSrc(self):
309
        self._imgSrc = None
310

  
311
    '''
312 271
        @brief  getter of line type configs
313 272
        @author humkyung
314 273
        @date   2018.06.28
HYTOS/HYTOS/Commands/AreaZoomCommand.py
11 11
    except ImportError:
12 12
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
13 13

  
14
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
15

  
16 14
class AreaZoomCommand(AbstractCommand.AbstractCommand):
17 15
    onRejected = pyqtSignal(AbstractCommand.AbstractCommand)
18 16

  
HYTOS/HYTOS/Commands/CreateSymbolCommand.py
1
import os.path
2
import AbstractCommand
3
try:
4
    from PyQt5.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR
5
    from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QCursor
6
    from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog
7
except ImportError:
8
    try:
9
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR
10
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QCursor
11
    except ImportError:
12
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
13
import sys, os
14
from AppDocData import AppDocData
15
import cv2
16
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
17
import SymbolEditorDialog
18
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + '\\Shapes')
19
from SymbolSvgItem import SymbolSvgItem
20

  
21
class CreateSymbolCommand(AbstractCommand.AbstractCommand):
22
    '''
23
        @history    2018.05.04  Jeongwoo    Add Parameter
24
    '''
25
    def __init__(self, imageViewer, resultTreeWidget, symbolTreeWidget):
26
        super(CreateSymbolCommand, self).__init__(imageViewer)
27
        self.name = 'CreateSymbol'
28
        self.imageViewer.setCursor(QCursor(Qt.CrossCursor))
29
        self.resultTreeWidget = resultTreeWidget
30
        self.symbolTreeWidget = symbolTreeWidget
31
    
32
    '''
33
        @brief  crop image by rectangle selected by user
34
        @history    2018.05.02  Jeongwoo    Init self.offsetX and self.offsetY
35
                                            Add QtImageViewer.startPointChanged.emit
36
                    2018.05.03  Jeongwoo    Make Svg/Image File Path by SymbolBase.getSvgFileFullePath() and SymbolBase.getImageFileFullPath()
37
                    2018.05.04  Jeongwoo    Add self.symbolTreeWidget.initTreeWidget()
38
                    2018.06.08  Jeongwoo    Add Parameter on SymbolSvgItem.buildItem()
39
    '''
40
    def execute(self, param):
41
        event = param[1]
42
        scenePos = param[2]
43
        if 'mousePressEvent' == param[0] and event.button() == Qt.LeftButton:
44
            self.imageViewer.setDragMode(QGraphicsView.RubberBandDrag)
45
            self.imageViewer.leftMouseButtonPressed.emit(scenePos.x(), scenePos.y())
46
            QGraphicsView.mousePressEvent(self.imageViewer, event)
47
        elif 'mouseReleaseEvent' == param[0] and event.button() == Qt.LeftButton:
48
            try:
49
                QGraphicsView.mouseReleaseEvent(self.imageViewer, event)
50
                viewBBox = self.imageViewer.zoomStack[-1] if len(self.imageViewer.zoomStack) else self.imageViewer.sceneRect()
51
                selectionBBox = self.imageViewer.scene.selectionArea().boundingRect().intersected(viewBBox)
52
                if selectionBBox.isValid():
53
                    croppedImage = self.imageViewer.image().copy(selectionBBox.toAlignedRect())
54
                    symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self.imageViewer, croppedImage, AppDocData.instance().getCurrentProject())
55
                    (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
56
                    self.symbolTreeWidget.initSymbolTreeWidget()
57
                    if isAccepted:
58
                        if isImmediateInsert:
59
                            svgPath = newSym.getSvgFileFullPath()
60
                            img = cv2.imread(newSym.getImageFileFullPath(), 1)
61
                            w, h = (0, 0)
62
                            if len(img.shape[::-1]) == 2:
63
                                w, h = img.shape[::-1]
64
                            else:
65
                                _chan, w, h = img.shape[::-1]
66
                            svg = SymbolSvgItem(svgPath)
67
                            svg.buildItem(newSym.getName(), newSym.getType(), 0, [selectionBBox.x()+offsetX, selectionBBox.y()+offsetY], [w, h], [float(x) for x in newSym.getOriginalPoint().split(',')], [(float(x.split(',')[0]), float(x.split(',')[1])) for x in newSym.getConnectionPoint().split('/')], newSym.getBaseSymbol(), newSym.getAdditionalSymbol())
68

  
69
                            #### lambda param=svg : bind 'svg' object to lambda('param')
70
                            #### If case of 'lambda svg=svg:', function uses the 'svg' value bound to lambda
71
                            svg.clicked.connect(lambda param=svg: self.resultTreeWidget.findItem(param))
72
                            svg.transfer.onRemoved.connect(self.resultTreeWidget.itemRemoved)
73
                            svg.addSvgItemToScene(self.imageViewer.scene)
74
                            for connector in svg.connectors:
75
                                self.imageViewer.scene.addItem(connector)
76

  
77
            finally:
78
                self.imageViewer.setDragMode(QGraphicsView.NoDrag)
79
                self.imageViewer.leftMouseButtonReleased.emit(scenePos.x(), scenePos.y())
80
                pass
81
        self.isTreated = False
82

  
83
    def undo(self):
84
        pass
85

  
86
    def redo(self):
87
        pass
HYTOS/HYTOS/Commands/FenceCommand.py
10 10
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QCursor
11 11
    except ImportError:
12 12
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
13
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
14 13

  
15 14
class FenceCommand(AbstractCommand.AbstractCommand):
16 15
    onSuccess = pyqtSignal(float, float, float, float)
HYTOS/HYTOS/Commands/FitImageCommand.py
1
# coding: utf-8
2

  
3
import os.path
4
import sys
5

  
6
try:
7
    from PyQt5.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect
8
    from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QCursor, QColor
9
    from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog
10
except ImportError:
11
    try:
12
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect
13
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QCursor, QColor
14
    except ImportError:
15
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
16
import numpy as np
17
 
18
import AbstractCommand
19

  
20
class FitImageCommand(AbstractCommand.AbstractCommand):
21
    WHITE_PIXEL = (255, 255, 255, 255)
22
    BLACK_PIXEL = (0, 0, 0, 255)
23

  
24
    '''
25
        @history    2018.05.02  Jeongwoo    Change variable name (adjustX, adjustY → offsetX, offsetY)
26
    '''
27
    def __init__(self, imageViewer):
28
        super(FitImageCommand, self).__init__(imageViewer)
29
        self.name = 'FitImage' 
30
        self.imageViewer.setCursor(QCursor(Qt.CrossCursor))
31

  
32
        boundingBox = self.getImageBoundingBox()
33
        croppedImage = self.imageViewer.image().copy(boundingBox)
34
        self.imageViewer.setImage(croppedImage)
35
        self.offsetX = boundingBox.left()
36
        self.offsetY = boundingBox.top()
37

  
38
    '''
39
        @history    2018.05.02  Jeongwoo    Change method name (getAdjust → getOffset)
40
    '''
41
    def getOffset(self):
42
        return (self.offsetX, self.offsetY)
43

  
44
    def convertQImageToMat(self, incomingImage):
45
        '''  Converts a QImage into an opencv MAT format  '''
46

  
47
        try:
48
            incomingImage = incomingImage.convertToFormat(QImage.Format_RGBA8888)
49

  
50
            width = incomingImage.width()
51
            height = incomingImage.height()
52

  
53
            ptr = incomingImage.bits()
54
            ptr.setsize(incomingImage.byteCount())
55
            arr = np.array(ptr).reshape(height, width, 4)  #  Copies the data
56
            return arr
57
        except Exception as ex:
58
            print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno))
59

  
60
    '''
61
        @brief      get minimum image bouding box
62
        @author     jeongwoo
63
        @date       
64
    '''
65
    def getImageBoundingBox(self):
66
        import cv2
67
        black = 0
68

  
69
        image = self.convertQImageToMat(self.imageViewer.image())
70
        image = cv2.threshold(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY), 0, 255, cv2.THRESH_BINARY+cv2.THRESH_OTSU)[1]
71
        indices = np.where(image == [0])
72
        minx, maxx = min(indices[1]), max(indices[1])
73
        miny, maxy = min(indices[0]), max(indices[0])
74
        
75
        return QRect(minx, miny, (maxx - minx) + 1, (maxy - miny) + 1)
76

  
77
    '''
78
        @brief  DO NOTHING
79
    '''
80
    def execute(self, param):
81
        pass
82

  
83
    def undo(self):
84
        pass
85

  
86
    def redo(self):
87
        pass
HYTOS/HYTOS/Commands/PlaceLineCommand.py
1
# coding: utf-8
2
"""
3
This is place line module
4
"""
5

  
6
import os.path
7
import AbstractCommand
8
try:
9
    from PyQt5.QtCore import Qt, QPointF, QRectF, pyqtSignal, QT_VERSION_STR
10
    from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QCursor, QTransform
11
    from PyQt5.QtWidgets import QGraphicsView, QGraphicsScene, QFileDialog
12
except ImportError:
13
    try:
14
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR
15
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QCursor
16
    except ImportError:
17
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
18

  
19
class PlaceLineCommand(AbstractCommand.AbstractCommand):
20
    """
21
    This is place line class
22
    """
23

  
24
    onSuccess = pyqtSignal()
25
    onRejected = pyqtSignal(AbstractCommand.AbstractCommand)
26

  
27
    def __init__(self, imageViewer):
28
        super(PlaceLineCommand, self).__init__(imageViewer)
29
        self.name = 'PlaceLine' 
30
        self.imageViewer.setCursor(QCursor(Qt.CrossCursor))
31

  
32
        self._polyline = None
33
    
34
    '''
35
        @brief      reset command status
36
        @author     humkyung
37
        @date       2018.07.23
38
    '''
39
    def reset(self):
40
        self._polyline = None
41

  
42
    '''
43
        @brief      place a line
44
        @author     humkyung
45
        @date       2018.07.23
46
    '''
47
    def execute(self, param):
48
        import shapely
49
        from EngineeringConnectorItem import QEngineeringConnectorItem
50
        from SymbolSvgItem import SymbolSvgItem
51
        from EngineeringPolylineItem import QEngineeringPolylineItem
52
        from EngineeringLineItem import QEngineeringLineItem
53

  
54
        self.isTreated = False
55

  
56
        event = param[1]
57
        if 'mousePressEvent' == param[0] and event.button() == Qt.LeftButton:
58
            if self._polyline is None:
59
                selected = self.imageViewer.scene.itemAt(param[2], QTransform())
60
                if selected is not None and type(selected) is QEngineeringConnectorItem:
61
                    self._polyline = QEngineeringPolylineItem()
62
                    self._polyline._vertices.append(selected.center())
63
                    self.imageViewer.scene.addItem(self._polyline)
64
                    self.imageViewer.scene.setFocusItem(self._polyline)
65
                elif selected is not None and type(selected) is QEngineeringLineItem:
66
                    length = selected.length()*0.5
67
                    dir = selected.perpendicular()
68
                    start = [param[2].x() - dir[0]*length, param[2].y() - dir[1]*length]
69
                    end = [param[2].x() + dir[0]*length, param[2].y() + dir[1]*length]
70
                    pt = selected.intersection([start, end])
71
                    if (pt is not None) and (type(pt) == shapely.geometry.point.Point):
72
                        self._polyline = QEngineeringPolylineItem()
73
                        self._polyline._vertices.append([pt.x, pt.y])
74
                        self.imageViewer.scene.addItem(self._polyline)
75
                        self.imageViewer.scene.setFocusItem(self._polyline)
76
            else:
77
                try:
78
                    QGraphicsView.mouseReleaseEvent(self.imageViewer, event)
79
                    self._polyline._vertices.append(self._polyline._pt)
80
                    self._polyline.update()
81
                finally:
82
                    pass
83
        elif 'mouseReleaseEvent' == param[0] and event.button() == Qt.RightButton and self._polyline is not None:
84
            self.onSuccess.emit()
85
        elif 'mouseReleaseEvent' == param[0] and event.button() == Qt.RightButton and self._polyline is None:
86
            self.onRejected.emit(self)
87
        elif 'mouseMoveEvent' == param[0] and self._polyline is not None:
88
            self._polyline.onMouseMoved(event, param[2])
89
        elif 'keyPressEvent' == param[0]:
90
            if event.key() == Qt.Key_Escape:
91
                self.onRejected.emit(self)
92
                self.isTreated = False
93
            elif event.key() == Qt.Key_A:   # axis lock mode
94
                self._polyline.drawing_mode = QEngineeringPolylineItem.AXIS_MODE
95
            elif event.key() == Qt.Key_F:   # free drawing mode 
96
                self._polyline.drawing_mode = QEngineeringPolylineItem.FREE_MODE
97

  
98
    def undo(self):
99
        pass
100

  
101
    def redo(self):
102
        pass
HYTOS/HYTOS/Commands/PlacePolygonCommand.py
1
# coding: utf-8
2
import os.path
3
import AbstractCommand
4
try:
5
    from PyQt5.QtCore import *
6
    from PyQt5.QtGui import *
7
    from PyQt5.QtWidgets import *
8
except ImportError:
9
    try:
10
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR
11
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QCursor
12
    except ImportError:
13
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
14

  
15
class PlacePolygonCommand(AbstractCommand.AbstractCommand):
16
    """
17
    This is place polygon class
18
    """
19

  
20
    onSuccess = pyqtSignal()
21
    onRejected = pyqtSignal(AbstractCommand.AbstractCommand)
22

  
23
    def __init__(self, imageViewer):
24
        super(PlacePolygonCommand, self).__init__(imageViewer)
25
        self.name = 'PlaceLine' 
26
        self.imageViewer.setCursor(QCursor(Qt.CrossCursor))
27

  
28
        self._polyline = None
29
    
30

  
31

  
32
    '''
33
        @brief      reset command status
34
        @author     humkyung
35
        @date       2018.07.23
36
    '''
37
    def reset(self):
38
        self._polyline = None
39

  
40
    '''
41
        @brief      place a line
42
        @author     humkyung
43
        @date       2018.07.23
44
    '''
45
    def execute(self, param):
46
        import shapely
47
        from EngineeringConnectorItem import QEngineeringConnectorItem
48
        from EngineeringPolylineItem import QEngineeringPolylineItem
49
        from EngineeringLineItem import QEngineeringLineItem
50

  
51
        self.isTreated = False
52

  
53
        event = param[1]
54
        if 'mousePressEvent' == param[0] and event.button() == Qt.LeftButton:
55
            try:
56
                if self._polyline is None:
57
                    self._polyline = QEngineeringPolylineItem()
58
                    self._polyline.drawing_mode = QEngineeringPolylineItem.FREE_MODE
59
                    self._polyline._vertices.append((param[2].x(), param[2].y()))
60
                    self.imageViewer.scene.addItem(self._polyline)
61
                    self.imageViewer.scene.setFocusItem(self._polyline)
62
                else:
63
                    QGraphicsView.mouseReleaseEvent(self.imageViewer, event)
64
                    self._polyline._vertices.append(self._polyline._pt)
65
                    self._polyline.update()
66
            finally:
67
                pass
68
        elif 'mouseReleaseEvent' == param[0] and event.button() == Qt.RightButton and self._polyline is not None:
69
            self.onSuccess.emit()
70
        elif 'mouseReleaseEvent' == param[0] and event.button() == Qt.RightButton and self._polyline is None:
71
            self.onRejected.emit(self)
72
        elif 'mouseMoveEvent' == param[0] and self._polyline is not None:
73
            self._polyline.onMouseMoved(event, param[2])
74
        elif 'keyPressEvent' == param[0]:
75
            if event.key() == Qt.Key_Escape:
76
                self.onRejected.emit(self)
77
                self.isTreated = False
78

  
79
    def undo(self):
80
        pass
81

  
82
    def redo(self):
83
        pass
84

  
85
    
86
        
HYTOS/HYTOS/Commands/SelectAttributeCommand.py
1
# coding: utf-8
2
""" This is select attribute command module """
3

  
4
import os.path
5
import sys
6
import AbstractCommand
7

  
8
try:
9
    from PyQt5.QtCore import *
10
    from PyQt5.QtGui import *
11
    from PyQt5.QtWidgets import *
12
except ImportError:
13
    try:
14
        from PyQt4.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QEvent
15
        from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImge, QPixmap, QPainterPath, QFileDialog, QCursor, QMouseEvent
16
    except ImportError:
17
        raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.")
18

  
19
'''
20
    @brief      QtImageViewer Select Attribute Command
21
    @author     kyouho
22
    @date       18.04.10
23
'''
24
class SelectAttributeCommand(AbstractCommand.AbstractCommand):
25
    onSuccess = pyqtSignal()
26

  
27
    def __init__(self, item, attr, imageViewer):
28
        super(SelectAttributeCommand, self).__init__(imageViewer)
29
        self.name = 'SelectAttribute'
30
        self.imageViewer.setCursor(QCursor(Qt.ArrowCursor))
31
        self._item = item
32
        self._attr = attr
33

  
34
    '''
35
        @brief      Select Attribuew
36
        @author     kyouho
37
        @date       18.07.19
38
        @history    euising  2019.01.15  add specbreak
39
        @history    add Valve Oper Item 2019.04.15 by humkyung
40
    '''
41
    def execute(self, param):
42
        from SymbolAttr import SymbolAttr
43
        from SymbolAttr import SymbolProp
44

  
45
        event = param[1]
46
        scenePos = param[2]
47

  
48
        try:
49
            if 'mouseReleaseEvent' == param[0] and event.button() == Qt.LeftButton:
50
                from EngineeringAbstractItem import QEngineeringAbstractItem
51
                from SymbolSvgItem import SymbolSvgItem
52
                from EngineeringTextItem import QEngineeringTextItem
53
                from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
54
                from EngineeringRunItem import QEngineeringRunItem
55
                from QEngineeringTagNoTextItem import QEngineeringTagNoTextItem
56
                from EngineeringLineItem import QEngineeringLineItem
57
                from EngineeringSpecBreakItem import QEngineeringSpecBreakItem
58
                from EngineeringValveOperCodeTextItem import QEngineeringValveOperCodeTextItem
59
                from EngineeringConnectorItem import QEngineeringConnectorItem
60
                from EngineeringEndBreakItem import QEngineeringEndBreakItem
61
                from EngineeringVendorItem import QEngineeringVendorItem
62
                from EngineeringReservedWordTextItem import QEngineeringReservedWordTextItem
63

  
64
                if self._attr is not None and type(self._attr) is SymbolAttr:
65
                    item = self.imageViewer.scene.itemAt(scenePos, QTransform())
66
                    if item is not None and self._attr.AttributeType == 'Line Item' and issubclass(type(item), QEngineeringLineItem):
67
                        self._item.conns.clear()
68
                        self._item.conns.append(item)
69
                        self.onSuccess.emit()
70
                    elif item is not None and self._attr.AttributeType == 'CONN' and (issubclass(type(item), QEngineeringLineItem) or issubclass(type(item), SymbolSvgItem) or type(item) is QEngineeringVendorItem or type(item) is QEngineeringReservedWordTextItem):
71
                        self._item.connectors[self._attr.AttrAt - 1].connect(item, QEngineeringAbstractItem.CONNECTED_AT_BODY)
72
                        if type(item) is QEngineeringReservedWordTextItem:
73
                            item.owner = self._item
74
                        self.onSuccess.emit()
75
                    elif item is not None and self._attr.AttributeType == 'CONN' and (type(item) is QEngineeringConnectorItem):
76
                        self._item.connectors[self._attr.AttrAt - 1].connect(item.parent, QEngineeringAbstractItem.CONNECTED_AT_PT)
77
                        self.onSuccess.emit()
78
                    elif item is not None and issubclass(type(self._item), QEngineeringSpecBreakItem) and self._attr.AttributeType == 'Comp Item' and type(item) is not QGraphicsPixmapItem:
79
                        self._item.attrs[self._attr] = str(item.uid)
80
                        self.onSuccess.emit()
81
                    elif item is not None and (type(self._item) is not QEngineeringEndBreakItem) and (type(item) is QEngineeringLineNoTextItem) and self._attr.AttributeType == 'OWNER':
82
                        if not item.runs:
83
                            item.runs.append(QEngineeringRunItem())
84

  
85
                        if 1 == len(item.runs): item.runs[0].items.append(self._item)
86

  
87
                        self._item.owner = item
88
                        self.onSuccess.emit()
89
                    elif item is not None and (type(self._item) is QEngineeringEndBreakItem or issubclass(type(self._item), QEngineeringTextItem)) and (type(item) is QEngineeringLineItem or issubclass(type(item), SymbolSvgItem)) and self._attr.AttributeType == 'OWNER':
90
                        self._item.owner = item
91
                        self.onSuccess.emit()
92
                    #elif item is not None and (type(self._item) is QEngineeringEndBreakItem) and (type(item) is QEngineeringLineItem) and self._attr.Attribute == 'Connected Line':
93
                    #    self._item.attrs[self._attr] = str(item.uid)
94
                    #    self.onSuccess.emit()
95
                    elif item is not None and self._attr.AttributeType == QEngineeringAbstractItem.assoc_type(item):
96
                        if self._attr.Freeze:
97
                            self.onSuccess.emit()
98
                            return
99
                            
100
                        if self._attr.AttributeType not in self._item._associations:
101
                            self._item._associations[self._attr.AttributeType] = []
102

  
103
                        while len(self._item._associations[self._attr.AttributeType]) <= self._attr.AttrAt:
104
                            self._item._associations[self._attr.AttributeType].append(None)
105
                        self._item.add_assoc_item(item, self._attr.AttrAt)
106
                        for key in self._item.attrs.keys():
107
                            if key.Attribute == self._attr.Attribute:
108
                                key.AssocItem = item
109
                                break
110
                        if issubclass(type(item), QEngineeringTextItem): item.owner = self._item
111
                        self.onSuccess.emit()
112
                elif self._attr is not None and type(self._attr) is SymbolProp:
113
                    item = self.imageViewer.scene.itemAt(scenePos, QTransform())
114
                    if item is not None and self._attr.match_type(item):
115
                        self._item.set_property(self._attr.Attribute, item)
116
                        if issubclass(type(item), QEngineeringTextItem): item.owner = self._item
117
                        self.onSuccess.emit()
118
        except Exception as ex:
119
            from App import App
120
            from AppDocData import MessageType
121

  
122
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
123
            App.mainWnd().addMessage.emit(MessageType.Error, message)       
124

  
125
        self.isTreated = True
126
        
127
    def undo(self):
128
        pass
129

  
130
    def redo(self):
131
        pass
132

  
133
    '''
134
        @brief      Find TextItem contain Point
135
        @author     kyouho
136
        @date       18.07.19
137
    '''
138
    def findTextItemInPoint(self, point):
139
        from EngineeringTextItem import QEngineeringTextItem
140
        
141
        for item in self.imageViewer.items():
142
            if type(item) is QEngineeringTextItem:
143
                if self.isOverlapItemAndPoint(item, point):
144
                    return (True, item)
145

  
146
        return (False,)
147

  
148
    '''
149
        @brief      Find Symbol Item contain Point
150
        @author     kyouho
151
        @date       18.07.19
152
    '''
153
    def findSymbolItemInPoint(self, point):
154
        from SymbolSvgItem import SymbolSvgItem
155
        
156
        for item in self.imageViewer.items():
157
            if issubclass(type(item), SymbolSvgItem):
158
                if self.isOverlapItemAndPoint(item, point):
159
                    return (True, item)
160

  
161
        return (False,)
162

  
163
    '''
164
        @brief      Check Overlap
165
        @author     kyouho
166
        @date       18.07.17
167
    '''
168
    def isOverlapItemAndPoint(self, item, point):
169
        x = point.x()
170
        y = point.y()
171
        loc = item.loc
172
        size = item.size
173

  
174
        if loc[0] <= x and loc[0] + size[0] >= x and loc[1] <= y and loc[1] + size[1] >= y:
175
            return True
176
        else:
177
            return False
HYTOS/HYTOS/ConnectAttrDialog.py
1
# coding: utf-8
2

  
3
from PyQt5.QtCore import *
4
from PyQt5.QtGui import *
5
from PyQt5.QtWidgets import *
6
import ConnectAttr_UI
7
import sys
8
import os
9
import cv2
10
from AppDocData import *
11
from LineDetector import LineDetector
12
from EngineeringLineItem import QEngineeringLineItem
13
from EngineeringLineNoTextItem import QEngineeringLineNoTextItem
14
from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem
15
from SymbolSvgItem import SymbolSvgItem
16
from EngineeringTextItem import QEngineeringTextItem
17
from GraphicsBoundingBoxItem import QGraphicsBoundingBoxItem
18

  
19
'''
20
'''
21
class Worker(QThread):
22
    """ This is Worker class """
23
    from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QGridLayout, QListWidget
24
    from QtImageViewer import QtImageViewer
25
    import sys
26

  
27
    '''
28
    '''
29
    finished = pyqtSignal()
30
    intReady = pyqtSignal(int)
31
    displayMessage = pyqtSignal(str)
32
    updateProgress = pyqtSignal(int)
33

  
34
    def __init__(self, graphicsView, update_line_type):
35
        QThread.__init__(self)
36
        self.graphicsView = graphicsView
37
        self._update_line_type = update_line_type
38

  
39
    '''
40
        @brief  execute connecting attributes
41
        @author humkyung
42
        @date   2018.06.17
43
    '''
44
    def run(self): # A slot takes no params
45
        from LineNoTracer import connectAttrImpl
46

  
47
        try:
48
            connectAttrImpl(self, self._update_line_type)
49
        except Exception as ex:
50
            from App import App 
51
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
52
            App.mainWnd().addMessage.emit(MessageType.Error, message)
53

  
54
class QConnectAttrDialog(QDialog):
55
    """ This is connect attr dialog class """
56

  
57
    def __init__(self, parent, graphicsView): #Parent is MainWindow
58
        import ConnectAttr_UI
59

  
60
        QDialog.__init__(self, parent)
61

  
62
        self.parent = parent
63
        self.graphicsView = graphicsView
64
        self.ui = ConnectAttr_UI.Ui_ConnectAttr()
65
        self.ui.setupUi(self)
66
        self.ui.pushButtonStart.setFocus()
67
        self.ui.buttonBox.setEnabled(True)
68
        self.ui.listWidget.model().rowsInserted.connect(self.rowInserted) ## connect to func rowInserted(self, item)
69
        self.isAccepted = False
70
        
71
        self.ui.pushButtonStart.clicked.connect(self.connStart)
72

  
73
    def connStart(self):
74
        '''
75
            @brief  connection start
76
            @author euisung
77
            @date   2019.02.25
78
        ''' 
79
        self.ui.buttonBox.setEnabled(False)
80
        self.ui.pushButtonStart.setEnabled(False)
81
        self.ui.progressBar.setValue(0)
82
        self.startThread()
83
        """ for DEBUG
84
        from LineNoTracer import connectAttrImpl
85
        connectAttrImpl(self)
86
        """
87

  
88
    '''
89
        @brief      QListWidget Row Inserted Listener
90
                    Whenever row inserted, scroll to bottom
91
        @author     Jeongwoo
92
        @date       18.04.12
93
    '''
94
    def rowInserted(self, item):
95
        self.ui.listWidget.scrollToBottom()
96

  
97
    '''
98
        @brief  add item to list widget
99
        @author humkyung
100
        @date   2018.06.17
101
    '''
102
    def addListItem(self, msg):
103
        self.ui.listWidget.addItem(msg)
104

  
105
    def accept(self):
106
        self.isAccepted = True
107
        QDialog.accept(self)
108

  
109
    '''
110
        @brief      update progressbar with given value
111
        @author     humkyung
112
        @date       2018.06.17
113
        @history    humkyung 2018.06.27 reset value if maxValue is -1
114
    '''
115
    def updateProgress(self, maxValue):
116
        if maxValue != -1:
117
            self.ui.progressBar.setMaximum(maxValue)
118
            self.ui.progressBar.setValue(self.ui.progressBar.value() + 1)
119
        else:
120
            self.ui.progressBar.setValue(0)
121

  
122
    '''
123
        @brief  start thread
124
        @author humkyung
125
        @date   2018.06.17
126
    '''
127
    def startThread(self):
128
        import timeit
129
        from LineNoTracer import connectAttrImpl
130

  
131
        try:
132
            self.ui.buttonBox.setDisabled(True)
133

  
134
            # 1 - create Worker and Thread inside the Form
135
            self.obj = Worker(self.graphicsView, self.ui.checkBoxUpdateLineType.isChecked())
136

  
137
            # 2 - Connect Worker Signals to the Thread slots
138
            self.obj.displayMessage.connect(self.addListItem)
139
            self.obj.updateProgress.connect(self.updateProgress)
140

  
141
            # 3 - Thread finished signal will close the app if you want!
142
            self.obj.finished.connect(self.dlgExit)
143

  
144
            # 4 - Start the thread
145
            self.obj.start()
146

  
147
            self.tmStart = timeit.default_timer()
148
        except Exception as ex:
149
            from App import App 
150
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
151
            App.mainWnd().addMessage.emit(MessageType.Error, message)
152
        finally:
153
            self.ui.buttonBox.setDisabled(False)
154

  
155
    '''
156
        @brief      set buttonbox's enabled flag
157
        @author     humkyung
158
        @date       2018.06.17
159
        @history    humkyung 2018.06.17 add flow mark for pipe run
160
                    humkyung 2018.08.16 don't update line type according to connected items
161
    '''
162
    def dlgExit(self):
163
        import timeit
164

  
165
        try:
166
            self.ui.progressBar.setValue(self.ui.progressBar.maximum())
167
            self.ui.buttonBox.setEnabled(True)
168
        except Exception as ex:
169
            from App import App
170

  
171
            message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)
172
            App.mainWnd().addMessage.emit(MessageType.Error, message)
173
        finally:
174
            self.tmStop = timeit.default_timer()    
175
            seconds = self.tmStop - self.tmStart
176
            self.ui.listWidget.addItem("\nRunning Time : {} min".format(str(round(seconds/60, 1))) + "\n")
HYTOS/HYTOS/ConnectAttr_UI.py
1
# -*- coding: utf-8 -*-
2

  
3
# Form implementation generated from reading ui file '.\UI\dlgConnectAttr.ui'
4
#
5
# Created by: PyQt5 UI code generator 5.11.3
6
#
7
# WARNING! All changes made in this file will be lost!
8

  
9
from PyQt5 import QtCore, QtGui, QtWidgets
10

  
11
class Ui_ConnectAttr(object):
12
    def setupUi(self, ConnectAttr):
13
        ConnectAttr.setObjectName("ConnectAttr")
14
        ConnectAttr.setWindowModality(QtCore.Qt.WindowModal)
15
        ConnectAttr.resize(845, 453)
16
        font = QtGui.QFont()
17
        font.setFamily("맑은 고딕")
18
        ConnectAttr.setFont(font)
19
        self.gridLayout = QtWidgets.QGridLayout(ConnectAttr)
20
        self.gridLayout.setObjectName("gridLayout")
21
        self.listWidget = QtWidgets.QListWidget(ConnectAttr)
22
        self.listWidget.setObjectName("listWidget")
23
        self.gridLayout.addWidget(self.listWidget, 3, 0, 1, 1)
24
        self.horizontalLayout = QtWidgets.QHBoxLayout()
25
        self.horizontalLayout.setObjectName("horizontalLayout")
26
        self.progressBar = QtWidgets.QProgressBar(ConnectAttr)
27
        self.progressBar.setProperty("value", 0)
28
        self.progressBar.setObjectName("progressBar")
29
        self.horizontalLayout.addWidget(self.progressBar)
30
        self.buttonBox = QtWidgets.QDialogButtonBox(ConnectAttr)
31
        self.buttonBox.setEnabled(False)
32
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
33
        sizePolicy.setHorizontalStretch(0)
34
        sizePolicy.setVerticalStretch(0)
35
        sizePolicy.setHeightForWidth(self.buttonBox.sizePolicy().hasHeightForWidth())
36
        self.buttonBox.setSizePolicy(sizePolicy)
37
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
38
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Close)
39
        self.buttonBox.setObjectName("buttonBox")
40
        self.horizontalLayout.addWidget(self.buttonBox, 0, QtCore.Qt.AlignRight)
41
        self.gridLayout.addLayout(self.horizontalLayout, 6, 0, 1, 1)
42
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout()
43
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
44
        self.checkBoxUpdateLineType = QtWidgets.QCheckBox(ConnectAttr)
45
        self.checkBoxUpdateLineType.setObjectName("checkBoxUpdateLineType")
46
        self.horizontalLayout_2.addWidget(self.checkBoxUpdateLineType)
47
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
48
        self.horizontalLayout_2.addItem(spacerItem)
49
        self.pushButtonStart = QtWidgets.QPushButton(ConnectAttr)
50
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
51
        sizePolicy.setHorizontalStretch(0)
52
        sizePolicy.setVerticalStretch(0)
53
        sizePolicy.setHeightForWidth(self.pushButtonStart.sizePolicy().hasHeightForWidth())
54
        self.pushButtonStart.setSizePolicy(sizePolicy)
55
        self.pushButtonStart.setObjectName("pushButtonStart")
56
        self.horizontalLayout_2.addWidget(self.pushButtonStart)
57
        self.gridLayout.addLayout(self.horizontalLayout_2, 2, 0, 1, 1)
58

  
59
        self.retranslateUi(ConnectAttr)
60
        self.buttonBox.clicked['QAbstractButton*'].connect(ConnectAttr.accept)
61
        QtCore.QMetaObject.connectSlotsByName(ConnectAttr)
62
        ConnectAttr.setTabOrder(self.pushButtonStart, self.listWidget)
63

  
64
    def retranslateUi(self, ConnectAttr):
65
        _translate = QtCore.QCoreApplication.translate
66
        ConnectAttr.setWindowTitle(_translate("ConnectAttr", "Connect Attribute"))
67
        self.checkBoxUpdateLineType.setText(_translate("ConnectAttr", "Update Line Type"))
68
        self.pushButtonStart.setText(_translate("ConnectAttr", "Start"))
69

  
HYTOS/HYTOS/DetectSymbolDialog.py
1
# coding: utf-8
2
"""
3
    This is fluid code dialog module
4
"""
5
import sys
6
import sqlite3
7
import os
8
import cv2
9
import math
10
import threading
11
import multiprocessing
12
from multiprocessing import Process, Queue
13

  
14
from shapely.geometry import Point
15
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse
16
from PyQt5.QtCore import *
17
from PyQt5.QtGui import *
18
from PyQt5.QtWidgets import *
19

  
20
from AppDocData import AppDocData
21
import DetectSymbol_UI
22

  
23
class QDetectSymbolDialog(QDialog):
24

  
25
    def __init__(self, parent):
26
        QDialog.__init__(self)
27
        self.parent = parent
28
        self.ui = DetectSymbol_UI.Ui_DetectSymbolDialog()
29
        self.ui.setupUi(self)
30

  
31
        self.table = self.ui.tableWidgetSymbol
32
        self.currentRow = 0
33
        self.currentColumn = 0
34

  
35
        ## box dir setting
36
        self.boxDir = AppDocData.instance().getCurrentProject().path + '/box/'
37
        if not os.path.exists(self.boxDir):
38
            os.makedirs(self.boxDir)
39
        ## drawing file setting
40
        self.drawingDir = AppDocData.instance().getCurrentProject().path + '/drawings/'
41
        if os.path.exists(self.drawingDir):
42
            files = os.listdir(self.drawingDir)
43
            for file in files:
44
                listItem = QListWidgetItem()
45
                listItem.setData(32, file)
46
                listItem.setText(os.path.splitext(file)[0])
47
                self.ui.listWidgetDrawings.addItem(listItem)
48

  
49
        self.ui.listWidgetDrawings.currentTextChanged.connect(self.currentTextChangedEvent)
50
        self.ui.pushButtonDetectSymbol.clicked.connect(self.detectSymbol)
51

  
52
        if self.ui.listWidgetDrawings.count():
53
            self.ui.listWidgetDrawings.setCurrentRow(0)
54

  
55
        self.table.cellDoubleClicked.connect(self.cellDoubleClickedEvent)
56
        self.table.currentCellChanged.connect(self.currentCellChangedEvent)
57

  
58
        self.setAllSymbolsTable()
59

  
60
    '''
61
        @brief  current cell chage event
62
        @author kyouho
63
        @date   2018.10.01
64
    '''
65
    def currentCellChangedEvent(self, currentRow, currentColumn, previousRow, previousColumn):
66
        currentItem = self.table.cellWidget(currentRow, currentColumn)
67
        if currentItem is not None:
68
            self.currentRow = currentRow
69
            self.currentColumn = currentColumn
70
        else:
71
            self.currentRow = -1
72
            self.currentColumn = -1
73

  
74
    '''
75
        @brief  cell double click event
76
        @author kyouho
77
        @date   2018.10.01
78
    '''
79
    def cellDoubleClickedEvent(self, row, column):
80
        cell = self.table.cellWidget(row,column)
81
        if cell is not None:
82
            import SymbolEditorDialog
83
            symbolEditorDialog = SymbolEditorDialog.QSymbolEditorDialog(self, cell.pixmap(), AppDocData.instance().getCurrentProject())
84
            (isAccepted, isImmediateInsert, offsetX, offsetY, newSym) = symbolEditorDialog.showDialog()
85
            if isAccepted:
86
                self.table.removeCellWidget(row, column)
87
                self.parent.symbolTreeWidget.initSymbolTreeWidget()
88
                self.setAllSymbolsTable()
89

  
90
    '''
91
        @brief  text changed Event
92
        @author kyouho
93
        @date   2018.09.18
94
    '''
95
    def currentTextChangedEvent(self, text):
96
        self.imageName = text
97
        self.imgPath = self.drawingDir + self.ui.listWidgetDrawings.currentItem().data(32)
98
        self.tableSetting()
99

  
100
    '''
101
        @brief  text changed Event
102
        @author kyouho
103
        @date   2018.10.11
104
    '''
105
    def setAllSymbolsTable(self):
106
        table = self.ui.tableWidgetAllSymbols
107
        table.setRowCount(0)
108

  
109
        imageFiles = []
110
        imageDir = AppDocData.instance().getCurrentProject().path + '/image/'
111
        self.findFiles(imageDir, imageFiles)
112

  
113
        table.horizontalHeader().setSectionResizeMode(0, QHeaderView.Stretch)
114
        size = table.maximumWidth() - 40
115

  
116
        table.setRowCount(len(imageFiles))
117
        row = 0
118
        for path in imageFiles:
119
            cell = QLabel()
120
            pixmap = QPixmap(path)
121
            cell.setPixmap(pixmap.scaled(size, size, Qt.KeepAspectRatio))
122
            table.setCellWidget(row, 0, cell)
123
            row = row + 1
124

  
125
        table.resizeRowsToContents()
126

  
127
    '''
128
        @brief  find image files
129
        @author kyouho
130
        @date   2018.10.11
131
    '''
132
    def findFiles(self, dir, list):
133
        fileList = os.listdir(dir)
134
        for file in fileList:
135
            path = os.path.join(dir, file)
136
            if os.path.isdir(path):
137
                self.findFiles(path, list)
138
            elif os.path.splitext(path)[1] == '.png':
139
                list.append(path)
140

  
141

  
142
    
143
    '''
144
        @brief  text changed Event
145
        @author kyouho
146
        @date   2018.09.18
147
    '''
148
    def detectSymbol(self):
149
        if not self.ui.listWidgetDrawings.count():
150
            return
151

  
152
        self.progress = QProgressDialog("잠시만 기다려주세요", "Cancel", 0, 100, self)
153
        self.progress.setWindowModality(Qt.WindowModal)
154
        self.progress.setAutoReset(True)
155
        self.progress.setAutoClose(True)
156
        self.progress.setMinimum(0)
157
        self.progress.resize(600,100)
158
        self.progress.setWindowTitle("인식 중...")
159
        self.progress.show()
160
        self.progress.setMaximum(100)
161
        self.progress.setValue(0)
162
        QApplication.processEvents()
163

  
164
        from TextDetector import TextDetector
165
        import numpy as np
166

  
167
        appDocData = AppDocData.instance()
168
        ## textDetector에서 사용하기 때문에 설정
169
        appDocData.imgName = self.imageName
170

  
171
        ## 흑색 이미지로 변환
172
        img = cv2.imread(self.imgPath, 1)
173
        imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
174
        
175
        ## 프로젝트의 Drawing Area data
176
        area = appDocData.getArea('Drawing')
177

  
178
        ## area 영역 자른 offset
179
        offset = (area.x, area.y) if area is not None else (0,0)
180
        
181
        ## 이미지 이진화
182
        thresholdImg = cv2.threshold(imgGray , 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
183
        ## 프로젝트의 Area 영역만큼만 자른 이미지
184
        areaImg = thresholdImg[round(area.y):round(area.y+area.height), round(area.x):round(area.x+area.width)]
185

  
186
        ## 선제거 전에 먼저 작은 영역 제거
187
        ## contours 추출을 위한 색반전
188
        areaImg = cv2.bitwise_not(areaImg) 
189
        ## contours 추출
190
        image, contours, hierarchy = cv2.findContours(areaImg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
191
        for contour in contours:
192
            [x, y, w, h] = cv2.boundingRect(contour)
193

  
194
            if (w < 40 or h < 40): 
195
                areaImg[y:y+h,x:x+w] = 0
196
        ## 다시 색반전
197
        areaImg = cv2.bitwise_not(areaImg) 
198

  
199
        ## find lines
200
        verticalLineList = []
201
        horizontalLineList = []
202
        self.findLines(areaImg, verticalLineList, horizontalLineList)
203

  
204
        ## chage color
205
        for vLine in verticalLineList:
206
            p1 = vLine[0]
207
            p2 = vLine[1]
208
            x = p1[0]
209
            areaImg[p1[1]:p2[1], x] = 255
210
        ## chage color
211
        for vLine in horizontalLineList:
212
            p1 = vLine[0]
213
            p2 = vLine[1]
214
            y = p1[1]
215
            areaImg[y, p1[0]:p2[0]] = 255
216
        
217
        ## contours 추출을 위한 색반전
218
        areaImg = cv2.bitwise_not(areaImg) 
219
        ## contours 추출
220
        recList = self.getContours(areaImg)
221

  
222
        ## to xml
223
        self.toXml(recList, offset)
224

  
225
        ## table setting
226
        self.tableSetting()
227

  
228
        self.progress.setValue(self.progress.maximum())
229
    
230
    '''
231
        @brief  find lines
232
        @author kyouho
233
        @date   2018.10.01
234
    '''
235
    def findLines(self, areaImg, verticalLineList, horizontalLineList):
236

  
237
        ## for multiprocessing
238
        verticalProcessList = []
239
        horizontalProcessList = []
240

  
241
        ## Find VerticalLine using multiprocessing
242
        ## Set Vertical Line
243
        jumpValue = int(areaImg.shape[1] / os.cpu_count())
244
        value = 0
245
        for cpuIndex in range(os.cpu_count()):
246
            _queue = Queue()
247
            _range = value + jumpValue
248
            if os.cpu_count() -1 == cpuIndex:
249
                _range = areaImg.shape[1]
250

  
251
            _process = Process(target=isVerticalLineThread, args=(value, _range, areaImg, _queue))
252
            _process.daemon = True
253
            verticalProcessList.append((_process, _queue))
254
            value = value + jumpValue
255
        
256
        ## Set Horizontal Line
257
        jumpValue = int(areaImg.shape[0] / os.cpu_count())
258
        value = 0
259
        for cpuIndex in range(os.cpu_count()):
260
            _queue = Queue()
261
            _range = value + jumpValue
262
            if os.cpu_count() -1 == cpuIndex:
263
                _range = areaImg.shape[0]
264

  
265
            _process = Process(target=isHorizontalLineThread, args=(value, _range, areaImg, _queue))
266
            _process.daemon = True
267
            horizontalProcessList.append((_process, _queue))
268
            value = value + jumpValue
269
        
270
        ## set percent
271
        progressCount = len(verticalProcessList) + len(horizontalProcessList) + 1
272
        percentGage = int(100 / progressCount)
273
        percent = percentGage
274
        self.progress.setValue(percent)
275
        QApplication.processEvents()
276

  
277
        ## process start
278
        for process in verticalProcessList:
279
            process[0].start()
280

  
281
        ## Wait Vertical And Start Horizontal 
282
        for index in range(len(verticalProcessList)):
283
            verticalLineList.extend(verticalProcessList[index][1].get())
284
            verticalProcessList[index][0].join()
285
            verticalProcessList[index][1].close()
286

  
287
            percent = percent + percentGage
288
            self.progress.setValue(percent)
289
            QApplication.processEvents()
290

  
291
            horizontalProcessList[index][0].start()
292

  
293
        ## Wait Horizontal 
294
        for process in horizontalProcessList:
295
            horizontalLineList.extend(process[1].get())
296
            process[0].join()
297
            process[1].close()
298

  
299
            percent = percent + percentGage
300
            self.progress.setValue(percent)
301
            QApplication.processEvents()
302

  
303
    '''
304
        @brief  get contours
305
        @author kyouho
306
        @date   2018.10.01
307
    '''
308
    def getContours(self, areaImg):
309
        
310
        image, contours, hierarchy = cv2.findContours(areaImg, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
311

  
312
        ## RecList 정리
313
        lineWidth = 5
314
        recList = []
315
        tempRecList = []
316
        for contour in contours:
317
            [x, y, w, h] = cv2.boundingRect(contour)
318
            tempRecList.append([x-lineWidth, y-lineWidth, x+w+lineWidth, y+h+lineWidth])
319

  
320
        ## Overlap Rec 합침
321
        while len(tempRecList):
322
            rec1 = tempRecList[0]
323
            _temp = []
324
            for index in range(1, len(tempRecList)):
325
                rec2 = tempRecList[index]
326
                if rec1[0] <= rec2[2] and rec1[2] >= rec2[0] and rec1[1] <= rec2[3] and rec1[3] >= rec2[1]:
327
                    _temp.append(rec2)
328
            
329
            if len(_temp):
330
                x1 = rec1[0]
331
                y1 = rec1[1]
332
                x2 = rec1[2]
333
                y2 = rec1[3]
334

  
335
                for rec in _temp:
336
                    x1 = min(x1, rec[0])
337
                    y1 = min(y1, rec[1])
338
                    x2 = max(x2, rec[2])
339
                    y2 = max(y2, rec[3])
340
                    tempRecList.remove(rec)
341
                tempRecList.append([x1, y1, x2, y2])
342

  
343
            else:
344
                recList.append(rec1)
345

  
346
            tempRecList.remove(rec1)
347

  
348
        return recList
349

  
350
    '''
351
        @brief  key press event
352
        @author kyouho
353
        @date   2018.10.01
354
    '''
355
    def keyPressEvent(self, event):
356
        if event.key() == Qt.Key_Delete and self.currentRow != -1 and self.currentColumn != -1:
357
            self.table.removeCellWidget(self.currentRow, self.currentColumn)
358
            
359

  
360
    '''
361
        @brief  box to xml
362
        @author kyouho
363
        @date   2018.10.01
364
    '''
365
    def toXml(self, recList, offset):
366
        xml = Element('BOXES')
367

  
368
        ## to xml
369
        for rec in recList:
370
            [x1, y1, x2, y2] = rec
371
            w = x2-x1
372
            h = y2-y1
373
            if w < 20 or h < 20: continue
374
            elif w*4<h or h*4<w: continue
375

  
376
            boxElement = Element('BOX')
377
            
378
            xElement = Element('X')
379
            xElement.text = str(x1 + offset[0])
380
            boxElement.append(xElement)
381

  
382
            yElement = Element('Y')
383
            yElement.text = str(y1 + offset[1])
384
            boxElement.append(yElement)
385

  
386
            widthElement = Element('WIDTH')
387
            widthElement.text = str(x2-x1)
388
            boxElement.append(widthElement)
389

  
390
            heightElement = Element('HEIGHT')
391
            heightElement.text = str(y2-y1)
392
            boxElement.append(heightElement)
393

  
394
            xml.append(boxElement)
395

  
396
        ElementTree(xml).write(self.boxDir + self.imageName + '.box')
397

  
398
    '''
399
        @brief  table setting
400
        @author kyouho
401
        @date   2018.09.18
402
    '''
403
    def tableSetting(self):
404
        columnCount = 3
405
        self.table.setColumnCount(columnCount)
406
        self.table.setRowCount(0)
407
        boxCount = 0
408

  
409
        xmlPath = self.boxDir + self.imageName + '.box'
410
        if os.path.exists(xmlPath):
411
            _pixmap = QPixmap(self.imgPath)
412

  
413
            xml = parse(xmlPath)
414
            root = xml.getroot()
415

  
416
            for box in root.iter('BOX'):
417
                rowIndex = int(boxCount / columnCount)
418
                self.table.setRowCount(rowIndex + 1)
419

  
420
                _x = int(box.find('X').text)
421
                _y = int(box.find('Y').text)
422
                _width = int(box.find('WIDTH').text)
423
                _height = int(box.find('HEIGHT').text)
424

  
425
                rect = QRect(_x, _y, _width, _height)
426
                boxImg = _pixmap.copy(rect)
427

  
428
                cell = QLabel()
429
                cell.setPixmap(boxImg)
430
                cell.rect = [_x, _y, _width, _height]
431
                self.table.setCellWidget(rowIndex, boxCount % columnCount, cell)
432

  
433
                boxCount = boxCount + 1
434
                
435

  
436
            self.table.resizeColumnsToContents()
437
            self.table.resizeRowsToContents()
438
        
439
    '''
440
        @brief  accept
441
        @author kyouho
442
        @date   2018.10.01
443
    '''
444
    def accept(self):
445
        columnCount = 3
446
        recList = []
447
        for rowIndex in range(self.table.rowCount()):
448
            for columnIndex in range(columnCount):
449
                cell = self.table.cellWidget(rowIndex, columnIndex)
450
                if cell is not None:
451
                    [x, y, w, h] = cell.rect
452
                    recList.append([x, y, x+w, y+h])
453

  
454
        self.toXml(recList, (0, 0))
455

  
456
        QDialog.accept(self)
457

  
458
'''
459
    @brief  Check Vertical Line using Multiprocessing
460
    @author kyouho
461
    @date   2018.09.27
462
'''
463
def isVerticalLineThread(start, end, img, _queue):
464
    minLineSize = 40
465
    
466
    ## Vertical
467
    find = False
468
    startY = 0
469
    lineList = []
470
    for x in range(start, end):
471
        for y in range(0, img.shape[0]):
472
            if img[y,x] == 0:
473
                if find:
474
                    continue
475
                else:
476
                    find = True
477
                    startY = y
478
            else:
479
                if find:
480
                    if y - startY > minLineSize:
481
                        lineList.append(((x,startY), (x,y)))
482
                    find = False
483
    _queue.put(lineList)
484

  
485
'''
486
    @brief  Check Horizontal Line using Multiprocessing
487
    @author kyouho
488
    @date   2018.09.27
489
'''
490
def isHorizontalLineThread(start, end, img, _queue):
491
    minLineSize = 40
492
    
493
    ## Horizontal
494
    find = False
495
    startX = 0
496
    lineList = []
497
    for y in range(start, end):
498
        for x in range(0, img.shape[1]):
499
            if img[y,x] == 0:
500
                if find:
501
                    continue
502
                else:
503
                    find = True
504
                    startX = x
505
            else:
506
                if find:
507
                    if x - startX > minLineSize:
508
                        lineList.append(((startX,y), (x,y)))
509

  
510
                    find = False
511
    _queue.put(lineList)
HYTOS/HYTOS/DetectSymbol_UI.py
1
# -*- coding: utf-8 -*-
2

  
3
# Form implementation generated from reading ui file '.\UI\DetectSymbol.ui'
4
#
5
# Created by: PyQt5 UI code generator 5.11.2
6
#
7
# WARNING! All changes made in this file will be lost!
8

  
9
from PyQt5 import QtCore, QtGui, QtWidgets
10

  
11
class Ui_DetectSymbolDialog(object):
12
    def setupUi(self, DetectSymbolDialog):
13
        DetectSymbolDialog.setObjectName("DetectSymbolDialog")
14
        DetectSymbolDialog.resize(1313, 813)
15
        font = QtGui.QFont()
16
        font.setFamily("맑은 고딕")
17
        DetectSymbolDialog.setFont(font)
18
        self.gridLayout = QtWidgets.QGridLayout(DetectSymbolDialog)
19
        self.gridLayout.setObjectName("gridLayout")
20
        self.gridLayout_2 = QtWidgets.QGridLayout()
21
        self.gridLayout_2.setSizeConstraint(QtWidgets.QLayout.SetDefaultConstraint)
22
        self.gridLayout_2.setObjectName("gridLayout_2")
23
        spacerItem = QtWidgets.QSpacerItem(40, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
24
        self.gridLayout_2.addItem(spacerItem, 0, 1, 1, 1)
25
        self.pushButtonDetectSymbol = QtWidgets.QPushButton(DetectSymbolDialog)
26
        self.pushButtonDetectSymbol.setMinimumSize(QtCore.QSize(0, 25))
27
        self.pushButtonDetectSymbol.setMaximumSize(QtCore.QSize(16777215, 25))
28
        self.pushButtonDetectSymbol.setObjectName("pushButtonDetectSymbol")
29
        self.gridLayout_2.addWidget(self.pushButtonDetectSymbol, 0, 0, 1, 1)
30
        self.gridLayout.addLayout(self.gridLayout_2, 0, 0, 1, 1)
31
        self.buttonBox = QtWidgets.QDialogButtonBox(DetectSymbolDialog)
32
        self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
33
        self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
34
        self.buttonBox.setObjectName("buttonBox")
35
        self.gridLayout.addWidget(self.buttonBox, 2, 0, 1, 1)
36
        self.splitter_2 = QtWidgets.QSplitter(DetectSymbolDialog)
37
        self.splitter_2.setOrientation(QtCore.Qt.Horizontal)
38
        self.splitter_2.setObjectName("splitter_2")
39
        self.splitter = QtWidgets.QSplitter(self.splitter_2)
40
        sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Preferred, QtWidgets.QSizePolicy.Expanding)
41
        sizePolicy.setHorizontalStretch(0)
42
        sizePolicy.setVerticalStretch(0)
43
        sizePolicy.setHeightForWidth(self.splitter.sizePolicy().hasHeightForWidth())
44
        self.splitter.setSizePolicy(sizePolicy)
45
        self.splitter.setMinimumSize(QtCore.QSize(0, 0))
46
        self.splitter.setMaximumSize(QtCore.QSize(300, 16777215))
47
        self.splitter.setOrientation(QtCore.Qt.Vertical)
48
        self.splitter.setObjectName("splitter")
... 이 차이점은 표시할 수 있는 최대 줄수를 초과해서 이 차이점은 잘렸습니다.

내보내기 Unified diff

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