개정판 d6d16d45
fixed issue #478:
- Unknown 항목들을 선택하여 텍스트 인식
DTI_PID/DTI_PID/Commands/AreaOcrCommand.py | ||
---|---|---|
10 | 10 |
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QPainter, QColor, QPen, QBrush, QCursor, QTransform, QFont, QRegExpValidator, QValidator |
11 | 11 |
except ImportError: |
12 | 12 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
13 |
import QOcrResultDialog
|
|
13 |
import OcrResultDialog |
|
14 | 14 |
import sys |
15 | 15 |
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + '\\Shapes') |
16 | 16 |
from QEngineeringTextItem import QEngineeringTextItem |
... | ... | |
20 | 20 |
from AppDocData import AppDocData |
21 | 21 | |
22 | 22 |
class AreaOcrCommand(AbstractCommand.AbstractCommand): |
23 |
onSuccess = pyqtSignal(float, float, float, float) |
|
24 | ||
23 | 25 |
def __init__(self, imageViewer): |
24 | 26 |
super(AreaOcrCommand, self).__init__(imageViewer) |
25 | 27 |
self.name = 'AreaOcr' |
... | ... | |
51 | 53 |
self.imageViewer.scene.setSelectionArea(QPainterPath()) # Clear current selection area. |
52 | 54 |
if selectionBBox.isValid(): |
53 | 55 |
if self.imageViewer.hasImage(): |
54 |
image = self.imageViewer.image().copy(selectionBBox.toAlignedRect()) |
|
55 |
dialog = QOcrResultDialog.QOcrResultDialog(self.imageViewer, image, selectionBBox) |
|
56 |
(isAccept, textInfoList) = dialog.showDialog() |
|
57 |
|
|
58 |
if isAccept: |
|
59 |
if textInfoList is not None and len(textInfoList) > 0: |
|
60 |
docData = AppDocData.instance() |
|
61 |
configs = docData.getConfigs('Line No', 'Delimiter') |
|
62 |
delimiter = configs[0].value if 1 == len(configs) else '-' |
|
63 |
lineNoconfigs = docData.getConfigs('Line No', 'Configuration') |
|
64 |
for textInfo in textInfoList: |
|
65 |
print("Accepted") |
|
66 |
x = textInfo.getX() |
|
67 |
y = textInfo.getY() |
|
68 |
angle = textInfo.getAngle() |
|
69 |
text = textInfo.getText() |
|
70 |
width = textInfo.getW() |
|
71 |
height = textInfo.getH() |
|
72 |
item = TextItemFactory.instance().createTextItem(text, delimiter, lineNoconfigs) |
|
73 |
item.loc = (x, y)#(int(selectionBBox.x() + x), int(selectionBBox.y() + y)) |
|
74 |
item.size = (width, height) |
|
75 |
item.angle = angle |
|
76 |
item.setPlainText(text) |
|
77 |
item.setDefaultTextColor(Qt.blue) |
|
78 |
item.addTextItemToScene(self.imageViewer.scene) |
|
79 |
else: |
|
80 |
QMessageBox.about(self.imageViewer, "알림", "텍스트 검출 실패") |
|
56 |
rect = selectionBBox.toAlignedRect() |
|
57 |
self.onSuccess.emit(rect.left(), rect.top(), rect.width(), rect.height()) |
|
81 | 58 |
else: |
82 | 59 |
QMessageBox.about(self.imageViewer, "알림", "부적절한 이미지입니다.\n이미지를 확인해주세요.") |
83 | 60 |
finally: |
DTI_PID/DTI_PID/Commands/FenceCommand.py | ||
---|---|---|
41 | 41 |
width = abs(self._vertices[0].x() - self._vertices[1].x()) |
42 | 42 |
height = abs(self._vertices[0].y() - self._vertices[1].y()) |
43 | 43 |
self.onSuccess.emit(x, y, width, height) |
44 |
pass |
|
45 | 44 |
self.isTreated = False |
46 | 45 | |
47 | 46 |
''' |
DTI_PID/DTI_PID/DTI_PID.pyproj | ||
---|---|---|
72 | 72 |
<Compile Include="QEquipmentDataListDialog.py" /> |
73 | 73 |
<Compile Include="QInstrumentDataListDialog.py" /> |
74 | 74 |
<Compile Include="QLineDataListDialog.py" /> |
75 |
<Compile Include="QOcrResultDialog.py" />
|
|
75 |
<Compile Include="OcrResultDialog.py" /> |
|
76 | 76 |
<Compile Include="PropertyTableWidget.py" /> |
77 | 77 |
<Compile Include="QRecognitionDialog.py" /> |
78 | 78 |
<Compile Include="ItemPropertyTableWidget.py" /> |
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
382 | 382 |
return |
383 | 383 | |
384 | 384 |
if self.actionOCR.isChecked(): |
385 |
self.graphicsView.command = AreaOcrCommand.AreaOcrCommand(self.graphicsView) |
|
385 |
cmd = AreaOcrCommand.AreaOcrCommand(self.graphicsView) |
|
386 |
cmd.onSuccess.connect(self.onRecognizeText) |
|
387 |
self.graphicsView.command = cmd |
|
386 | 388 |
else: |
387 | 389 |
self.graphicsView.useDefaultCommand() |
388 | 390 |
|
389 | 391 |
''' |
392 |
@brief show text recognition dialog |
|
393 |
@author humkyung |
|
394 |
@date 2018.08.08 |
|
395 |
''' |
|
396 |
def onRecognizeText(self, x, y, width, height): |
|
397 |
from OcrResultDialog import QOcrResultDialog |
|
398 | ||
399 |
try: |
|
400 |
image = self.graphicsView.image().copy(x, y, width, height) |
|
401 |
dialog = QOcrResultDialog(self.graphicsView, image, QRectF(x, y, width, height)) |
|
402 |
(isAccept, textInfoList) = dialog.showDialog() |
|
403 |
if isAccept: |
|
404 |
if textInfoList is not None and len(textInfoList) > 0: |
|
405 |
docData = AppDocData.instance() |
|
406 |
configs = docData.getConfigs('Line No', 'Delimiter') |
|
407 |
delimiter = configs[0].value if 1 == len(configs) else '-' |
|
408 |
lineNoconfigs = docData.getConfigs('Line No', 'Configuration') |
|
409 |
for textInfo in textInfoList: |
|
410 |
x = textInfo.getX() |
|
411 |
y = textInfo.getY() |
|
412 |
angle = textInfo.getAngle() |
|
413 |
text = textInfo.getText() |
|
414 |
width = textInfo.getW() |
|
415 |
height = textInfo.getH() |
|
416 |
item = TextItemFactory.instance().createTextItem(text, delimiter, lineNoconfigs) |
|
417 |
item.loc = (x, y) |
|
418 |
item.size = (width, height) |
|
419 |
item.angle = angle |
|
420 |
item.setPlainText(text) |
|
421 |
item.setDefaultTextColor(Qt.blue) |
|
422 |
item.addTextItemToScene(self.imageViewer.scene) |
|
423 |
else: |
|
424 |
QMessageBox.about(self.graphicsView, "알림", "텍스트 검출 실패") |
|
425 |
except Exception as ex: |
|
426 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
427 |
self.addMessage(MessageType.Error, message) |
|
428 | ||
429 |
''' |
|
390 | 430 |
@brief area configuration |
391 | 431 |
''' |
392 | 432 |
def areaConfiguration(self): |
DTI_PID/DTI_PID/OcrResultDialog.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 | ||
3 |
from PyQt5.QtCore import * |
|
4 |
from PyQt5.QtGui import * |
|
5 |
from PyQt5.QtWidgets import * |
|
6 |
import UI_OcrResultDialog |
|
7 |
import QtImageViewer |
|
8 |
import tesseract_ocr_module as TOCR |
|
9 |
from PIL import Image |
|
10 |
import io |
|
11 |
import numpy as np |
|
12 |
import cv2 |
|
13 |
import math |
|
14 |
from App import App |
|
15 | ||
16 |
class QOcrResultDialog(QDialog): |
|
17 |
def __init__(self, parent, qimage, boundingBox, isModify = False, text = None): |
|
18 |
QDialog.__init__(self, parent) |
|
19 |
self.textInfoList = None |
|
20 | ||
21 |
self.isModify = isModify |
|
22 |
self.image = qimage |
|
23 |
self.originImageWidth = qimage.width() |
|
24 |
self.originImageHeight = qimage.height() |
|
25 |
self.boundingBox = boundingBox |
|
26 | ||
27 |
self.angle = 0 # angle is degree |
|
28 | ||
29 |
self.ui = UI_OcrResultDialog.Ui_Dialog() |
|
30 |
self.ui.setupUi(self) |
|
31 |
|
|
32 |
self.imgW = qimage.width() |
|
33 |
self.imgH = qimage.height() |
|
34 |
self.image = self.image.scaled(self.imgW, self.imgH) |
|
35 |
self.graphicsView = QtImageViewer.QtImageViewer(App.mainWnd()) |
|
36 |
self.graphicsView.useDefaultCommand() ##### USE DEFAULT COMMAND |
|
37 |
self.graphicsView.setImage(self.image) |
|
38 |
self.ui.tVerticalLayout_2.addWidget(self.graphicsView) |
|
39 |
|
|
40 |
self.ui.counterClockPushButton_2.clicked.connect(lambda : self.rotateImage(True)) |
|
41 |
self.ui.clockPushButton_2.clicked.connect(lambda : self.rotateImage(False)) |
|
42 |
self.ui.redetectPushButton_2.clicked.connect(self.detectText) |
|
43 | ||
44 |
if self.isModify == False: |
|
45 |
self.detectText() |
|
46 |
else: |
|
47 |
self.ui.detectResultTextEdit_2.setPlainText(text) |
|
48 | ||
49 |
self.isAccepted = False |
|
50 |
|
|
51 |
def rotateImage(self, isCounterClock): |
|
52 |
for item in self.graphicsView.scene.items(): |
|
53 |
self.graphicsView.scene.removeItem(item) |
|
54 |
self.graphicsView.clearImage() |
|
55 |
transform = QTransform() |
|
56 |
if isCounterClock: |
|
57 |
'''CounterClock''' |
|
58 |
self.angle = (self.angle - 90) % 360 |
|
59 |
transform.rotate(-90) |
|
60 |
else: |
|
61 |
'''Clock''' |
|
62 |
self.angle = (self.angle - 270) % 360 |
|
63 |
transform.rotate(90) |
|
64 |
print(str(360 - self.angle)) |
|
65 |
self.image = self.image.transformed(transform) |
|
66 |
self.graphicsView.setImage(self.image) |
|
67 | ||
68 |
''' |
|
69 |
@history 2018.04.26 Jeongwoo Add Rectangle with modified Coords |
|
70 |
2018.06.20 Jeongwoo Remove test code |
|
71 |
''' |
|
72 |
def detectText(self): |
|
73 |
try: |
|
74 |
buffer = QBuffer() |
|
75 |
buffer.open(QBuffer.ReadWrite) |
|
76 |
self.image.save(buffer, "PNG") |
|
77 |
pyImage = Image.open(io.BytesIO(buffer.data())) |
|
78 |
img = np.array(pyImage) |
|
79 | ||
80 |
## exclude area bigger than one characeter size |
|
81 |
#minx = None |
|
82 |
#miny = None |
|
83 |
#maxx = None |
|
84 |
#maxy = None |
|
85 | ||
86 |
#img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1] |
|
87 |
#img = cv2.erode(img, np.ones((2,2), np.uint8)) |
|
88 |
#width, height = img.shape[::-1] |
|
89 |
#imgContour = np.ones(img.shape, np.uint8)*255 |
|
90 | ||
91 |
##cv2.rectangle(img, (0,0), (width - 1, height - 1), 255, 1) |
|
92 |
#imgNot = np.ones(img.shape, np.uint8) |
|
93 |
#cv2.bitwise_not(img, imgNot) |
|
94 |
#_, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
|
95 |
#holes = [contours[i] for i in range(len(contours)) if hierarchy[0][i][3] >= 0] |
|
96 |
#for contour in contours: |
|
97 |
# [x, y, w, h] = cv2.boundingRect(contour) |
|
98 | ||
99 |
# # remove too big one |
|
100 |
# if (w > 60 or h > 60): continue |
|
101 |
# ratio = w/h |
|
102 |
# if ratio > 4: continue |
|
103 |
|
|
104 |
# area = cv2.contourArea(contour, True) |
|
105 |
# if area > 0: |
|
106 |
# cv2.drawContours(imgContour, [contour], -1, (255,255,255), -1) |
|
107 |
# else: |
|
108 |
# cv2.drawContours(imgContour, [contour], -1, (0,0,0), -1) |
|
109 |
|
|
110 |
# if minx is None or x < minx: minx = x |
|
111 |
# if miny is None or y < miny: miny = y |
|
112 |
# if maxx is None or (x + w) > maxx: maxx = (x + w) |
|
113 |
# if maxy is None or (y + h) > maxy: maxy = (y + h) |
|
114 |
|
|
115 |
#cv2.imshow('img', imgContour) |
|
116 |
#cv2.waitKey(0) |
|
117 |
#cv2.destroyAllWindows() |
|
118 | ||
119 |
# up to here |
|
120 |
self.textInfoList = TOCR.getTextInfo(img, (round(self.boundingBox.x()), round(self.boundingBox.y()))) |
|
121 | ||
122 |
#self.textInfoList = TOCR.getTextInfo(img, (int(self.boundingBox.x()), int(self.boundingBox.y()))) |
|
123 |
if self.textInfoList is not None and len(self.textInfoList) > 0: |
|
124 |
self.ui.detectResultTextEdit_2.setText(self.getPlainText(self.textInfoList)) |
|
125 |
for textInfo in self.textInfoList: |
|
126 |
self.graphicsView.scene.addRect(textInfo.getX()-int(self.boundingBox.x()), textInfo.getY()-int(self.boundingBox.y()), textInfo.getW(), textInfo.getH(), QPen(Qt.red, 1, Qt.SolidLine)) |
|
127 |
else: |
|
128 |
self.ui.detectResultTextEdit_2.setText("Not Found") |
|
129 |
except Exception as ex: |
|
130 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
131 | ||
132 |
def getPlainText(self, textInfoList): |
|
133 |
text = '' |
|
134 |
for index in range(len(textInfoList)): |
|
135 |
textInfo = textInfoList[index] |
|
136 |
if index != 0: |
|
137 |
text = text + '\n' |
|
138 |
text = text + textInfo.getText() |
|
139 |
return text |
|
140 | ||
141 |
''' |
|
142 |
@brief OK Button Clicked. Remake TextInfo object |
|
143 |
@author Jeongwoo |
|
144 |
@date 18.04.19 |
|
145 |
@history 18.04.20 Jeongwoo Calculate Start Point Coordinates by rotated angle |
|
146 |
18.04.26 Jeongwoo Scene.itemAt(textX - boundBox.x(), textY - boundBox.y()) |
|
147 |
''' |
|
148 |
def accept(self): |
|
149 |
self.isAccepted = True |
|
150 |
text = self.ui.detectResultTextEdit_2.toPlainText() |
|
151 |
splitText = text.split('\n') |
|
152 |
if self.textInfoList is not None and len(self.textInfoList) > 0: |
|
153 |
for index in range(len(splitText)): |
|
154 |
textInfo = self.textInfoList[index] |
|
155 |
item = self.graphicsView.scene.itemAt(QPointF(float(textInfo.getX() - int(self.boundingBox.x())), float(textInfo.getY()-int(self.boundingBox.y()))), QTransform()) |
|
156 |
if item is not None: |
|
157 |
## Transform rectangle for calculate start point |
|
158 |
imgTransform = QTransform() |
|
159 |
if self.angle == 90 or self.angle == 270: |
|
160 |
imgTransform.translate(self.image.height()*0.5, self.image.width()*0.5) |
|
161 |
elif self.angle == 0 or self.angle == 360: |
|
162 |
imgTransform.translate(self.image.width()*0.5, self.image.height()*0.5) |
|
163 |
imgTransform.rotate(-abs(self.angle)) |
|
164 |
imgTransform.translate(-self.image.width()*0.5, -self.image.height()*0.5) |
|
165 |
rect = QRect(textInfo.getX() - int(self.boundingBox.x()), textInfo.getY() - int(self.boundingBox.y()), textInfo.getW(), textInfo.getH()) |
|
166 |
rect = imgTransform.mapRect(rect) |
|
167 |
## up to here |
|
168 |
textInfo.setX(rect.x() + int(self.boundingBox.x())) |
|
169 |
textInfo.setY(rect.y() + int(self.boundingBox.y())) |
|
170 |
textInfo.setText(splitText[index]) |
|
171 |
radian = round(math.radians(abs(self.angle)), 2) |
|
172 |
textInfo.setAngle(radian) # 360 degree == 6.28319 radian |
|
173 |
if radian == 1.57 or radian == 4.71: |
|
174 |
width = textInfo.getW() |
|
175 |
height = textInfo.getH() |
|
176 |
textInfo.setW(height) ## SWAP |
|
177 |
textInfo.setH(width) ## SWAP |
|
178 |
QDialog.accept(self) |
|
179 |
else: |
|
180 |
QMessageBox.about(self.ui.ocrDialogButtonBox, "알림", "텍스트 검출을 하신 후 다시 시도해주세요.") |
|
181 | ||
182 |
def reject(self): |
|
183 |
self.isAccepted = False |
|
184 |
self.textInfoList = None |
|
185 |
QDialog.reject(self) |
|
186 | ||
187 |
''' |
|
188 |
@brief Display this QDialog |
|
189 |
''' |
|
190 |
def showDialog(self): |
|
191 |
self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) |
|
192 |
#self.show() |
|
193 |
self.exec_() |
|
194 |
return (self.isAccepted, self.textInfoList) |
DTI_PID/DTI_PID/QOcrResultDialog.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 | ||
3 |
from PyQt5.QtCore import * |
|
4 |
from PyQt5.QtGui import * |
|
5 |
from PyQt5.QtWidgets import * |
|
6 |
import UI_OcrResultDialog |
|
7 |
import QtImageViewer |
|
8 |
import tesseract_ocr_module as TOCR |
|
9 |
from PIL import Image |
|
10 |
import io |
|
11 |
import numpy as np |
|
12 |
import cv2 |
|
13 |
import math |
|
14 | ||
15 |
class QOcrResultDialog(QDialog): |
|
16 |
def __init__(self, parent, qimage, boundingBox, isModify = False, text = None): |
|
17 |
from MainWindow import MainWindow |
|
18 | ||
19 |
QDialog.__init__(self, parent) |
|
20 |
self.textInfoList = None |
|
21 | ||
22 |
self.isModify = isModify |
|
23 |
self.image = qimage |
|
24 |
self.originImageWidth = qimage.width() |
|
25 |
self.originImageHeight = qimage.height() |
|
26 |
self.boundingBox = boundingBox |
|
27 | ||
28 |
self.angle = 0 # angle is degree |
|
29 | ||
30 |
self.ui = UI_OcrResultDialog.Ui_Dialog() |
|
31 |
self.ui.setupUi(self) |
|
32 |
|
|
33 |
self.imgW = qimage.width() |
|
34 |
self.imgH = qimage.height() |
|
35 |
self.image = self.image.scaled(self.imgW, self.imgH) |
|
36 |
self.graphicsView = QtImageViewer.QtImageViewer(MainWindow.instance()) |
|
37 |
self.graphicsView.useDefaultCommand() ##### USE DEFAULT COMMAND |
|
38 |
self.graphicsView.setImage(self.image) |
|
39 |
self.ui.tVerticalLayout_2.addWidget(self.graphicsView) |
|
40 |
|
|
41 |
self.ui.counterClockPushButton_2.clicked.connect(lambda : self.rotateImage(True)) |
|
42 |
self.ui.clockPushButton_2.clicked.connect(lambda : self.rotateImage(False)) |
|
43 |
self.ui.redetectPushButton_2.clicked.connect(self.detectText) |
|
44 | ||
45 |
if self.isModify == False: |
|
46 |
self.detectText() |
|
47 |
else: |
|
48 |
self.ui.detectResultTextEdit_2.setPlainText(text) |
|
49 | ||
50 |
self.isAccepted = False |
|
51 |
|
|
52 |
def rotateImage(self, isCounterClock): |
|
53 |
for item in self.graphicsView.scene.items(): |
|
54 |
self.graphicsView.scene.removeItem(item) |
|
55 |
self.graphicsView.clearImage() |
|
56 |
transform = QTransform() |
|
57 |
if isCounterClock: |
|
58 |
'''CounterClock''' |
|
59 |
self.angle = (self.angle - 90) % 360 |
|
60 |
transform.rotate(-90) |
|
61 |
else: |
|
62 |
'''Clock''' |
|
63 |
self.angle = (self.angle - 270) % 360 |
|
64 |
transform.rotate(90) |
|
65 |
print(str(360 - self.angle)) |
|
66 |
self.image = self.image.transformed(transform) |
|
67 |
self.graphicsView.setImage(self.image) |
|
68 | ||
69 |
''' |
|
70 |
@history 2018.04.26 Jeongwoo Add Rectangle with modified Coords |
|
71 |
2018.06.20 Jeongwoo Remove test code |
|
72 |
''' |
|
73 |
def detectText(self): |
|
74 |
try: |
|
75 |
buffer = QBuffer() |
|
76 |
buffer.open(QBuffer.ReadWrite) |
|
77 |
self.image.save(buffer, "PNG") |
|
78 |
pyImage = Image.open(io.BytesIO(buffer.data())) |
|
79 |
img = np.array(pyImage) |
|
80 | ||
81 |
## exclude area bigger than one characeter size |
|
82 |
#minx = None |
|
83 |
#miny = None |
|
84 |
#maxx = None |
|
85 |
#maxy = None |
|
86 | ||
87 |
#img = cv2.threshold(cv2.cvtColor(img, cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1] |
|
88 |
#img = cv2.erode(img, np.ones((2,2), np.uint8)) |
|
89 |
#width, height = img.shape[::-1] |
|
90 |
#imgContour = np.ones(img.shape, np.uint8)*255 |
|
91 | ||
92 |
##cv2.rectangle(img, (0,0), (width - 1, height - 1), 255, 1) |
|
93 |
#imgNot = np.ones(img.shape, np.uint8) |
|
94 |
#cv2.bitwise_not(img, imgNot) |
|
95 |
#_, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
|
96 |
#holes = [contours[i] for i in range(len(contours)) if hierarchy[0][i][3] >= 0] |
|
97 |
#for contour in contours: |
|
98 |
# [x, y, w, h] = cv2.boundingRect(contour) |
|
99 | ||
100 |
# # remove too big one |
|
101 |
# if (w > 60 or h > 60): continue |
|
102 |
# ratio = w/h |
|
103 |
# if ratio > 4: continue |
|
104 |
|
|
105 |
# area = cv2.contourArea(contour, True) |
|
106 |
# if area > 0: |
|
107 |
# cv2.drawContours(imgContour, [contour], -1, (255,255,255), -1) |
|
108 |
# else: |
|
109 |
# cv2.drawContours(imgContour, [contour], -1, (0,0,0), -1) |
|
110 |
|
|
111 |
# if minx is None or x < minx: minx = x |
|
112 |
# if miny is None or y < miny: miny = y |
|
113 |
# if maxx is None or (x + w) > maxx: maxx = (x + w) |
|
114 |
# if maxy is None or (y + h) > maxy: maxy = (y + h) |
|
115 |
|
|
116 |
#cv2.imshow('img', imgContour) |
|
117 |
#cv2.waitKey(0) |
|
118 |
#cv2.destroyAllWindows() |
|
119 | ||
120 |
# up to here |
|
121 |
self.textInfoList = TOCR.getTextInfo(img, (round(self.boundingBox.x()), round(self.boundingBox.y()))) |
|
122 | ||
123 |
#self.textInfoList = TOCR.getTextInfo(img, (int(self.boundingBox.x()), int(self.boundingBox.y()))) |
|
124 |
if self.textInfoList is not None and len(self.textInfoList) > 0: |
|
125 |
self.ui.detectResultTextEdit_2.setText(self.getPlainText(self.textInfoList)) |
|
126 |
for textInfo in self.textInfoList: |
|
127 |
self.graphicsView.scene.addRect(textInfo.getX()-int(self.boundingBox.x()), textInfo.getY()-int(self.boundingBox.y()), textInfo.getW(), textInfo.getH(), QPen(Qt.red, 1, Qt.SolidLine)) |
|
128 |
else: |
|
129 |
self.ui.detectResultTextEdit_2.setText("Not Found") |
|
130 |
except Exception as ex: |
|
131 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
|
132 | ||
133 |
def getPlainText(self, textInfoList): |
|
134 |
text = '' |
|
135 |
for index in range(len(textInfoList)): |
|
136 |
textInfo = textInfoList[index] |
|
137 |
if index != 0: |
|
138 |
text = text + '\n' |
|
139 |
text = text + textInfo.getText() |
|
140 |
return text |
|
141 | ||
142 |
''' |
|
143 |
@brief OK Button Clicked. Remake TextInfo object |
|
144 |
@author Jeongwoo |
|
145 |
@date 18.04.19 |
|
146 |
@history 18.04.20 Jeongwoo Calculate Start Point Coordinates by rotated angle |
|
147 |
18.04.26 Jeongwoo Scene.itemAt(textX - boundBox.x(), textY - boundBox.y()) |
|
148 |
''' |
|
149 |
def accept(self): |
|
150 |
self.isAccepted = True |
|
151 |
text = self.ui.detectResultTextEdit_2.toPlainText() |
|
152 |
splitText = text.split('\n') |
|
153 |
if self.textInfoList is not None and len(self.textInfoList) > 0: |
|
154 |
for index in range(len(splitText)): |
|
155 |
textInfo = self.textInfoList[index] |
|
156 |
item = self.graphicsView.scene.itemAt(QPointF(float(textInfo.getX() - int(self.boundingBox.x())), float(textInfo.getY()-int(self.boundingBox.y()))), QTransform()) |
|
157 |
if item is not None: |
|
158 |
## Transform rectangle for calculate start point |
|
159 |
imgTransform = QTransform() |
|
160 |
if self.angle == 90 or self.angle == 270: |
|
161 |
imgTransform.translate(self.image.height()*0.5, self.image.width()*0.5) |
|
162 |
elif self.angle == 0 or self.angle == 360: |
|
163 |
imgTransform.translate(self.image.width()*0.5, self.image.height()*0.5) |
|
164 |
imgTransform.rotate(-abs(self.angle)) |
|
165 |
imgTransform.translate(-self.image.width()*0.5, -self.image.height()*0.5) |
|
166 |
rect = QRect(textInfo.getX() - int(self.boundingBox.x()), textInfo.getY() - int(self.boundingBox.y()), textInfo.getW(), textInfo.getH()) |
|
167 |
rect = imgTransform.mapRect(rect) |
|
168 |
## up to here |
|
169 |
textInfo.setX(rect.x() + int(self.boundingBox.x())) |
|
170 |
textInfo.setY(rect.y() + int(self.boundingBox.y())) |
|
171 |
textInfo.setText(splitText[index]) |
|
172 |
radian = round(math.radians(abs(self.angle)), 2) |
|
173 |
textInfo.setAngle(radian) # 360 degree == 6.28319 radian |
|
174 |
if radian == 1.57 or radian == 4.71: |
|
175 |
width = textInfo.getW() |
|
176 |
height = textInfo.getH() |
|
177 |
textInfo.setW(height) ## SWAP |
|
178 |
textInfo.setH(width) ## SWAP |
|
179 |
QDialog.accept(self) |
|
180 |
else: |
|
181 |
QMessageBox.about(self.ui.ocrDialogButtonBox, "알림", "텍스트 검출을 하신 후 다시 시도해주세요.") |
|
182 | ||
183 |
def reject(self): |
|
184 |
self.isAccepted = False |
|
185 |
self.textInfoList = None |
|
186 |
QDialog.reject(self) |
|
187 | ||
188 |
''' |
|
189 |
@brief Display this QDialog |
|
190 |
''' |
|
191 |
def showDialog(self): |
|
192 |
self.setWindowFlags(self.windowFlags() & ~Qt.WindowContextHelpButtonHint) |
|
193 |
#self.show() |
|
194 |
self.exec_() |
|
195 |
return (self.isAccepted, self.textInfoList) |
DTI_PID/DTI_PID/READ ME.txt | ||
---|---|---|
102 | 102 |
- �ɺ��� ������� Ŭ�� �� �ϴ� QPropertyTableWidget �� �ɺ� ���� ��� |
103 | 103 |
- �ɺ� �巡��, ��� �� QtImageViewer �� �ɺ� ���� |
104 | 104 | |
105 |
12) QOcrResultDialog.py
|
|
105 |
12) OcrResultDialog.py |
|
106 | 106 |
- MainWindow ���� �� �� OCR �Ǵ� ����ǿ� QtImageViewer �� ǥ�õ� �ؽ�Ʈ�� ����Ŭ���� ��� ǥ�õǴ� ���̾�α� |
107 | 107 |
- ��� ���� �̹��� �� ����� �ؽ�Ʈ�� ȸ�� �ɼ� ���� |
108 | 108 |
- 90�� ���� ȸ���� �����ϸ�, ������ �ؽ�Ʈ�� ���������� ȸ���Ͽ� ��ġ�� �� Re-Detect ��ư�� Ŭ���� �� �ؽ�Ʈ ���� |
DTI_PID/DTI_PID/Shapes/EngineeringUnknownItem.py | ||
---|---|---|
78 | 78 |
registerSymbolAction = QAction("심볼 등록") |
79 | 79 |
registerSymbolAction.triggered.connect(lambda: self.onRegisterSymbolEvent()) |
80 | 80 |
menu.addAction(registerSymbolAction) |
81 |
recognizeTextAction = QAction("텍스트 인식") |
|
82 |
recognizeTextAction.triggered.connect(lambda: self.onRecognizeTextEvent()) |
|
83 |
menu.addAction(recognizeTextAction) |
|
81 | 84 | |
82 | 85 |
menu.exec_(event.screenPos()) |
83 | 86 | |
... | ... | |
108 | 111 |
for item in selected: |
109 | 112 |
rect = rect.united(item.sceneBoundingRect()) |
110 | 113 | |
111 |
image = App.mainWnd().onAreaSelected(round(rect.left()), round(rect.top()), round(rect.width()), round(rect.height()))
|
|
114 |
App.mainWnd().onAreaSelected(round(rect.left()), round(rect.top()), round(rect.width()), round(rect.height())) |
|
112 | 115 |
except Exception as ex: |
113 |
from App import App |
|
116 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
|
117 |
App.mainWnd().addMessage(MessageType.Error, message) |
|
118 | ||
119 |
''' |
|
120 |
@brief show text recognition dialog |
|
121 |
@author humkyung |
|
122 |
@date 2018.08.08 |
|
123 |
''' |
|
124 |
def onRecognizeTextEvent(self): |
|
125 |
from App import App |
|
114 | 126 | |
127 |
try: |
|
128 |
selected = [item for item in self.scene().items() if item.isSelected() and type(item) is QEngineeringUnknownItem] |
|
129 |
rect = QRectF() |
|
130 |
for item in selected: |
|
131 |
rect = rect.united(item.sceneBoundingRect()) |
|
132 | ||
133 |
App.mainWnd().onRecognizeText(round(rect.left()), round(rect.top()), round(rect.width()), round(rect.height())) |
|
134 |
except Exception as ex: |
|
115 | 135 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
116 | 136 |
App.mainWnd().addMessage(MessageType.Error, message) |
117 | 137 |
DTI_PID/DTI_PID/Shapes/QEngineeringLineNoTextItem.py | ||
---|---|---|
15 | 15 | |
16 | 16 |
from EngineeringPolylineItem import QEngineeringPolylineItem |
17 | 17 |
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
18 |
import QOcrResultDialog |
|
18 |
from OcrResultDialog import QOcrResultDialog
|
|
19 | 19 |
from AppDocData import AppDocData |
20 | 20 |
from QEngineeringTextItem import QEngineeringTextItem |
21 | 21 |
DTI_PID/DTI_PID/Shapes/QEngineeringNoteItem.py | ||
---|---|---|
14 | 14 | |
15 | 15 |
from EngineeringPolylineItem import QEngineeringPolylineItem |
16 | 16 |
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
17 |
import QOcrResultDialog
|
|
17 |
import OcrResultDialog |
|
18 | 18 |
from AppDocData import AppDocData |
19 | 19 |
from QEngineeringTextItem import QEngineeringTextItem |
20 | 20 |
import re |
DTI_PID/DTI_PID/Shapes/QEngineeringSizeTextItem.py | ||
---|---|---|
15 | 15 | |
16 | 16 |
from EngineeringPolylineItem import QEngineeringPolylineItem |
17 | 17 |
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
18 |
import QOcrResultDialog
|
|
18 |
import OcrResultDialog |
|
19 | 19 |
from AppDocData import AppDocData |
20 | 20 |
from QEngineeringTextItem import QEngineeringTextItem |
21 | 21 |
DTI_PID/DTI_PID/Shapes/QEngineeringTagNoTextItem.py | ||
---|---|---|
15 | 15 | |
16 | 16 |
from EngineeringPolylineItem import QEngineeringPolylineItem |
17 | 17 |
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
18 |
import QOcrResultDialog
|
|
18 |
import OcrResultDialog |
|
19 | 19 |
from AppDocData import AppDocData |
20 | 20 |
from QEngineeringTextItem import QEngineeringTextItem |
21 | 21 |
DTI_PID/DTI_PID/Shapes/QEngineeringTextItem.py | ||
---|---|---|
15 | 15 | |
16 | 16 |
from EngineeringPolylineItem import QEngineeringPolylineItem |
17 | 17 |
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
18 |
import QOcrResultDialog |
|
18 |
from OcrResultDialog import QOcrResultDialog
|
|
19 | 19 |
from AppDocData import AppDocData |
20 | 20 |
from QEngineeringAbstractItem import QEngineeringAbstractItem |
21 | 21 | |
... | ... | |
156 | 156 |
''' |
157 | 157 |
def mouseDoubleClickEvent(self, event): |
158 | 158 |
if event.buttons() == Qt.LeftButton: |
159 |
dialog = QOcrResultDialog.QOcrResultDialog(None, AppDocData.instance().getCurrentPidSource().getQImageOnRect(QRect(self.loc[0], self.loc[1], self.size[0]+1, self.size[1]))
|
|
159 |
dialog = QOcrResultDialog(None, AppDocData.instance().getCurrentPidSource().getQImageOnRect(QRect(self.loc[0], self.loc[1], self.size[0]+1, self.size[1])) |
|
160 | 160 |
, QRect(self.loc[0], self.loc[1], self.size[0]+1, self.size[1]), True, self.text()) |
161 | 161 |
(isAccept, textInfoList) = dialog.showDialog() |
162 | 162 |
DTI_PID/DTI_PID/Shapes/QEngineeringTrimLineNoTextItem.py | ||
---|---|---|
15 | 15 | |
16 | 16 |
from EngineeringPolylineItem import QEngineeringPolylineItem |
17 | 17 |
from QGraphicsBoundingBoxItem import QGraphicsBoundingBoxItem |
18 |
import QOcrResultDialog
|
|
18 |
import OcrResultDialog |
|
19 | 19 |
from AppDocData import AppDocData |
20 | 20 |
from QEngineeringLineNoTextItem import QEngineeringLineNoTextItem |
21 | 21 |
내보내기 Unified diff