개정판 a3dcb1a9
QRecognitionDialog 멈춤 현상 개선
DTI_PID/DTI_PID/DTI_PID.py | ||
---|---|---|
655 | 655 |
canvas[::] = (255, 255, 255) |
656 | 656 |
|
657 | 657 |
try: |
658 |
#pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER) |
|
659 | 658 |
for symbol in searchedSymbolList: |
660 |
#pool.submit(drawFoundSymbols, symbol) |
|
661 | 659 |
drawFoundSymbols(symbol, listWidget) |
662 |
#pool.shutdown(wait = True) |
|
663 | 660 |
|
664 | 661 |
for text in textInfoList: |
665 | 662 |
if not checkTextInSymbol((text.getX(), text.getY())): |
... | ... | |
713 | 710 |
Jeongwoo 2018.05.25 Add condition on if-statemen |
714 | 711 |
''' |
715 | 712 |
def initMainSrc(mainRes): |
716 |
global src |
|
717 | 713 |
global srcGray |
718 | 714 |
global ocrCompletedSrc |
719 | 715 |
global textInfoList |
... | ... | |
721 | 717 |
|
722 | 718 |
try: |
723 | 719 |
if os.path.isfile(mainRes): |
724 |
#load original src & symbol |
|
725 |
src = cv2.imread(mainRes, 1) |
|
726 |
|
|
727 |
#gray scale |
|
728 |
if len(src.shape) == 3: |
|
729 |
srcGray = cvtGrayImage(src) |
|
730 |
else: |
|
731 |
srcGray = src.copy() |
|
732 |
srcGray = cv2.threshold(srcGray, 127, 255, cv2.THRESH_BINARY)[1] |
|
733 |
|
|
734 | 720 |
ocrCompletedSrc = srcGray.copy() |
735 | 721 |
|
736 | 722 |
area = AppDocData.instance().getArea('Drawing') |
737 |
if area is not None: |
|
738 |
#TODO: 영역을 설정한 값과 이미지 좌표계를 차이를 보정 |
|
739 |
area.img = srcGray[round(area.y+1):round(area.y+area.height), round(area.x+1):round(area.x+area.width)] |
|
740 |
|
|
723 |
|
|
741 | 724 |
#(_tempOcrSrc, textInfoList) = OCR.removeTextFromNpArray(area.img if area is not None else srcGray, area.x if area is not None else 0, area.y if area is not None else 0) |
742 | 725 |
(_tempOcrSrc, tInfoList) = OCR.removeTextFromNpArray(area.img if area is not None else srcGray, area.x if area is not None else 0, area.y if area is not None else 0) |
743 | 726 |
|
... | ... | |
764 | 747 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
765 | 748 |
|
766 | 749 |
''' |
750 |
@brief remove small objects from given image |
|
751 |
@author humkyung |
|
752 |
@date 2018.04.26 |
|
753 |
@history 2018.05.25 Jeongwoo Moved from MainWindow |
|
754 |
''' |
|
755 |
def removeSmallObjects(image): |
|
756 |
try: |
|
757 |
docData = AppDocData.instance() |
|
758 |
configs = docData.getConfigs('Small Object Size', 'Min Area') |
|
759 |
minArea = int(configs[0].value) if 1 == len(configs) else 20 |
|
760 |
configs = docData.getConfigs('Small Object Size', 'Max Area') |
|
761 |
maxArea = int(configs[0].value) if 1 == len(configs) else 50 |
|
762 |
|
|
763 |
#path = os.path.join(AppDocData.instance().getCurrentProject().getTempPath(), 'before_contours.png') |
|
764 |
#cv2.imwrite(path, image) |
|
765 |
|
|
766 |
_,contours,_ = cv2.findContours(image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE); |
|
767 |
selectedContours=[] |
|
768 |
for contour in contours: |
|
769 |
#if cv2.isContourConvex(contour): |
|
770 |
#approx = cv2.approxPolyDP(contour, 0.2*cv2.arcLength(contour, True), True) |
|
771 |
area = cv2.contourArea(contour) |
|
772 |
if area > minArea and area < maxArea: selectedContours.append(contour) |
|
773 |
contourImage = cv2.drawContours(image, selectedContours, -1, (255,255,255), -1); # draw contour with white color |
|
774 |
#path = os.path.join(AppDocData.instance().getCurrentProject().getTempPath(), 'contours.png') |
|
775 |
#cv2.imwrite(path, contourImage) |
|
776 |
except Exception as ex: |
|
777 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
778 |
|
|
779 |
return contourImage |
|
780 |
|
|
781 |
''' |
|
782 |
@history 2018.05.25 Jeongwoo Moved from MainWindow |
|
783 |
''' |
|
784 |
def recognizeLine(listWidget, graphicsView): |
|
785 |
from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem |
|
786 |
from QEngineeringLineNoTextItem import QEngineeringLineNoTextItem |
|
787 |
from QEngineeringTextItem import QEngineeringTextItem |
|
788 |
from LineDetector import LineDetector |
|
789 |
|
|
790 |
try: |
|
791 |
#remove already existing line and flow arrow item |
|
792 |
items = [item for item in graphicsView.scene.items() if (type(item) is QEngineeringLineItem) or (type(item) is QEngineeringFlowArrowItem)] |
|
793 |
for item in items: |
|
794 |
graphicsView.scene.removeItem(item) |
|
795 |
#up to here |
|
796 |
|
|
797 |
# detect line |
|
798 |
connectedLines = [] |
|
799 |
|
|
800 |
area = AppDocData.instance().getArea('Drawing') |
|
801 |
area.img = removeSmallObjects(area.img) |
|
802 |
detector = LineDetector(area.img) |
|
803 |
|
|
804 |
symbols = [] |
|
805 |
for item in graphicsView.scene.items(): |
|
806 |
if issubclass(type(item), SymbolSvgItem): |
|
807 |
symbols.append(item) |
|
808 |
res = detector.detectConnectedLine(item, round(area.x), round(area.y)) |
|
809 |
if res is not None: |
|
810 |
for line in res: connectedLines.append(line) |
|
811 |
|
|
812 |
texts = [item for item in graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)] |
|
813 |
for symbol in symbols: |
|
814 |
symbol.connectAttribute(texts) |
|
815 |
|
|
816 |
lineNos = [item for item in graphicsView.scene.items() if type(item) is QEngineeringLineNoTextItem] |
|
817 |
|
|
818 |
if len(connectedLines) > 1: |
|
819 |
detector.mergeLines(connectedLines, toler=20) |
|
820 |
# connect line to symbol |
|
821 |
try: |
|
822 |
for line in connectedLines: |
|
823 |
matches = [symbol for symbol in symbols if symbol.isConnectable(line, (round(area.x), round(area.y)), toler=20)] |
|
824 |
for symbol in matches: |
|
825 |
detector.connectLineToSymbol(line, (round(area.x), round(area.y)), symbol) |
|
826 |
except Exception as ex: |
|
827 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
828 |
# up to here |
|
829 |
|
|
830 |
# connect line to line |
|
831 |
try: |
|
832 |
for line in connectedLines[:]: |
|
833 |
matches = [it for it in connectedLines if (line != it) and (not detector.isParallel(line, it))] |
|
834 |
for match in matches: |
|
835 |
detector.connectLineToLine(match, line) |
|
836 |
except Exception as ex: |
|
837 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
838 |
# up to here |
|
839 |
|
|
840 |
lines = [] |
|
841 |
for pts in connectedLines: |
|
842 |
processLine = QEngineeringLineItem() |
|
843 |
lines.append(processLine) |
|
844 |
for pt in pts: |
|
845 |
processLine._pol.append(QPointF(pt[0] + round(area.x), pt[1] + round(area.y))) |
|
846 |
processLine.buildItem() |
|
847 |
graphicsView.scene.addItem(processLine) |
|
848 |
except Exception as ex: |
|
849 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
850 |
finally: |
|
851 |
listWidget.addItem('Finish Line searching') |
|
852 |
|
|
853 |
''' |
|
767 | 854 |
@brief Main function |
768 | 855 |
@author jwkim |
769 | 856 |
@date |
... | ... | |
771 | 858 |
Jeongwoo 2018.04.25 Remove 'Current Symbol : ' QListItem |
772 | 859 |
Jeongwoo 2018.05.09 Make Comments OCR.removeTextFromNpArray block |
773 | 860 |
Jeongwoo 2018.05.25 Remove imgLineList variable and parameter on writeXml() |
861 |
humkyung 2018.05.26 add parameters(graphicsView, isSymbolTextChecked, isLineChecked) |
|
774 | 862 |
''' |
775 |
def executeRecognition(path, listWidget): |
|
776 |
global src |
|
863 |
def executeRecognition(path, listWidget, graphicsView, isSymbolTextChecked, isLineChecked): |
|
777 | 864 |
global srcGray |
778 | 865 |
global ocrCompletedSrc |
779 | 866 |
global searchedSymbolList |
... | ... | |
799 | 886 |
searchedSymbolList = [] |
800 | 887 |
textInfoList = [] |
801 | 888 |
|
802 |
#start = timeit.default_timer() |
|
803 |
|
|
804 |
initMainSrc(mainRes) |
|
889 |
if not os.path.isfile(mainRes): |
|
890 |
item = QListWidgetItem('{} file is not found'.format(os.path.basename(mainRes))) |
|
891 |
item.setBackground(Qt.red) |
|
892 |
listWidget.addItem(item) |
|
893 |
continue |
|
805 | 894 |
|
806 |
listWidget.addItem("Start recognition : " + mainRes) |
|
807 |
|
|
808 |
#threadLock = threading.Lock() |
|
809 |
pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER) |
|
810 |
for targetItem in targetSymbolList: |
|
811 |
if type(targetItem).__name__ == 'list': |
|
812 |
#detectSymbolsOnPid(mainRes, target) |
|
813 |
pool.submit(detectSymbolsOnPid, mainRes, targetItem, listWidget) |
|
814 |
else: |
|
815 |
#detectSymbolOnPid(mainRes, target) |
|
816 |
pool.submit(detectSymbolOnPid, mainRes, targetItem, listWidget) |
|
817 |
|
|
818 |
pool.shutdown(wait = True) |
|
819 |
|
|
820 |
chan, docData.imgWidth, docData.imgHeight = src.shape[::-1] |
|
821 |
drawFoundSymbolsOnCanvas(mainRes, docData.imgWidth, docData.imgHeight, listWidget) |
|
822 |
|
|
823 |
docData.imgName = os.path.splitext(os.path.basename(mainRes))[0] |
|
824 |
|
|
825 |
pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER) |
|
826 |
for sym in searchedSymbolList: |
|
827 |
#threadLock.acquire() |
|
828 |
pool.submit(removeDetectedSymbol, sym) |
|
829 |
pool.submit(drawRectOnSrc, sym) |
|
830 |
#drawRectOnSrc() |
|
831 |
#threadLock.release() |
|
832 |
pool.shutdown(wait = True) |
|
895 |
#load original src & symbol |
|
896 |
src = cv2.imread(mainRes, 1) |
|
897 |
|
|
898 |
#gray scale |
|
899 |
if len(src.shape) == 3: |
|
900 |
srcGray = cvtGrayImage(src) |
|
901 |
else: |
|
902 |
srcGray = src.copy() |
|
903 |
srcGray = cv2.threshold(srcGray, 127, 255, cv2.THRESH_BINARY)[1] |
|
833 | 904 |
|
834 |
####area = AppDocData.instance().getArea('Drawing') |
|
835 |
####(_tempOcrSrc, tInfoList) = OCR.removeTextFromNpArray(area.img if area is not None else srcGray, area.x if area is not None else 0, area.y if area is not None else 0) |
|
836 |
#####(srcGray, tInfoList) = OCR.removeTextFromNpArray(area.img if area is not None else srcGray) |
|
837 |
####if area is not None: |
|
838 |
#### srcGray[int(area.y):int(area.y+area.height), int(area.x):int(area.x+area.width)] = _tempOcrSrc |
|
839 |
####else: |
|
840 |
#### srcGray = _tempOcrSrc |
|
841 |
####srcGray = TOCR.removeTextFromNpArray(srcGray, TOCR.FLAG_IMAGE_TO_DATA) |
|
842 |
global MIN_TEXT_SIZE |
|
843 |
for textInfo in textInfoList: |
|
844 |
#if not checkTextInSymbol((textInfo.getX(), textInfo.getY())): |
|
845 |
if textInfo.getW() >= MIN_TEXT_SIZE or textInfo.getH() >= MIN_TEXT_SIZE: |
|
846 |
removeText(srcGray, textInfo.getText(), textInfo.getX(), textInfo.getY(), textInfo.getW(), textInfo.getH()) |
|
847 |
|
|
848 |
## Remove Noise |
|
849 |
kernel1 = np.ones((2, 2), np.uint8) |
|
850 |
srcGray = cv2.dilate(srcGray, kernel1) |
|
851 |
#kernel2 = np.ones((4, 4), np.uint8) |
|
852 |
srcGray = cv2.erode(srcGray, kernel1) |
|
853 |
|
|
854 |
removedSymbolImgPath = os.path.join(project.getTempPath(), os.path.basename(path)) |
|
855 |
cv2.imwrite(removedSymbolImgPath, srcGray) |
|
856 |
area = AppDocData.instance().getArea('Drawing') |
|
905 |
area = docData.getArea('Drawing') |
|
857 | 906 |
if area is not None: |
907 |
#TODO: 영역을 설정한 값과 이미지 좌표계를 차이를 보정 |
|
858 | 908 |
area.img = srcGray[round(area.y+1):round(area.y+area.height), round(area.x+1):round(area.x+area.width)] |
859 |
cv2.imwrite(os.path.join(project.getTempPath(), "rect_" + os.path.basename(path)), src) |
|
909 |
|
|
910 |
listWidget.addItem("Start recognition : " + mainRes) |
|
911 |
|
|
912 |
if isSymbolTextChecked: |
|
913 |
initMainSrc(mainRes) |
|
914 |
|
|
915 |
#threadLock = threading.Lock() |
|
916 |
pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER) |
|
917 |
for targetItem in targetSymbolList: |
|
918 |
if type(targetItem).__name__ == 'list': |
|
919 |
#detectSymbolsOnPid(mainRes, target) |
|
920 |
pool.submit(detectSymbolsOnPid, mainRes, targetItem, listWidget) |
|
921 |
else: |
|
922 |
#detectSymbolOnPid(mainRes, target) |
|
923 |
pool.submit(detectSymbolOnPid, mainRes, targetItem, listWidget) |
|
924 |
|
|
925 |
pool.shutdown(wait = True) |
|
926 |
|
|
927 |
chan, docData.imgWidth, docData.imgHeight = src.shape[::-1] |
|
928 |
drawFoundSymbolsOnCanvas(mainRes, docData.imgWidth, docData.imgHeight, listWidget) |
|
929 |
|
|
930 |
docData.imgName = os.path.splitext(os.path.basename(mainRes))[0] |
|
931 |
|
|
932 |
pool = futures.ThreadPoolExecutor(max_workers = THREAD_MAX_WORKER) |
|
933 |
for sym in searchedSymbolList: |
|
934 |
#threadLock.acquire() |
|
935 |
pool.submit(removeDetectedSymbol, sym) |
|
936 |
pool.submit(drawRectOnSrc, sym) |
|
937 |
#drawRectOnSrc() |
|
938 |
#threadLock.release() |
|
939 |
pool.shutdown(wait = True) |
|
940 |
|
|
941 |
####area = AppDocData.instance().getArea('Drawing') |
|
942 |
####(_tempOcrSrc, tInfoList) = OCR.removeTextFromNpArray(area.img if area is not None else srcGray, area.x if area is not None else 0, area.y if area is not None else 0) |
|
943 |
#####(srcGray, tInfoList) = OCR.removeTextFromNpArray(area.img if area is not None else srcGray) |
|
944 |
####if area is not None: |
|
945 |
#### srcGray[int(area.y):int(area.y+area.height), int(area.x):int(area.x+area.width)] = _tempOcrSrc |
|
946 |
####else: |
|
947 |
#### srcGray = _tempOcrSrc |
|
948 |
####srcGray = TOCR.removeTextFromNpArray(srcGray, TOCR.FLAG_IMAGE_TO_DATA) |
|
949 |
global MIN_TEXT_SIZE |
|
950 |
for textInfo in textInfoList: |
|
951 |
#if not checkTextInSymbol((textInfo.getX(), textInfo.getY())): |
|
952 |
if textInfo.getW() >= MIN_TEXT_SIZE or textInfo.getH() >= MIN_TEXT_SIZE: |
|
953 |
removeText(srcGray, textInfo.getText(), textInfo.getX(), textInfo.getY(), textInfo.getW(), textInfo.getH()) |
|
954 |
|
|
955 |
## Remove Noise |
|
956 |
kernel1 = np.ones((2, 2), np.uint8) |
|
957 |
srcGray = cv2.dilate(srcGray, kernel1) |
|
958 |
#kernel2 = np.ones((4, 4), np.uint8) |
|
959 |
srcGray = cv2.erode(srcGray, kernel1) |
|
960 |
|
|
961 |
removedSymbolImgPath = os.path.join(project.getTempPath(), os.path.basename(path)) |
|
962 |
cv2.imwrite(removedSymbolImgPath, srcGray) |
|
963 |
area = AppDocData.instance().getArea('Drawing') |
|
964 |
if area is not None: |
|
965 |
area.img = srcGray[round(area.y+1):round(area.y+area.height), round(area.x+1):round(area.x+area.width)] |
|
966 |
cv2.imwrite(os.path.join(project.getTempPath(), "rect_" + os.path.basename(path)), src) |
|
967 |
|
|
968 |
listWidget.addItem("Searched symbol count : " + str(len(searchedSymbolList))) |
|
969 |
|
|
970 |
if isLineChecked: |
|
971 |
recognizeLine(listWidget, graphicsView) |
|
860 | 972 |
|
861 | 973 |
xmlPath = xg.writeXml(docData.imgName, docData.imgWidth, docData.imgHeight, searchedSymbolList, textInfoList, noteTextInfoList) |
862 | 974 |
res.append(xmlPath) |
863 |
|
|
864 |
listWidget.addItem("Searched symbol count : " + str(len(searchedSymbolList))) |
|
865 |
|
|
866 |
#stop = timeit.default_timer() |
|
867 |
#seconds = stop - start |
|
868 |
|
|
869 |
#listWidget.addItem("\nRunning Time : " + str(seconds / 60) + "min\n") |
|
870 | 975 |
except Exception as ex: |
871 | 976 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
872 | 977 |
|
DTI_PID/DTI_PID/QRecognitionDialog.py | ||
---|---|---|
13 | 13 |
from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem |
14 | 14 |
from SymbolSvgItem import SymbolSvgItem |
15 | 15 |
from QEngineeringTextItem import QEngineeringTextItem |
16 |
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
|
16 | 17 |
|
17 | 18 |
''' |
18 | 19 |
@history 2018.05.25 Jeongwoo Add pyqtSignal(recognizeLine, loadRecognitionResult) |
... | ... | |
32 | 33 |
@history 2018.05.25 Jeongwoo Add if-statements by isSymbolTextChecked and isLineChecked variable |
33 | 34 |
''' |
34 | 35 |
#pyqtSlot() |
35 |
def procCounter(self, isSymbolTextChecked, isLineChecked): # A slot takes no params
|
|
36 |
def procCounter(self): # A slot takes no params |
|
36 | 37 |
from DTI_PID import executeRecognition |
37 | 38 |
import timeit |
38 | 39 |
|
39 | 40 |
try: |
40 | 41 |
start = timeit.default_timer() |
41 | 42 |
self.xmlPath = None |
42 |
if isSymbolTextChecked: |
|
43 |
self.xmlPath = executeRecognition(self.path, self.listWidget) |
|
44 |
if self.xmlPath is not None and len(self.xmlPath) > 0: |
|
45 |
self.loadRecognitionResult.emit(self.xmlPath[0]) |
|
46 |
if isLineChecked: |
|
47 |
self.recognizeLine.emit() |
|
43 |
self.xmlPath = executeRecognition(self.path, self.listWidget, self.graphicsView, self.isSymbolTextChecked, self.isLineChecked) |
|
48 | 44 |
self.finished.emit() |
49 | 45 |
except Exception as ex: |
50 | 46 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
... | ... | |
90 | 86 |
QDialog.accept(self) |
91 | 87 |
|
92 | 88 |
def recognizeButtonClicked(self, event): |
93 |
self.startThread() |
|
89 |
if self.ui.symbolTextCheckBox.isChecked() or self.ui.lineCheckBox.isChecked(): |
|
90 |
self.startThread() |
|
94 | 91 |
|
95 | 92 |
''' |
96 | 93 |
@brief start thread |
... | ... | |
105 | 102 |
self.obj = Worker() # no parent! |
106 | 103 |
self.obj.path = self.path |
107 | 104 |
self.obj.listWidget = self.ui.listWidget |
105 |
self.obj.graphicsView = self.graphicsView |
|
106 |
self.obj.isSymbolTextChecked = self.ui.symbolTextCheckBox.isChecked() |
|
107 |
self.obj.isLineChecked = self.ui.lineCheckBox.isChecked() |
|
108 | 108 |
self.thread = QThread() # no parent! |
109 | 109 |
|
110 | 110 |
# 2 - Connect Worker`s Signals to Form method slots to post data. |
... | ... | |
115 | 115 |
|
116 | 116 |
# 4 - Connect Worker Signals to the Thread slots |
117 | 117 |
self.obj.finished.connect(self.thread.quit) |
118 |
self.obj.recognizeLine.connect(self.recognizeLine) |
|
119 |
self.obj.loadRecognitionResult.connect(self.loadRecognitionResult) |
|
120 | 118 |
|
121 | 119 |
# 5 - Connect Thread started signal to Worker operational slot method |
122 |
self.thread.started.connect(lambda : self.obj.procCounter(self.ui.symbolTextCheckBox.isChecked(), self.ui.lineCheckBox.isChecked()))
|
|
120 |
self.thread.started.connect(self.obj.procCounter)
|
|
123 | 121 |
|
124 | 122 |
# * - Thread finished signal will close the app if you want! |
125 | 123 |
self.thread.finished.connect(self.dlgExit) |
... | ... | |
132 | 130 |
@history 2018.05.25 Jeongwoo Moved from MainWindow |
133 | 131 |
''' |
134 | 132 |
def dlgExit(self): |
135 |
self.xmlPath = self.obj.xmlPath |
|
136 |
self.ui.buttonBox.setEnabled(True) |
|
137 |
|
|
138 |
''' |
|
139 |
@brief remove small objects from given image |
|
140 |
@author humkyung |
|
141 |
@date 2018.04.26 |
|
142 |
@history 2018.05.25 Jeongwoo Moved from MainWindow |
|
143 |
''' |
|
144 |
def removeSmallObjects(self, image): |
|
145 | 133 |
try: |
146 |
docData = AppDocData.instance() |
|
147 |
configs = docData.getConfigs('Small Object Size', 'Min Area') |
|
148 |
minArea = int(configs[0].value) if 1 == len(configs) else 20 |
|
149 |
configs = docData.getConfigs('Small Object Size', 'Max Area') |
|
150 |
maxArea = int(configs[0].value) if 1 == len(configs) else 50 |
|
151 |
|
|
152 |
#path = os.path.join(AppDocData.instance().getCurrentProject().getTempPath(), 'before_contours.png') |
|
153 |
#cv2.imwrite(path, image) |
|
154 |
|
|
155 |
_,contours,_ = cv2.findContours(image, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE); |
|
156 |
selectedContours=[] |
|
157 |
for contour in contours: |
|
158 |
#if cv2.isContourConvex(contour): |
|
159 |
#approx = cv2.approxPolyDP(contour, 0.2*cv2.arcLength(contour, True), True) |
|
160 |
area = cv2.contourArea(contour) |
|
161 |
if area > minArea and area < maxArea: selectedContours.append(contour) |
|
162 |
contourImage = cv2.drawContours(image, selectedContours, -1, (255,255,255), -1); |
|
163 |
#path = os.path.join(AppDocData.instance().getCurrentProject().getTempPath(), 'contours.png') |
|
164 |
#cv2.imwrite(path, contourImage) |
|
134 |
self.xmlPath = self.obj.xmlPath |
|
135 |
self.loadRecognitionResult(self.xmlPath[0]) |
|
136 |
self.ui.buttonBox.setEnabled(True) |
|
165 | 137 |
except Exception as ex: |
166 | 138 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
167 | 139 |
|
168 |
return contourImage |
|
169 |
|
|
170 | 140 |
''' |
171 | 141 |
@history 2018.05.25 Jeongwoo Moved from MainWindow |
172 | 142 |
SvgItem and TextItem Connect with method in this class |
... | ... | |
256 | 226 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
257 | 227 |
|
258 | 228 |
''' |
259 |
@history 2018.05.25 Jeongwoo Moved from MainWindow |
|
260 |
''' |
|
261 |
def recognizeLine(self): |
|
262 |
try: |
|
263 |
#remove already existing line and flow arrow item |
|
264 |
items = [item for item in self.graphicsView.scene.items() if (type(item) is QEngineeringLineItem) or (type(item) is QEngineeringFlowArrowItem)] |
|
265 |
for item in items: |
|
266 |
self.graphicsView.scene.removeItem(item) |
|
267 |
#up to here |
|
268 |
|
|
269 |
# detect line |
|
270 |
connectedLines = [] |
|
271 |
|
|
272 |
area = AppDocData.instance().getArea('Drawing') |
|
273 |
area.img = self.removeSmallObjects(area.img) |
|
274 |
detector = LineDetector(area.img) |
|
275 |
|
|
276 |
symbols = [] |
|
277 |
for item in self.graphicsView.scene.items(): |
|
278 |
if issubclass(type(item), SymbolSvgItem): |
|
279 |
symbols.append(item) |
|
280 |
res = detector.detectConnectedLine(item, round(area.x), round(area.y)) |
|
281 |
if res is not None: |
|
282 |
for line in res: connectedLines.append(line) |
|
283 |
|
|
284 |
texts = [item for item in self.graphicsView.scene.items() if issubclass(type(item), QEngineeringTextItem)] |
|
285 |
for symbol in symbols: |
|
286 |
symbol.connectAttribute(texts) |
|
287 |
|
|
288 |
lineNos = [item for item in self.graphicsView.scene.items() if type(item) is QEngineeringLineNoTextItem] |
|
289 |
|
|
290 |
if len(connectedLines) > 1: |
|
291 |
detector.mergeLines(connectedLines, toler=20) |
|
292 |
# connect line to symbol |
|
293 |
try: |
|
294 |
for line in connectedLines: |
|
295 |
matches = [symbol for symbol in symbols if symbol.isConnectable(line, (round(area.x), round(area.y)), toler=20)] |
|
296 |
for symbol in matches: |
|
297 |
detector.connectLineToSymbol(line, (round(area.x), round(area.y)), symbol) |
|
298 |
except Exception as ex: |
|
299 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
300 |
# up to here |
|
301 |
|
|
302 |
# connect line to line |
|
303 |
try: |
|
304 |
for line in connectedLines[:]: |
|
305 |
matches = [it for it in connectedLines if (line != it) and (not detector.isParallel(line, it))] |
|
306 |
for match in matches: |
|
307 |
detector.connectLineToLine(match, line) |
|
308 |
except Exception as ex: |
|
309 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
310 |
# up to here |
|
311 |
|
|
312 |
lines = [] |
|
313 |
for pts in connectedLines: |
|
314 |
processLine = QEngineeringLineItem() |
|
315 |
lines.append(processLine) |
|
316 |
for pt in pts: |
|
317 |
processLine._pol.append(QPointF(pt[0] + round(area.x), pt[1] + round(area.y))) |
|
318 |
processLine.buildItem() |
|
319 |
self.graphicsView.scene.addItem(processLine) |
|
320 |
except Exception as ex: |
|
321 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
322 |
finally: |
|
323 |
self.ui.listWidget.addItem('Finish Line searching') |
|
324 |
|
|
325 |
''' |
|
326 | 229 |
@brief Emit svgItem to slot on MainWindow |
327 | 230 |
@date 2018.05.25 |
328 | 231 |
@author Jeongwoo |
내보내기 Unified diff