개정판 d8ddd93d
Add function to rotate point
DTI_PID/DTI_PID/App.py | ||
---|---|---|
47 | 47 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
48 | 48 |
|
49 | 49 |
class ExampleApp(QMainWindow, DTI_PID_UI.Ui_MainWindow, SingletonInstane): |
50 |
''' |
|
51 |
@brief initialize |
|
52 |
@author |
|
53 |
@date |
|
54 |
@history humkyung 2018.04.12 add splitter widget |
|
55 |
''' |
|
50 | 56 |
def __init__(self): |
51 | 57 |
super(self.__class__, self).__init__() |
52 | 58 |
self.setupUi(self) |
... | ... | |
75 | 81 |
self.propertyTableWidget = QPropertyTableWidget.QPropertyTableWidget() |
76 | 82 |
self.symbolTabVerticalLayout.addWidget(self.propertyTableWidget) |
77 | 83 |
self.dirTreeWidget.singleClicked.connect(self.propertyTableWidget.getClickedSymbol) |
84 |
# add splitter widget |
|
85 |
splitter = QSplitter(Qt.Vertical) |
|
86 |
splitter.addWidget(self.dirTreeWidget) |
|
87 |
splitter.addWidget(self.propertyTableWidget) |
|
88 |
self.symbolTabVerticalLayout.addWidget(splitter) |
|
89 |
# up to here |
|
78 | 90 |
|
79 | 91 |
# Add Custom Result Tree Widget (Symbol Explorer) |
80 | 92 |
self.resultTreeWidget = QResultTreeWidget.QResultTreeWidget(self.graphicsView) |
... | ... | |
84 | 96 |
# Add Empty Widget |
85 | 97 |
self.emptyWidget = QTableWidget() |
86 | 98 |
self.symbolExplorerVerticalLayout.addWidget(self.emptyWidget) |
99 |
# add splitter widget |
|
100 |
splitter = QSplitter(Qt.Vertical) |
|
101 |
splitter.addWidget(self.resultTreeWidget) |
|
102 |
splitter.addWidget(self.emptyWidget) |
|
103 |
self.symbolExplorerVerticalLayout.addWidget(splitter) |
|
104 |
# up to here |
|
87 | 105 |
|
88 | 106 |
self.loadStyleSheet(os.path.dirname(os.path.realpath(__file__)) + '\\coffee') |
89 | 107 |
|
... | ... | |
150 | 168 |
# DEBUG |
151 | 169 |
''' |
152 | 170 |
from LineDetector import LineDetector |
153 |
self.loadRecognitionResult('d:/Projects/DTIPID/DTI_PID/DTI_PID/SG_TEST/output/UY1-K-2007_P1_300dpi_black.xml')
|
|
171 |
self.loadRecognitionResult('D:/Projects/DTIPID/DTI_PID/DTI_PID/SG_TEST/output/UY1-K-2005G_P1_300dpi_black.xml')
|
|
154 | 172 |
|
155 | 173 |
# detect line |
156 | 174 |
connectedLines = [] |
... | ... | |
262 | 280 |
processLine.setPath(processLine._path) |
263 | 281 |
processLine.setPen(QPen(Qt.blue, 5, Qt.SolidLine)) |
264 | 282 |
self.graphicsView.scene.addItem(processLine) |
265 |
|
|
266 |
''' |
|
267 |
res = detector.detectConnectedLine(item, int(area.x), int(area.y)) |
|
268 |
for pts in res: |
|
269 |
processLine = QEngineeringLineItem() |
|
270 |
for pt in pts: |
|
271 |
processLine._pol.append(QPointF(pt[0] + int(area.x), pts[1] + int(area.y))) |
|
272 |
processLine._path.addPolygon(processLine._pol) |
|
273 |
processLine.setPath(processLine._path) |
|
274 |
self.graphicsView.scene.addItem(processLine) |
|
275 |
''' |
|
276 | 283 |
# up to here |
277 | 284 |
except Exception as ex: |
278 | 285 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
279 | 286 |
|
280 | 287 |
''' |
281 |
@brief load recognition result |
|
282 |
@author humkyung |
|
283 |
@date 2018.04.?? |
|
288 |
@brief load recognition result |
|
289 |
@author humkyung |
|
290 |
@date 2018.04.?? |
|
291 |
@history humkyung 2018.01.12 parse originalpoint and connectionpoint |
|
284 | 292 |
''' |
285 | 293 |
def loadRecognitionResult(self, xmlPath): |
286 | 294 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse |
... | ... | |
296 | 304 |
name = symbol.find('NAME').text |
297 | 305 |
angle = float(symbol.find('ANGLE').text) |
298 | 306 |
type = symbol.find('TYPE').text |
307 |
origin = [float(x) for x in symbol.find('ORIGINALPOINT').text.split(',')] |
|
308 |
connPts = [] |
|
309 |
if symbol.find('CONNECTIONPOINT').text is not None: |
|
310 |
connPts = [(float(x.split(',')[0]), float(x.split(',')[1])) for x in symbol.find('CONNECTIONPOINT').text.split('/')] |
|
299 | 311 |
|
312 |
if 'GATE VALVE WITH PLUG' != name: continue |
|
300 | 313 |
svgFilePath = project.getSvgFilePath() + '/' + type + '/' + name + '.svg' |
301 | 314 |
if os.path.isfile(svgFilePath): |
302 | 315 |
svg = SymbolSvgItem(svgFilePath) |
... | ... | |
305 | 318 |
svg.angle = angle |
306 | 319 |
svg.loc = pt |
307 | 320 |
svg.size = size |
321 |
svg.origin = origin |
|
322 |
svg.connPts = connPts |
|
308 | 323 |
|
309 | 324 |
#### lambda param=svg : bind 'svg' object to lambda('param') |
310 | 325 |
#### If case of 'lambda svg=svg:', function uses the 'svg' value bound to lambda |
DTI_PID/DTI_PID/DTI_PID.py | ||
---|---|---|
113 | 113 |
def cvtGrayImage(img): |
114 | 114 |
return cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) |
115 | 115 |
|
116 |
''' |
|
117 |
@brief rotate and translate by given angle |
|
118 |
@author jwkim |
|
119 |
@date 2018.??.?? |
|
120 |
''' |
|
116 | 121 |
def getCoordOnRotatedImage(rAngle, x, y, originImageWidth, originImageHeight): |
117 | 122 |
rx = None |
118 | 123 |
ry = None |
DTI_PID/DTI_PID/LineDetector.py | ||
---|---|---|
144 | 144 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
145 | 145 |
|
146 | 146 |
''' |
147 |
@brief rotate given point about origin by angle |
|
148 |
@author humkyung |
|
149 |
@date 2018.04.12 |
|
150 |
''' |
|
151 |
def rotatePoint(self, point, origin, angle): |
|
152 |
dx = point[0] - origin[0] |
|
153 |
dy = point[1] - origin[1] |
|
154 |
|
|
155 |
qx = origin[0] + math.cos(angle) * dx - math.sin(angle) * dy |
|
156 |
qy = origin[1] + math.sin(angle) * dx + math.cos(angle) * dy |
|
157 |
return [qx, qy] |
|
158 |
|
|
159 |
''' |
|
147 | 160 |
@brief check if given two lines are connected |
148 | 161 |
@author humkyung |
149 | 162 |
@date 2018.04.11 |
... | ... | |
260 | 273 |
length = math.sqrt(dx*dx + dy*dy) |
261 | 274 |
dx /= length |
262 | 275 |
dy /= length |
263 |
if dx < 0.05:
|
|
276 |
if dx < 0.1:
|
|
264 | 277 |
for pt in res: |
265 | 278 |
pt[0] = res[0][0] |
266 |
elif dy < 0.05:
|
|
279 |
elif dy < 0.1:
|
|
267 | 280 |
for pt in res: |
268 | 281 |
pt[1] = res[0][1] |
269 | 282 |
# up to here |
270 | 283 |
|
271 | 284 |
return res |
272 | 285 |
|
273 |
''' |
|
274 |
elif len(lines) > 2: |
|
275 |
bLoop = True |
|
276 |
while bLoop and (len(lines) > 1): |
|
277 |
bLoop = False |
|
278 |
for line in lines[:]: |
|
279 |
matches = [param for param in lines if (line != param) and self.isConnected(line, param)] |
|
280 |
if len(matches) > 0: |
|
281 |
matches.append(line) |
|
282 |
mergedLine = self.mergeLines(matches) |
|
283 |
lines.append(mergedLine) |
|
284 |
for match in matches: |
|
285 |
lines.remove(match) |
|
286 |
|
|
287 |
bLoop = True |
|
288 |
break |
|
289 |
return lines |
|
290 |
''' |
|
291 |
|
|
292 | 286 |
return None |
293 | 287 |
|
294 | 288 |
''' |
... | ... | |
296 | 290 |
@author humkyung |
297 | 291 |
@date 2018.04.?? |
298 | 292 |
@history humkyung 2018.04.11 merge lines which are collinear or connected |
293 |
@history humkyung 2018.04.12 rotate connection points by symbol angle |
|
299 | 294 |
''' |
300 | 295 |
def detectConnectedLine(self, symbol, offsetX, offsetY): |
301 | 296 |
res = [] |
302 | 297 |
|
303 | 298 |
try: |
304 | 299 |
pool = [] |
305 |
if (0 == symbol.angle) or (3.14 == symbol.angle): |
|
306 |
right = int(symbol.rect().right()) |
|
307 |
left = int(symbol.rect().left()) |
|
308 |
|
|
309 |
pt = [right - int(offsetX), int(symbol.center().y()) - int(offsetY)] |
|
310 |
pool.append([[1,0], pt]) |
|
311 |
pt = [left - int(offsetX), int(symbol.center().y()) - int(offsetY)] |
|
312 |
pool.append([[-1,0], pt]) |
|
313 |
elif (1.57 == symbol.angle) or (4.71 == symbol.angle): # rotated by 90 or 270 degree |
|
314 |
bottom = int(symbol.rect().bottom()) |
|
315 |
top = int(symbol.rect().top()) |
|
316 |
|
|
317 |
pt = [int(symbol.center().x()) - int(offsetX), bottom - int(offsetY)] |
|
318 |
pool.append([[0,1], pt]) |
|
319 |
pt = [int(symbol.center().x()) - int(offsetX), top - int(offsetY)] |
|
320 |
pool.append([[0,-1], pt]) |
|
300 |
if (0 == symbol.angle) or (1.57 == symbol.angle) or (3.14 == symbol.angle) or (4.71 == symbol.angle): |
|
301 |
for conn in symbol.connPts: |
|
302 |
pt = self.rotatePoint(conn, symbol.origin, symbol.angle) |
|
303 |
dx = pt[0] - symbol.origin[0] |
|
304 |
dy = pt[1] - symbol.origin[1] |
|
305 |
length = math.sqrt(dx*dx + dy*dy) |
|
306 |
dx /= length |
|
307 |
dy /= length |
|
308 |
|
|
309 |
if abs(dx) < 0.1: |
|
310 |
pool.append([[0,1 if dy > 0 else -1], [round(pt[0] - offsetX), round(pt[1] - offsetY)]]) |
|
311 |
elif abs(dy) < 0.1: |
|
312 |
pool.append([[1 if dx > 0 else -1,0], [round(pt[0] - offsetX), round(pt[1] - offsetY)]]) |
|
321 | 313 |
|
322 | 314 |
while len(pool) > 0: |
323 | 315 |
dir, pt = pool.pop() |
... | ... | |
332 | 324 |
pt[1] = line[1][1] |
333 | 325 |
pool.append([[1,0], pt]) |
334 | 326 |
pool.append([[-1,0], pt]) |
335 |
|
|
336 |
# merge lines which are collinear or connected |
|
337 |
''' |
|
338 |
bLoop = True |
|
339 |
while bLoop and (len(res) > 1): |
|
340 |
bLoop = False |
|
341 |
for line in res[:]: |
|
342 |
matches = [param for param in res if (line != param) and self.isConnected(line, param)] |
|
343 |
if len(matches) == 1: |
|
344 |
matches.append(line) |
|
345 |
mergedLine = self.mergeLines(matches) |
|
346 |
if mergedLine is not None: res.append(mergedLine) |
|
347 |
for match in matches: |
|
348 |
res.remove(match) |
|
349 |
|
|
350 |
bLoop = True |
|
351 |
break |
|
352 |
''' |
|
353 |
# up to here |
|
354 |
|
|
355 | 327 |
return res |
356 | 328 |
except Exception as ex: |
357 | 329 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
358 | 330 |
|
359 | 331 |
''' |
360 |
@breif merge lines(1.connect collinear lines 2.connect lines) |
|
361 |
@author humkyung |
|
362 |
@date 2018.04.11 |
|
332 |
@breif merge lines(1.connect collinear lines 2.connect lines) |
|
333 |
@author humkyung |
|
334 |
@date 2018.04.11 |
|
335 |
@history humkyung 2018.04.12 continue loop if line is not in connectedLines |
|
363 | 336 |
''' |
364 | 337 |
def mergeLines(self, connectedLines, toler): |
365 | 338 |
try: |
366 |
bLoop = True |
|
367 |
#while bLoop and (len(connectedLines) > 1): |
|
368 |
bLoop = False |
|
369 | 339 |
for line in connectedLines[:]: |
340 |
if line not in connectedLines: continue |
|
370 | 341 |
matches = [param for param in connectedLines if (line != param) and self.isCollinear(line, param, toler)] |
371 | 342 |
if len(matches) > 0: |
372 | 343 |
matches.append(line) |
... | ... | |
375 | 346 |
if mergedLine is not None: |
376 | 347 |
connectedLines.append(mergedLine) |
377 | 348 |
for match in matches: connectedLines.remove(match) |
378 |
|
|
379 |
bLoop = True |
|
380 |
#break |
|
381 | 349 |
except Exception as ex: |
382 | 350 |
print('error occured({}) in {}:{}'.format(ex, sys.exc_info()[-1].tb_frame.f_code.co_filename, sys.exc_info()[-1].tb_lineno)) |
383 | 351 |
|
내보내기 Unified diff