개정판 f500705a
issue #1366: add auto labeling function
Change-Id: I586b2fea69445b75434721338811a3bf8b4e9611
DTI_PID/DTI_PID/MainWindow.py | ||
---|---|---|
279 | 279 |
if configs and 1 == len(configs) and 'advanced' == configs[0].value: |
280 | 280 |
self.actionOCR_Training.triggered.connect(self.oCRTrainingClicked) |
281 | 281 |
self.actionSymbol_Training.triggered.connect(self.symbolTrainingClicked) |
282 |
self.actionMake_Label_Data.triggered.connect(self.make_label_data) |
|
282 | 283 |
else: |
283 | 284 |
# self.actionOCR_Training.setVisible(False) |
284 | 285 |
# self.actionSymbol_Training.setVisible(False) |
... | ... | |
1828 | 1829 |
self.onCommandRejected() |
1829 | 1830 |
QApplication.restoreOverrideCursor() |
1830 | 1831 |
|
1832 |
def make_label_data(self): |
|
1833 |
""" make label data from symbol info """ |
|
1834 |
from xml.etree.ElementTree import Element, SubElement, dump, ElementTree, parse |
|
1835 |
|
|
1836 |
if not self.graphicsView.hasImage(): |
|
1837 |
self.showImageSelectionMessageBox() |
|
1838 |
return |
|
1839 |
|
|
1840 |
app_doc_data = AppDocData.instance() |
|
1841 |
project = app_doc_data.getCurrentProject() |
|
1842 |
|
|
1843 |
smalls = [] |
|
1844 |
bigs = [] |
|
1845 |
|
|
1846 |
symbol_list = app_doc_data.getTargetSymbolList(all=True) |
|
1847 |
for symbol in symbol_list: |
|
1848 |
if symbol.width and symbol.height: |
|
1849 |
if symbol.width > 300 or symbol.height > 300: |
|
1850 |
bigs.append(symbol.getName()) |
|
1851 |
else: |
|
1852 |
smalls.append(symbol.getName()) |
|
1853 |
|
|
1854 |
symbols = [item for item in self.graphicsView.scene().items() if issubclass(type(item), SymbolSvgItem)] |
|
1855 |
names = [smalls, bigs] |
|
1856 |
|
|
1857 |
img = app_doc_data.activeDrawing.image_origin |
|
1858 |
|
|
1859 |
small_size = 500 |
|
1860 |
big_size = 850 |
|
1861 |
|
|
1862 |
save_path = project.getTrainingSymbolFilePath() |
|
1863 |
|
|
1864 |
index = 0 |
|
1865 |
for size in [small_size, big_size]: |
|
1866 |
offsets = [0, int(size / 2)] |
|
1867 |
|
|
1868 |
width, height = img.shape[1], img.shape[0] |
|
1869 |
width_count, height_count = width // size + 2, height // size + 2 |
|
1870 |
b_width, b_height = width_count * size, height_count * size |
|
1871 |
b_img = np.zeros((b_height, b_width), np.uint8) + 255 |
|
1872 |
b_img[:height, :width] = img[:, :] |
|
1873 |
|
|
1874 |
for offset in offsets: |
|
1875 |
for row in range(height_count): |
|
1876 |
for col in range(width_count): |
|
1877 |
x, y = col * size + offset, row * size + offset |
|
1878 |
tile_rect = QRectF(x, y, size, size) |
|
1879 |
tile_symbols = [] |
|
1880 |
for symbol in [symbol for symbol in symbols if symbol.name in names[index]]: |
|
1881 |
if tile_rect.contains(symbol.sceneBoundingRect()): |
|
1882 |
tile_symbols.append(symbol) |
|
1883 |
symbols.remove(symbol) |
|
1884 |
|
|
1885 |
if tile_symbols: |
|
1886 |
training_uid = str(uuid.uuid4()) |
|
1887 |
training_image_path = os.path.join(save_path, training_uid + '.png') |
|
1888 |
training_xml_path = os.path.join(save_path, training_uid + '.xml') |
|
1889 |
|
|
1890 |
# save image |
|
1891 |
_img = b_img[round(tile_rect.top()):round(tile_rect.bottom()), |
|
1892 |
round(tile_rect.left()):round(tile_rect.right())] |
|
1893 |
cv2.imwrite(training_image_path, _img) |
|
1894 |
|
|
1895 |
# save label |
|
1896 |
xml = Element('annotation') |
|
1897 |
SubElement(xml, 'folder').text = 'None' |
|
1898 |
SubElement(xml, 'filename').text = os.path.basename(save_path) |
|
1899 |
|
|
1900 |
pathNode = Element('path') |
|
1901 |
pathNode.text = save_path.replace('/', '\\') |
|
1902 |
xml.append(pathNode) |
|
1903 |
|
|
1904 |
sourceNode = Element('source') |
|
1905 |
databaseNode = Element('database') |
|
1906 |
databaseNode.text = 'Unknown' |
|
1907 |
sourceNode.append(databaseNode) |
|
1908 |
xml.append(sourceNode) |
|
1909 |
|
|
1910 |
sizeNode = Element('size') |
|
1911 |
widthNode = Element('width') |
|
1912 |
widthNode.text = str(int(tile_rect.width())) |
|
1913 |
sizeNode.append(widthNode) |
|
1914 |
heightNode = Element('height') |
|
1915 |
heightNode.text = str(int(tile_rect.height())) |
|
1916 |
sizeNode.append(heightNode) |
|
1917 |
depthNode = Element('depth') |
|
1918 |
depthNode.text = '3' |
|
1919 |
sizeNode.append(depthNode) |
|
1920 |
xml.append(sizeNode) |
|
1921 |
|
|
1922 |
segmentedNode = Element('segmented') |
|
1923 |
segmentedNode.text = '0' |
|
1924 |
xml.append(segmentedNode) |
|
1925 |
|
|
1926 |
labelContent = [] |
|
1927 |
counts = {} |
|
1928 |
for item in tile_symbols: |
|
1929 |
rect = item.sceneBoundingRect() |
|
1930 |
label, xMin, yMin, xMax, yMax = item.name, int(rect.x() - 5 - x), int(rect.y() - 5 - y), int(rect.x() + rect.width() + 5 - x), int(rect.y() + rect.height() + 5 - y) |
|
1931 |
xMin = xMin if xMin > 0 else 0 |
|
1932 |
yMin = yMin if yMin > 0 else 0 |
|
1933 |
xMax = xMax if xMax < size else size |
|
1934 |
yMax = yMax if yMax < size else size |
|
1935 |
|
|
1936 |
if label == 'None' or label == '': |
|
1937 |
continue |
|
1938 |
if label not in labelContent: |
|
1939 |
labelContent.append(label) |
|
1940 |
counts[label] = 1 |
|
1941 |
else: |
|
1942 |
counts[label] = counts[label] + 1 |
|
1943 |
|
|
1944 |
objectNode = Element('object') |
|
1945 |
nameNode = Element('name') |
|
1946 |
nameNode.text = label |
|
1947 |
objectNode.append(nameNode) |
|
1948 |
poseNode = Element('pose') |
|
1949 |
poseNode.text = 'Unspecified' |
|
1950 |
objectNode.append(poseNode) |
|
1951 |
truncatedNode = Element('truncated') |
|
1952 |
truncatedNode.text = '0' |
|
1953 |
objectNode.append(truncatedNode) |
|
1954 |
difficultNode = Element('difficult') |
|
1955 |
difficultNode.text = '0' |
|
1956 |
objectNode.append(difficultNode) |
|
1957 |
|
|
1958 |
bndboxNode = Element('bndbox') |
|
1959 |
xminNode = Element('xmin') |
|
1960 |
xminNode.text = str(xMin) |
|
1961 |
bndboxNode.append(xminNode) |
|
1962 |
yminNode = Element('ymin') |
|
1963 |
yminNode.text = str(yMin) |
|
1964 |
bndboxNode.append(yminNode) |
|
1965 |
xmaxNode = Element('xmax') |
|
1966 |
xmaxNode.text = str(xMax) |
|
1967 |
bndboxNode.append(xmaxNode) |
|
1968 |
ymaxNode = Element('ymax') |
|
1969 |
ymaxNode.text = str(yMax) |
|
1970 |
bndboxNode.append(ymaxNode) |
|
1971 |
objectNode.append(bndboxNode) |
|
1972 |
|
|
1973 |
xml.append(objectNode) |
|
1974 |
|
|
1975 |
ElementTree(xml).write(training_xml_path) |
|
1976 |
|
|
1977 |
index += 1 |
|
1978 |
|
|
1979 |
|
|
1831 | 1980 |
''' |
1832 | 1981 |
@brief create a line |
1833 | 1982 |
@author humkyung |
1834 | 1983 |
@history Jeongwoo 2018.05.10 Change method for Checkable action |
1835 | 1984 |
''' |
1836 |
|
|
1837 | 1985 |
def onPlaceLine(self): |
1838 | 1986 |
if not self.graphicsView.hasImage(): |
1839 | 1987 |
self.actionLine.setChecked(False) |
DTI_PID/DTI_PID/MainWindow_UI.py | ||
---|---|---|
1 | 1 |
# -*- coding: utf-8 -*- |
2 | 2 |
|
3 |
# Form implementation generated from reading ui file '.\UI\MainWindow.ui'
|
|
3 |
# Form implementation generated from reading ui file './UI/MainWindow.ui'
|
|
4 | 4 |
# |
5 |
# Created by: PyQt5 UI code generator 5.14.2
|
|
5 |
# Created by: PyQt5 UI code generator 5.11.3
|
|
6 | 6 |
# |
7 | 7 |
# WARNING! All changes made in this file will be lost! |
8 | 8 |
|
9 |
|
|
10 | 9 |
from PyQt5 import QtCore, QtGui, QtWidgets |
11 | 10 |
|
12 |
|
|
13 | 11 |
class Ui_MainWindow(object): |
14 | 12 |
def setupUi(self, MainWindow): |
15 | 13 |
MainWindow.setObjectName("MainWindow") |
... | ... | |
582 | 580 |
self.actionRedo.setObjectName("actionRedo") |
583 | 581 |
self.actionSymbol_Replace_Insert = QtWidgets.QAction(MainWindow) |
584 | 582 |
self.actionSymbol_Replace_Insert.setObjectName("actionSymbol_Replace_Insert") |
583 |
self.actionMake_Label_Data = QtWidgets.QAction(MainWindow) |
|
584 |
self.actionMake_Label_Data.setObjectName("actionMake_Label_Data") |
|
585 | 585 |
self.menuExport.addAction(self.actionExportAsSVG) |
586 | 586 |
self.menuExport.addAction(self.actionExportAsXML) |
587 | 587 |
self.menuExport.addAction(self.actionExportAsImage) |
... | ... | |
606 | 606 |
self.menu_2.addSeparator() |
607 | 607 |
self.menu_2.addAction(self.actionOCR_Training) |
608 | 608 |
self.menu_2.addAction(self.actionSymbol_Training) |
609 |
self.menu_2.addAction(self.actionMake_Label_Data) |
|
609 | 610 |
self.menu_3.addAction(self.actionImage_Drawing) |
610 | 611 |
self.menu_3.addAction(self.actionViewText) |
611 | 612 |
self.menu_3.addAction(self.actionViewSymbol) |
... | ... | |
781 | 782 |
self.actionRedo.setText(_translate("MainWindow", "Redo")) |
782 | 783 |
self.actionRedo.setToolTip(_translate("MainWindow", "Redo")) |
783 | 784 |
self.actionSymbol_Replace_Insert.setText(_translate("MainWindow", "Symbol Replace/Insert")) |
785 |
self.actionMake_Label_Data.setText(_translate("MainWindow", "Make Label Data")) |
|
786 |
|
|
784 | 787 |
import MainWindow_rc |
788 |
|
|
789 |
if __name__ == "__main__": |
|
790 |
import sys |
|
791 |
app = QtWidgets.QApplication(sys.argv) |
|
792 |
MainWindow = QtWidgets.QMainWindow() |
|
793 |
ui = Ui_MainWindow() |
|
794 |
ui.setupUi(MainWindow) |
|
795 |
MainWindow.show() |
|
796 |
sys.exit(app.exec_()) |
|
797 |
|
DTI_PID/DTI_PID/Shapes/EngineeringLineNoTextItem.py | ||
---|---|---|
329 | 329 |
app_doc_data = AppDocData.instance() |
330 | 330 |
|
331 | 331 |
# get associations |
332 |
associations = app_doc_data.get_component_associations(uid)
|
|
332 |
associations = app_doc_data.get_component_associations(component['UID'])
|
|
333 | 333 |
if associations: |
334 | 334 |
for assoc in associations: |
335 | 335 |
_attrType = assoc['Type'] |
DTI_PID/DTI_PID/UI/MainWindow.ui | ||
---|---|---|
108 | 108 |
<addaction name="separator"/> |
109 | 109 |
<addaction name="actionOCR_Training"/> |
110 | 110 |
<addaction name="actionSymbol_Training"/> |
111 |
<addaction name="actionMake_Label_Data"/> |
|
111 | 112 |
</widget> |
112 | 113 |
<widget class="QMenu" name="menu_3"> |
113 | 114 |
<property name="title"> |
... | ... | |
1240 | 1241 |
</action> |
1241 | 1242 |
<action name="actionExportAsSVG"> |
1242 | 1243 |
<property name="icon"> |
1243 |
<iconset resource="../res/MainWindow.qrc">
|
|
1244 |
<iconset> |
|
1244 | 1245 |
<normaloff>:/newPrefix/svg.png</normaloff>:/newPrefix/svg.png</iconset> |
1245 | 1246 |
</property> |
1246 | 1247 |
<property name="text"> |
... | ... | |
1309 | 1310 |
<string>Symbol Replace/Insert</string> |
1310 | 1311 |
</property> |
1311 | 1312 |
</action> |
1313 |
<action name="actionMake_Label_Data"> |
|
1314 |
<property name="text"> |
|
1315 |
<string>Make Label Data</string> |
|
1316 |
</property> |
|
1317 |
</action> |
|
1312 | 1318 |
</widget> |
1313 | 1319 |
<resources> |
1314 | 1320 |
<include location="../res/MainWindow.qrc"/> |
내보내기 Unified diff