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_())
|