개정판 12ee48dc
fixed issue #477:
- fit image 기능 오류 수정
DTI_PID/DTI_PID/AppDocData.py | ||
---|---|---|
224 | 224 |
import cv2 |
225 | 225 |
|
226 | 226 |
if self._imgSrc is None and self._imgFilePath is not None and os.path.isfile(self._imgFilePath): |
227 |
self._imgSrc = cv2.cvtColor(cv2.imread(self._imgFilePath, 1), cv2.COLOR_BGR2GRAY)
|
|
227 |
self._imgSrc = cv2.threshold(cv2.cvtColor(cv2.imread(self._imgFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1]
|
|
228 | 228 |
|
229 | 229 |
return self._imgSrc |
230 | 230 |
|
DTI_PID/DTI_PID/Commands/FitImageCommand.py | ||
---|---|---|
1 |
# coding: utf-8 |
|
2 |
|
|
1 | 3 |
import os.path |
2 |
import AbstractCommand |
|
4 |
import sys |
|
5 |
|
|
3 | 6 |
try: |
4 | 7 |
from PyQt5.QtCore import Qt, QRectF, pyqtSignal, QT_VERSION_STR, QRect |
5 | 8 |
from PyQt5.QtGui import QImage, QPixmap, QPainterPath, QCursor, QColor |
... | ... | |
10 | 13 |
from PyQt4.QtGui import QGraphicsView, QGraphicsScene, QImage, QPixmap, QPainterPath, QFileDialog, QCursor, QColor |
11 | 14 |
except ImportError: |
12 | 15 |
raise ImportError("ImageViewerQt: Requires PyQt5 or PyQt4.") |
13 |
import sys |
|
16 |
import numpy as np |
|
17 |
|
|
18 |
import AbstractCommand |
|
14 | 19 |
|
15 | 20 |
class FitImageCommand(AbstractCommand.AbstractCommand): |
16 | 21 |
WHITE_PIXEL = (255, 255, 255, 255) |
... | ... | |
36 | 41 |
def getOffset(self): |
37 | 42 |
return (self.offsetX, self.offsetY) |
38 | 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 |
''' |
|
39 | 65 |
def getImageBoundingBox(self): |
40 |
image = self.imageViewer.image() |
|
66 |
import cv2 |
|
67 |
black = 0 |
|
68 |
|
|
69 |
image = self.convertQImageToMat(self.imageViewer.image()) |
|
70 |
image = cv2.threshold(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1] |
|
71 |
width, height = image.shape[::-1] |
|
72 |
|
|
41 | 73 |
minX = sys.maxsize |
42 | 74 |
minY = sys.maxsize |
43 | 75 |
maxX = -1 |
44 | 76 |
maxY = -1 |
45 |
for xi in range(image.width()): |
|
46 |
for yi in range(image.height()):
|
|
47 |
pixel = image.pixel(xi, yi)
|
|
48 |
if QColor(pixel).getRgb() == self.BLACK_PIXEL:
|
|
49 |
#if QColor(pixel).getRgb() != self.WHITE_PIXEL:
|
|
77 |
|
|
78 |
for xi in range(width):
|
|
79 |
for yi in range(height):
|
|
80 |
color = image[yi, xi]
|
|
81 |
if color == black:
|
|
50 | 82 |
if xi < minX: |
51 | 83 |
minX = xi |
52 | 84 |
if xi > maxX: |
53 | 85 |
maxX = xi |
86 |
|
|
54 | 87 |
if yi < minY: |
55 | 88 |
minY = yi |
56 | 89 |
if yi > maxY: |
57 | 90 |
maxY = yi |
91 |
else: |
|
92 |
pass |
|
93 |
|
|
58 | 94 |
return QRect(minX, minY, (maxX - minX) + 1, (maxY - minY) + 1) |
59 | 95 |
|
60 | 96 |
''' |
DTI_PID/DTI_PID/ConfigurationAreaDialog.py | ||
---|---|---|
365 | 365 |
area.parse(self.ui.tableWidgetEquipmentDescArea.item(row, 1).text()) |
366 | 366 |
configs.append(Config(section, str(row), area.toString())) |
367 | 367 |
|
368 |
self.removeEquipmentDescArea(area) |
|
368 |
self.removeEquipmentDescArea(area.toString())
|
|
369 | 369 |
# up to here |
370 | 370 |
docData.saveConfigs(configs) |
371 | 371 |
|
DTI_PID/DTI_PID/DTI_PID.py | ||
---|---|---|
818 | 818 |
humkyung 2018.06.11 add drawing path to parameter and write recognized lines to image |
819 | 819 |
humkyung 2018.07.04 call arrangeLinePosition after creating line |
820 | 820 |
''' |
821 |
def recognizeLine(path, listWidget, graphicsView): |
|
821 |
def recognizeLine(path, listWidget, graphicsView, worker):
|
|
822 | 822 |
from shapely.geometry import Point, LineString |
823 | 823 |
from SymbolSvgItem import SymbolSvgItem |
824 | 824 |
from QEngineeringFlowArrowItem import QEngineeringFlowArrowItem |
... | ... | |
901 | 901 |
# up to here |
902 | 902 |
except Exception as ex: |
903 | 903 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
904 |
MainWindow.instance().displayMessage.emit(MessageType.Error, message)
|
|
904 |
worker.displayLog.emit(MessageType.Error, message)
|
|
905 | 905 |
finally: |
906 | 906 |
listWidget.addItem('Finished line recognization') |
907 | 907 |
|
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
907 | 907 |
thickness = int(windowSize[1]) |
908 | 908 |
|
909 | 909 |
diffFilePath = os.path.join(project.getTempPath(), "DIFF_" + os.path.basename(self.path)) |
910 |
imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1] |
|
911 |
|
|
912 |
lines = [item for item in self.graphicsView.scene.items() if (type(item) is QEngineeringLineItem)] |
|
913 |
for line in lines: |
|
914 |
line.drawToImage(imgDiff, 255, thickness) |
|
915 |
cv2.imwrite(diffFilePath, imgDiff) |
|
916 |
|
|
917 |
imgNot = np.ones(imgDiff.shape, np.uint8) |
|
918 |
cv2.bitwise_not(imgDiff, imgNot) |
|
919 |
imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8)) |
|
920 |
|
|
921 |
image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
|
922 |
for contour in contours: |
|
923 |
[x, y, w, h] = cv2.boundingRect(contour) |
|
924 |
|
|
925 |
# remove too small one |
|
926 |
if (w < 10 or h < 10): continue |
|
927 |
|
|
928 |
# create unknown item |
|
929 |
epsilon = cv2.arcLength(contour, True)*0.001 |
|
930 |
approx = cv2.approxPolyDP(contour, epsilon, True) |
|
931 |
approx = [pt[0] for pt in approx] |
|
932 |
item = QEngineeringUnknownItem(approx) |
|
933 |
item.transfer.onRemoved.connect(self.itemRemoved) |
|
934 |
self.addUnknownItemToScene(item) |
|
935 |
# up to here |
|
910 |
if os.path.isfile(diffFilePath): |
|
911 |
imgDiff = cv2.threshold(cv2.cvtColor(cv2.imread(diffFilePath, 1), cv2.COLOR_BGR2GRAY), 127, 255, cv2.THRESH_BINARY)[1] |
|
912 |
|
|
913 |
lines = [item for item in self.graphicsView.scene.items() if (type(item) is QEngineeringLineItem)] |
|
914 |
for line in lines: |
|
915 |
line.drawToImage(imgDiff, 255, thickness) |
|
916 |
cv2.imwrite(diffFilePath, imgDiff) |
|
917 |
|
|
918 |
imgNot = np.ones(imgDiff.shape, np.uint8) |
|
919 |
cv2.bitwise_not(imgDiff, imgNot) |
|
920 |
imgNot = cv2.dilate(imgNot, np.ones((8,8), np.uint8)) |
|
921 |
|
|
922 |
image, contours, hierarchy = cv2.findContours(imgNot, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) |
|
923 |
for contour in contours: |
|
924 |
[x, y, w, h] = cv2.boundingRect(contour) |
|
925 |
|
|
926 |
# remove too small one |
|
927 |
if (w < 10 or h < 10): continue |
|
928 |
|
|
929 |
# create unknown item |
|
930 |
epsilon = cv2.arcLength(contour, True)*0.001 |
|
931 |
approx = cv2.approxPolyDP(contour, epsilon, True) |
|
932 |
approx = [pt[0] for pt in approx] |
|
933 |
item = QEngineeringUnknownItem(approx) |
|
934 |
item.transfer.onRemoved.connect(self.itemRemoved) |
|
935 |
self.addUnknownItemToScene(item) |
|
936 |
# up to here |
|
936 | 937 |
|
937 |
notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(self.path)) |
|
938 |
cv2.imwrite(notFilePath, imgNot) |
|
938 |
notFilePath = os.path.join(project.getTempPath(), "NOT_" + os.path.basename(self.path)) |
|
939 |
cv2.imwrite(notFilePath, imgNot) |
|
940 |
else: |
|
941 |
message = 'can\'t found {}'.format(diffFilePath) |
|
942 |
self.addMessage(MessageType.Normal, message) |
|
939 | 943 |
except Exception as ex: |
940 | 944 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
941 | 945 |
self.addMessage(MessageType.Error, message) |
DTI_PID/DTI_PID/QRecognitionDialog.py | ||
---|---|---|
30 | 30 |
''' |
31 | 31 |
finished = pyqtSignal() |
32 | 32 |
intReady = pyqtSignal(int) |
33 |
recognizeLine = pyqtSignal(str, QListWidget, QtImageViewer) |
|
33 |
recognizeLine = pyqtSignal(str, QListWidget, QtImageViewer, QObject)
|
|
34 | 34 |
drawDetectedItems = pyqtSignal(list, list, list) |
35 | 35 |
displayMessage = pyqtSignal(QListWidgetItem) |
36 | 36 |
updateProgress = pyqtSignal(int) |
... | ... | |
48 | 48 |
try: |
49 | 49 |
executeRecognition(self.drawDetectedItems, self.path, self.listWidget, self.isSymbolTextChecked, self) |
50 | 50 |
if self.isLineChecked: |
51 |
self.recognizeLine.emit(self.path, self.listWidget, self.graphicsView) |
|
51 |
self.recognizeLine.emit(self.path, self.listWidget, self.graphicsView, self)
|
|
52 | 52 |
self.finished.emit() |
53 | 53 |
except Exception as ex: |
54 | 54 |
message = 'error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno) |
DTI_PID/DTI_PID/QSymbolEditorDialog.py | ||
---|---|---|
405 | 405 |
@brief Called When Close Button Clicked |
406 | 406 |
''' |
407 | 407 |
def reject(self): |
408 |
print("cancel") |
|
409 | 408 |
self.isAccepted = False |
410 | 409 |
QDialog.reject(self) |
411 | 410 |
|
... | ... | |
535 | 534 |
@brief Area Eraser Tool Button Clicked |
536 | 535 |
''' |
537 | 536 |
def areaEraserToolClickEvent(self, event): |
538 |
print("area eraser") |
|
539 | 537 |
self.ui.imageView.command = AreaEraserCommand.AreaEraserCommand(self.ui.imageView) |
540 | 538 |
|
541 | 539 |
''' |
542 |
@brief Fit Image Tool Button Clicked |
|
540 |
@brief Fit Image Tool Button Clicked
|
|
543 | 541 |
@history 2018.05.02 Jeongwoo Method name changed(getAdjust → getOffset) |
544 | 542 |
Emit offsets to startPointChanged |
545 | 543 |
2018.06.11 Jeongwoo init original/connection points |
546 | 544 |
''' |
547 | 545 |
def fitImageToolClickEvent(self, event): |
548 |
print("Fit Image") |
|
549 | 546 |
self.initOriginalAndConnectionPoint() |
550 | 547 |
self.ui.imageView.command = FitImageCommand.FitImageCommand(self.ui.imageView) |
551 | 548 |
adjustX, adjustY = self.ui.imageView.command.getOffset() |
... | ... | |
566 | 563 |
@brief Add AdditionalSymbol String on ListWidget Listener |
567 | 564 |
''' |
568 | 565 |
def addAdditionalSymbolEvent(self, event): |
569 |
print("addAdditionalSymbolEvent") |
|
570 | 566 |
additionalSymbolIndex = self.ui.additionalSymbolComboBox.currentIndex() |
571 | 567 |
if additionalSymbolIndex != 0: |
572 |
print("Symbol Selected") |
|
573 | 568 |
direction = self.ui.defaultSymbolDirectionComboBox.currentText() |
574 | 569 |
symbolName = self.ui.additionalSymbolComboBox.currentText() |
575 | 570 |
self.addAdditionalSymbol(direction, symbolName) |
내보내기 Unified diff