프로젝트

일반

사용자정보

개정판 170b1dd7

ID170b1dd73852a46453927816eec8aae83bd0ec84
상위 1734774c
하위 0f777efa, 4f359afa

humkyung 이(가) 약 7년 전에 추가함

Add dialog box showing status of process while recognize the image drawing

차이점 보기:

DTI_PID/DTI_PID/DTI_PID.py
35 35
from PyQt5.QtGui import *
36 36
from PyQt5.QtWidgets import *
37 37
import DTI_PID_UI
38
import QtImageViewer
38 39
#endregion
39 40

  
40 41
## Tesseract path
......
229 230

  
230 231

  
231 232
#detect symbols on PID
232
def detectSymbolsOnPid(mainRes, targetSymbols):
233
def detectSymbolsOnPid(mainRes, targetSymbols, listWidget):
233 234
    for detailTarget in targetSymbols:
234
        detectSymbolOnPid(mainRes, detailTarget)
235
        detectSymbolOnPid(mainRes, detailTarget, listWidget)
235 236

  
236

  
237
#detect symbol on PID
238
def detectSymbolOnPid(mainRes, targetSymbol):
237
'''
238
    @brief detect symbol on PID
239
'''
240
def detectSymbolOnPid(mainRes, targetSymbol, listWidget):
239 241
    global src
240 242
    global srcGray
241 243
    global ocrCompletedSrc
......
259 261
    symbolOriginalPoint = targetSymbol.getOriginalPoint()
260 262
    symbolConnectionPoint = targetSymbol.getConnectionPoint()
261 263

  
262
    print('current symbol : ' + symbolPath)
264
    listWidget.addItem('current symbol : ' + symbolPath)
263 265

  
264 266
    foundSymbolCount = 0
265 267

  
......
414 416
    
415 417
    threadLock.acquire()
416 418
    srcName = os.path.splitext(os.path.basename(mainRes))[0]
417
    print('finish symbol(count) / AvgMpCount : ' + symbolPath + '(' + str(foundSymbolCount) + ') / avgMpCount : ' + str(avgMpCount))
419
    listWidget.addItem('finish symbol(count) / AvgMpCount : ' + symbolPath + '(' + str(foundSymbolCount) + ') / avgMpCount : ' + str(avgMpCount))
418 420
    f = open(os.path.dirname(os.path.realpath(__file__)) + "\\res\\Result\\result_"+srcName+"_600dpi.txt", 'a+')
419 421
    data = 'symbolName - (count) : ' + symbolPath + ' - (' + str(foundSymbolCount) + ') / avgMpCount : '+str(avgMpCount)+'\n'
420 422
    f.write(data)
......
461 463

  
462 464
    cv2.rectangle(src, sp, (sp[0]+sw, sp[1]+sh), (0, 0, 255), 2)
463 465

  
464
def drawFoundSymbols(symbol):
466
def drawFoundSymbols(symbol, listWidget):
465 467
    global src
466 468
    global canvas
467 469
    global WHITE_LIST_CHARS
......
514 516
        ocrData = pytesseract.image_to_boxes(im, config='-c tessedit_char_whitelist="-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" -psm 6')
515 517
        #ocrData = pytesseract.image_to_data(im)
516 518
        #ocrData = pytesseract.image_to_string(im, config = "hocr")
517
        print("tesseract result : \n" + ocrData)
519
        listWidget.addItem("tesseract result : \n" + ocrData)
518 520

  
519 521
        ### For image_to_data()
520 522
        #if ocrData:
......
592 594
            threadLock.release()
593 595

  
594 596

  
595
def drawFoundSymbolsOnCanvas(mainRes, width, height):
597
def drawFoundSymbolsOnCanvas(mainRes, width, height, listWidget):
596 598
    global src
597 599
    global srcGray
598 600
    global ocrCompletedSrc
......
607 609
    #pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER)
608 610
    for symbol in searchedSymbolList:
609 611
        #pool.submit(drawFoundSymbols, symbol)
610
        drawFoundSymbols(symbol)
612
        drawFoundSymbols(symbol, listWidget)
611 613
    #pool.shutdown(wait = True)
612 614

  
613 615
    for text in textInfoList:
......
707 709

  
708 710

  
709 711
#Main function
710
def main(path):
712
def main(path, listWidget):
711 713
    global src
712 714
    global srcGray
713 715
    global ocrCompletedSrc
......
715 717
    global threadLock
716 718
    global textInfoList
717 719
    
718
    srcList = []
719
    srcList.append(path)
720
    #srcList = [CONST_IMG_PID_UY1_K_2006_300DPI]
721
    #srcList = [CONST_IMG_PID_UY1_K_300DPI]
722
    #srcList = [CONST_IMG_PID_UY1_K_2005G_300DPI, CONST_IMG_PID_UY1_K_2007_300DPI]
723
    #srcList = [CONST_IMG_PID_UY1_K_300DPI, CONST_IMG_PID_UY1_K_2005G_300DPI, CONST_IMG_PID_UY1_K_2006_300DPI, CONST_IMG_PID_UY1_K_2007_300DPI]
724
    #srcList = [CONST_IMG_PID_UY1_K_2006_300DPI]
725

  
726
    initTargetSymbolDataList()
727

  
728
    for mainRes in srcList:
729
        #Init src
730
        src = []
731
        srcGray = []
732
        ocrCompletedSrc = []
733
        searchedSymbolList = []
734
        textInfoList = []
735

  
736
        start = timeit.default_timer()
737

  
738
        initMainSrc(mainRes)
739

  
740
        print("######### Ready : " + mainRes)
741
        
742
        #threadLock = threading.Lock()
743
        pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER)
744
        for targetItem in targetSymbolList:
745
            if type(targetItem).__name__ == 'list':
746
                #detectSymbolsOnPid(mainRes, target)
747
                pool.submit(detectSymbolsOnPid, mainRes, targetItem)
748
            else:
749
                #detectSymbolOnPid(mainRes, target)
750
                pool.submit(detectSymbolOnPid, mainRes, targetItem)
751

  
752
        pool.shutdown(wait = True)
753

  
754
        chan, srcWidth, srcHeight = src.shape[::-1]
755
        drawFoundSymbolsOnCanvas(mainRes, srcWidth, srcHeight)
756
        
757
        srcName = os.path.splitext(os.path.basename(mainRes))[0]
758

  
759
        #srcName = mainRes.split("/")[-1]
760
        #srcName = srcName.replace(".png", "")
761

  
762
        
763
        pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER)
764
        for sym in searchedSymbolList:
765
            #threadLock.acquire()
766
            pool.submit(removeDetectedSymbol, sym)
767
            pool.submit(drawRectOnSrc, sym)
768
            #drawRectOnSrc()
769
            #threadLock.release()
770
        pool.shutdown(wait = True)
771
        
772
        (srcGray, tInfoList) = OCR.removeTextFromNpArray(srcGray)
773
        #srcGray = TOCR.removeTextFromNpArray(srcGray, TOCR.FLAG_IMAGE_TO_DATA)
774

  
775
        for textInfo in textInfoList:
776
            #if not checkTextInSymbol((textInfo.getX(), textInfo.getY())):
777
            removeText(srcGray, textInfo.getText(), textInfo.getX(), textInfo.getY(), textInfo.getW(), textInfo.getH())
778

  
779
        ## Remove Noise
780
        kernel1 = np.ones((2, 2), np.uint8)
781
        srcGray = cv2.dilate(srcGray, kernel1)
782
        #kernel2 = np.ones((4, 4), np.uint8)
783
        srcGray = cv2.erode(srcGray, kernel1)
784

  
785
        for sym in searchedSymbolList:
786
            drawTempLine(sym)
787

  
788
        removedSymbolImgPath = os.path.dirname(os.path.realpath(__file__)) + "\\res\\Result\\result_fslo_"+srcName+"_600dpi.png"
789
        cv2.imwrite(removedSymbolImgPath, srcGray)
790
        cv2.imwrite(os.path.dirname(os.path.realpath(__file__)) + "\\res\\Result\\result_fslo_rect_"+srcName+"_600dpi.png", src)
791

  
792

  
793
        ####### Potrace
794
        imgLineList = potrace.passpotrace(removedSymbolImgPath)
720
    try:
721
        srcList = []
722
        srcList.append(path)
723

  
724
        initTargetSymbolDataList()
725

  
726
        for mainRes in srcList:
727
            #Init src
728
            src = []
729
            srcGray = []
730
            ocrCompletedSrc = []
731
            searchedSymbolList = []
732
            textInfoList = []
733

  
734
            start = timeit.default_timer()
735

  
736
            initMainSrc(mainRes)
737

  
738
            listWidget.addItem("Start recognition : " + mainRes)
739
            
740
            #threadLock = threading.Lock()
741
            pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER)
742
            for targetItem in targetSymbolList:
743
                if type(targetItem).__name__ == 'list':
744
                    #detectSymbolsOnPid(mainRes, target)
745
                    pool.submit(detectSymbolsOnPid, mainRes, targetItem, listWidget)
746
                else:
747
                    #detectSymbolOnPid(mainRes, target)
748
                    pool.submit(detectSymbolOnPid, mainRes, targetItem, listWidget)
749

  
750
            pool.shutdown(wait = True)
751

  
752
            chan, srcWidth, srcHeight = src.shape[::-1]
753
            drawFoundSymbolsOnCanvas(mainRes, srcWidth, srcHeight, listWidget)
754
            
755
            srcName = os.path.splitext(os.path.basename(mainRes))[0]
756

  
757
            pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER)
758
            for sym in searchedSymbolList:
759
                #threadLock.acquire()
760
                pool.submit(removeDetectedSymbol, sym)
761
                pool.submit(drawRectOnSrc, sym)
762
                #drawRectOnSrc()
763
                #threadLock.release()
764
            pool.shutdown(wait = True)
765
            
766
            (srcGray, tInfoList) = OCR.removeTextFromNpArray(srcGray)
767
            #srcGray = TOCR.removeTextFromNpArray(srcGray, TOCR.FLAG_IMAGE_TO_DATA)
768

  
769
            for textInfo in textInfoList:
770
                #if not checkTextInSymbol((textInfo.getX(), textInfo.getY())):
771
                removeText(srcGray, textInfo.getText(), textInfo.getX(), textInfo.getY(), textInfo.getW(), textInfo.getH())
772

  
773
            ## Remove Noise
774
            kernel1 = np.ones((2, 2), np.uint8)
775
            srcGray = cv2.dilate(srcGray, kernel1)
776
            #kernel2 = np.ones((4, 4), np.uint8)
777
            srcGray = cv2.erode(srcGray, kernel1)
778

  
779
            for sym in searchedSymbolList:
780
                drawTempLine(sym)
781

  
782
            removedSymbolImgPath = os.path.dirname(os.path.realpath(__file__)) + "\\res\\Result\\result_fslo_"+srcName+"_600dpi.png"
783
            cv2.imwrite(removedSymbolImgPath, srcGray)
784
            cv2.imwrite(os.path.dirname(os.path.realpath(__file__)) + "\\res\\Result\\result_fslo_rect_"+srcName+"_600dpi.png", src)
785

  
786
            ####### Potrace
787
            imgLineList = potrace.passpotrace(removedSymbolImgPath)
788

  
789

  
790
            xg.writeXml(srcName, srcWidth, srcHeight, searchedSymbolList, textInfoList, imgLineList)
791
            
792
            listWidget.addItem("Searched symbol count : " + str(len(searchedSymbolList)))
793

  
794
            stop = timeit.default_timer()    
795
            seconds = stop - start
796
            f = open(os.path.dirname(os.path.realpath(__file__)) + "\\res\\Result\\result_"+srcName+"_600dpi.txt", 'a+')
797
            data = "Running Time : " + str(seconds / 60) + "min\n"
798
            f.write(data)
799
            f.close()
800

  
801
            listWidget.addItem("\nRunning Time : " + str(seconds / 60) + "min\n")
802
    except Exception as ex:
803
        msg = QMessageBox()
804
        msg.setIcon(QMessageBox.Critical)
805
        msg.setText(ex)
806
        msg.exec_()
807
    
808
class Worker(QObject):
809
    from PyQt5.QtCore import QThread
810
    from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QGridLayout
811
    import sys
795 812

  
813
    finished = pyqtSignal()
814
    intReady = pyqtSignal(int)
796 815

  
797
        xg.writeXml(srcName, srcWidth, srcHeight, searchedSymbolList, textInfoList, imgLineList)
798
        
799
        print("Searched symbol count : " + str(len(searchedSymbolList)))
800

  
801
        stop = timeit.default_timer()    
802
        seconds = stop - start
803
        f = open(os.path.dirname(os.path.realpath(__file__)) + "\\res\\Result\\result_"+srcName+"_600dpi.txt", 'a+')
804
        data = "Running Time : " + str(seconds / 60) + "min\n"
805
        f.write(data)
806
        f.close()
807
        print("\nRunning Time : " + str(seconds / 60) + "min\n")
808
    
809
    '''
810
    b, g, r = cv2.split(src)
811
    pltSrc = cv2.merge([r, g, b])
812

  
813
    plt.imshow(pltSrc)
814
    plt.imshow(cv2.cvtColor(srcGray, cv2.COLOR_GRAY2RGB))
815
    plt.show()
816

  
817
    while True:
818
        k = cv2.waitKey(0)
819
        if k == 27:
820
            cv2.destroyAllWindows()
821
            break
822
        elif k == 'r':
823
            print('result')
824
            break;
825
    '''
816
    #pyqtSlot()
817
    def procCounter(self): # A slot takes no params
818
        main(self.path, self.listWidget)
819
        self.finished.emit()
826 820

  
827 821
class ExampleApp(QMainWindow, DTI_PID_UI.Ui_MainWindow):
828 822
    def __init__(self):
829 823
        super(self.__class__, self).__init__()
830 824
        self.setupUi(self)
825
        self.graphicsView = QtImageViewer.QtImageViewer()
826
        self.graphicsView.setParent(self.centralwidget)
827
        self.verticalLayout.addWidget(self.graphicsView)
831 828

  
832
        # close MainWindow
829
        # connect signals and slots
833 830
        self.actionClose.triggered.connect(self.close)
834 831
        self.actionOpen.triggered.connect(self.openImageDrawing)
832
        self.actionRecognition.triggered.connect(self.recognize)
835 833
    
836 834
    '''
837
        Open Image Drawing File and then display it
835
        @brief Open image drawing file and then display it
838 836
    '''
839 837
    def openImageDrawing(MainWindow):
840
        options = QFileDialog.Options()
841
        options |= QFileDialog.DontUseNativeDialog
842
        path, _ = QFileDialog.getOpenFileName(MainWindow, "Select Image Drawing File", os.getcwd(), "Image Files (*.png *.jpg)", options=options) 
838
        MainWindow.path = MainWindow.graphicsView.loadImageFromFile()
839
        return MainWindow.path
840

  
841
    '''
842
        @brief recognize symbol and text
843
    '''
844
    def recognize(self, MainWindow):
845
        import Recognition_UI
846

  
847
        try:
848
            self.dlg = QDialog(self)
849
            self.ui = Recognition_UI.Ui_Recognition()
850
            self.ui.setupUi(self.dlg)
851
            self.startThread()
852
            self.dlg.show()
853
            self.dlg.exec_()
854
        except Exception as ex:
855
            print('에러가 발생했습니다.\n', ex)
856

  
857
    '''
858
        @brief start thread
859
    '''
860
    def startThread(self):
861
        self.ui.buttonBox.setDisabled(True)
862

  
863
        # 1 - create Worker and Thread inside the Form
864
        self.obj = Worker()  # no parent!
865
        self.obj.path = self.path
866
        self.obj.listWidget = self.ui.listWidget
867
        self.thread = QThread()  # no parent!
868

  
869
        # 2 - Connect Worker`s Signals to Form method slots to post data.
870
        #self.obj.intReady.connect(self.onIntReady)
871

  
872
        # 3 - Move the Worker object to the Thread object
873
        self.obj.moveToThread(self.thread)
874

  
875
        # 4 - Connect Worker Signals to the Thread slots
876
        self.obj.finished.connect(self.thread.quit)
843 877

  
844
        scene = QGraphicsScene()
845
        pixmap = QPixmap(path)
846
        MainWindow.graphicsView.setScene(scene)
847
        MainWindow.graphicsView.show()
878
        # 5 - Connect Thread started signal to Worker operational slot method
879
        self.thread.started.connect(self.obj.procCounter)
848 880

  
849
        return path
881
        # * - Thread finished signal will close the app if you want!
882
        self.thread.finished.connect(self.dlgExit)
883

  
884
        # 6 - Start the thread
885
        self.thread.start()
886

  
887
    '''
888
        @brief set buttonbox's enabled flag
889
    '''
890
    def dlgExit(self):
891
        self.ui.buttonBox.setEnabled(True)
892
        
850 893

  
851 894
if __name__ == '__main__':
852 895
    import DTI_PID_UI
......
859 902
    except Exception as ex:
860 903
        print('에러가 발생했습니다.\n', ex)
861 904

  
862
    sys.exit(app.exec_())
863

  
864
    '''
865
    try:
866
        if 1 == len(sys.argv):
867
            options = QFileDialog.Options()
868
            options |= QFileDialog.DontUseNativeDialog
869
            path, _ = QFileDialog.getOpenFileName(None, "Select Image Drawing File", os.getcwd(), "Image Files (*.png *.jpg)", options=options)
870
        elif 2 == len(sys.argv):
871
            path = sys.argv[1]  # 1 argument given is a string for the path of drawing
872
    
873
        #region Program start
874
        if len(path) and os.path.isfile(path):
875
            main(path)
876
        #endregion
877
    except Exception as ex:
878
        print('에러가 발생했습니다.\n', ex)
879

  
880
    sys.exit(app.exec_())
881
    '''
905
    sys.exit(app.exec_())
DTI_PID/DTI_PID/DTI__PID.ui
27 27
      <property name="sizeConstraint">
28 28
       <enum>QLayout::SetMaximumSize</enum>
29 29
      </property>
30
      <item>
31
       <widget class="QGraphicsView" name="graphicsView"/>
32
      </item>
33 30
     </layout>
34 31
    </item>
35 32
   </layout>
......
69 66
    <enum>TopToolBarArea</enum>
70 67
   </attribute>
71 68
   <attribute name="toolBarBreak">
72
    <bool>true</bool>
69
    <bool>false</bool>
73 70
   </attribute>
74 71
   <addaction name="actionOpen"/>
75 72
   <addaction name="actionRecognition"/>
DTI_PID/DTI_PID/QtImageViewer.py
131 131
        Without any arguments, loadImageFromFile() will popup a file dialog to choose the image file.
132 132
        With a fileName argument, loadImageFromFile(fileName) will attempt to load the specified image file directly.
133 133
        """
134

  
134 135
        if len(fileName) == 0:
136
            options = QFileDialog.Options()
137
            options |= QFileDialog.DontUseNativeDialog
135 138
            if QT_VERSION_STR[0] == '4':
136
                fileName = QFileDialog.getOpenFileName(self, "Open image file.")
139
                fileName = QFileDialog.getOpenFileName(self, "Open image file", os.getcwd(), "Image files(*.png *.jpg)", options=options)
137 140
            elif QT_VERSION_STR[0] == '5':
138
                fileName, dummy = QFileDialog.getOpenFileName(self, "Open image file.")
141
                fileName, dummy = QFileDialog.getOpenFileName(self, "Open image file", os.getcwd(), "Image files(*.png *.jpg)", options=options)
139 142
        if len(fileName) and os.path.isfile(fileName):
140 143
            image = QImage(fileName)
141 144
            self.setImage(image)
142 145

  
146
        return fileName
147

  
143 148
    def updateViewer(self):
144 149
        """ Show current zoom (if showing entire image, apply current aspect ratio mode).
145 150
        """
DTI_PID/DTI_PID/UI/dlgRecognition.ui
1
<?xml version="1.0" encoding="UTF-8"?>
2
<ui version="4.0">
3
 <class>Recognition</class>
4
 <widget class="QDialog" name="Recognition">
5
  <property name="windowModality">
6
   <enum>Qt::WindowModal</enum>
7
  </property>
8
  <property name="geometry">
9
   <rect>
10
    <x>0</x>
11
    <y>0</y>
12
    <width>845</width>
13
    <height>300</height>
14
   </rect>
15
  </property>
16
  <property name="font">
17
   <font>
18
    <family>맑은 고딕</family>
19
   </font>
20
  </property>
21
  <property name="windowTitle">
22
   <string>설계정보 인식 중...</string>
23
  </property>
24
  <layout class="QGridLayout" name="gridLayout">
25
   <item row="1" column="0">
26
    <widget class="QDialogButtonBox" name="buttonBox">
27
     <property name="enabled">
28
      <bool>false</bool>
29
     </property>
30
     <property name="orientation">
31
      <enum>Qt::Horizontal</enum>
32
     </property>
33
     <property name="standardButtons">
34
      <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
35
     </property>
36
    </widget>
37
   </item>
38
   <item row="0" column="0">
39
    <widget class="QListWidget" name="listWidget"/>
40
   </item>
41
  </layout>
42
 </widget>
43
 <resources/>
44
 <connections>
45
  <connection>
46
   <sender>buttonBox</sender>
47
   <signal>accepted()</signal>
48
   <receiver>Recognition</receiver>
49
   <slot>accept()</slot>
50
   <hints>
51
    <hint type="sourcelabel">
52
     <x>248</x>
53
     <y>254</y>
54
    </hint>
55
    <hint type="destinationlabel">
56
     <x>157</x>
57
     <y>274</y>
58
    </hint>
59
   </hints>
60
  </connection>
61
  <connection>
62
   <sender>buttonBox</sender>
63
   <signal>rejected()</signal>
64
   <receiver>Recognition</receiver>
65
   <slot>reject()</slot>
66
   <hints>
67
    <hint type="sourcelabel">
68
     <x>316</x>
69
     <y>260</y>
70
    </hint>
71
    <hint type="destinationlabel">
72
     <x>286</x>
73
     <y>274</y>
74
    </hint>
75
   </hints>
76
  </connection>
77
 </connections>
78
</ui>

내보내기 Unified diff