Enable difficult mode, fix a bug on Mac and Update icon
|
@ -107,7 +107,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
getStr = lambda strId: self.stringBundle.getString(strId)
|
||||
|
||||
self.defaultSaveDir = defaultSaveDir
|
||||
self.ocr = PaddleOCR(use_pdserving=False, use_angle_cls=True, det=True, cls=True, use_gpu=False, lang=lang)
|
||||
self.ocr = PaddleOCR(use_pdserving=False, use_angle_cls=True, det=True, cls=True, use_gpu=True, lang=lang)
|
||||
|
||||
if os.path.exists('./data/paddle.png'):
|
||||
result = self.ocr.ocr('./data/paddle.png', cls=True, det=True)
|
||||
|
@ -161,9 +161,6 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
self.AutoRecognition = QToolButton()
|
||||
self.AutoRecognition.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
self.AutoRecognition.setIcon(newIcon('Auto'))
|
||||
# self.AutoRecognition.setIconSize(QSize(100,20))
|
||||
# self.AutoRecognition.setFixedSize(QSize(80,30))
|
||||
# self.AutoRecognition.setStyleSheet('text-align:center;')#border:none;font-size : 12pt;
|
||||
autoRecLayout = QHBoxLayout()
|
||||
autoRecLayout.setContentsMargins(0, 0, 0, 0)
|
||||
autoRecLayout.addWidget(self.AutoRecognition)
|
||||
|
@ -182,25 +179,17 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
listLayout = QVBoxLayout()
|
||||
listLayout.setContentsMargins(0, 0, 0, 0)
|
||||
|
||||
# Create a widget for edit and diffc button
|
||||
self.diffcButton = QCheckBox(getStr('useDifficult'))
|
||||
self.diffcButton.setChecked(False)
|
||||
self.diffcButton.stateChanged.connect(self.btnstate)
|
||||
self.editButton = QToolButton()
|
||||
self.reRecogButton = QToolButton()
|
||||
self.reRecogButton.setIcon(newIcon('reRec', 30))
|
||||
# self.reRecogButton.setFixedSize(QSize(80,30))
|
||||
self.reRecogButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
|
||||
self.newButton = QToolButton()
|
||||
self.newButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
# self.newButton.setFixedSize(QSize(80, 30))
|
||||
self.SaveButton = QToolButton()
|
||||
self.SaveButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
# self.SaveButton.setFixedSize(QSize(60, 30))
|
||||
self.DelButton = QToolButton()
|
||||
self.DelButton.setToolButtonStyle(Qt.ToolButtonTextBesideIcon)
|
||||
# self.DelButton.setFixedSize(QSize(80, 30))
|
||||
|
||||
|
||||
lefttoptoolbox = QHBoxLayout()
|
||||
|
@ -285,12 +274,9 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
hlayout.setSpacing(0)
|
||||
hlayout.setContentsMargins(*m)
|
||||
self.preButton = QToolButton()
|
||||
# self.preButton.setFixedHeight(100)
|
||||
# self.preButton.setText(getStr("prevImg"))
|
||||
self.preButton.setIcon(newIcon("prev",40))
|
||||
self.preButton.setIconSize(QSize(40, 100))
|
||||
self.preButton.clicked.connect(self.openPrevImg)
|
||||
# self.preButton.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
|
||||
self.preButton.setStyleSheet('border: none;')
|
||||
self.iconlist = QListWidget()
|
||||
self.iconlist.setViewMode(QListView.IconMode)
|
||||
|
@ -299,19 +285,14 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
self.iconlist.setIconSize(QSize(50, 50))
|
||||
self.iconlist.setMovement(False)
|
||||
self.iconlist.setResizeMode(QListView.Adjust)
|
||||
# self.iconlist.itemDoubleClicked.connect(self.iconitemDoubleClicked)
|
||||
self.iconlist.itemClicked.connect(self.iconitemDoubleClicked)
|
||||
self.iconlist.setStyleSheet("background-color:transparent; border: none;")
|
||||
self.iconlist.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
|
||||
# self.iconlist.setStyleSheet('border: none;')
|
||||
self.nextButton = QToolButton()
|
||||
# self.nextButton.setFixedHeight(100)
|
||||
# self.nextButton.setText(getStr("nextImg"))
|
||||
self.nextButton.setIcon(newIcon("next", 40))
|
||||
self.nextButton.setIconSize(QSize(40, 100))
|
||||
self.nextButton.setStyleSheet('border: none;')
|
||||
self.nextButton.clicked.connect(self.openNextImg)
|
||||
# self.nextButton.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
|
||||
|
||||
hlayout.addWidget(self.preButton)
|
||||
hlayout.addWidget(self.iconlist)
|
||||
|
@ -874,7 +855,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
# shape.line_color = generateColorByText(shape.label)
|
||||
self.setDirty()
|
||||
else: # User probably changed item visibility
|
||||
self.canvas.setShapeVisible(shape, item.checkState() == Qt.Checked)
|
||||
self.canvas.setShapeVisible(shape, True)#item.checkState() == Qt.Checked
|
||||
|
||||
def editBox(self): # ADD
|
||||
if not self.canvas.editing():
|
||||
|
@ -945,33 +926,6 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
if len(self.mImgList) > 0:
|
||||
self.zoomWidget.setValue(self.zoomWidgetValue + self.imgsplider.value())
|
||||
|
||||
# Add chris
|
||||
def btnstate(self, item=None):
|
||||
""" Function to handle difficult examples
|
||||
Update on each object """
|
||||
if not self.canvas.editing():
|
||||
return
|
||||
|
||||
item = self.currentItem()
|
||||
if not item: # If not selected Item, take the first one
|
||||
item = self.labelList.item(self.labelList.count() - 1)
|
||||
|
||||
difficult = self.diffcButton.isChecked()
|
||||
|
||||
try:
|
||||
shape = self.itemsToShapes[item]
|
||||
except:
|
||||
pass
|
||||
# Checked and Update
|
||||
try:
|
||||
if difficult != shape.difficult:
|
||||
shape.difficult = difficult
|
||||
self.setDirty()
|
||||
else: # User probably changed item visibility
|
||||
self.canvas.setShapeVisible(shape, item.checkState() == Qt.Checked)
|
||||
except:
|
||||
pass
|
||||
|
||||
# React to canvas signals.
|
||||
def shapeSelectionChanged(self, selected=False):
|
||||
if self._noSelectionSlot:
|
||||
|
@ -993,7 +947,8 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
shape.paintLabel = self.displayLabelOption.isChecked()
|
||||
item = HashableQListWidgetItem(shape.label)
|
||||
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
|
||||
item.setCheckState(Qt.Checked)
|
||||
item.setCheckState(Qt.Unchecked) if shape.difficult else item.setCheckState(Qt.Checked)
|
||||
# Checked means difficult is False
|
||||
# item.setBackground(generateColorByText(shape.label))
|
||||
self.itemsToShapes[item] = shape
|
||||
self.shapesToItems[shape] = item
|
||||
|
@ -1002,10 +957,6 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
|
||||
# ADD for box
|
||||
item = HashableQListWidgetItem(str([(int(p.x()), int(p.y())) for p in shape.points]))
|
||||
# item = QListWidgetItem(str([(p.x(), p.y()) for p in shape.points]))
|
||||
item.setFlags(item.flags() | Qt.ItemIsUserCheckable)
|
||||
item.setCheckState(Qt.Checked)
|
||||
# item.setBackground(generateColorByText(shape.label))
|
||||
self.itemsToShapesbox[item] = shape
|
||||
self.shapesToItemsbox[shape] = item
|
||||
self.BoxList.addItem(item)
|
||||
|
@ -1072,6 +1023,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
# self.comboBox.update_items(uniqueTextList)
|
||||
|
||||
def saveLabels(self, annotationFilePath, mode='Auto'):
|
||||
# Mode is Auto means that labels will be loaded from self.result_dic totally, which is the output of ocr model
|
||||
annotationFilePath = ustr(annotationFilePath)
|
||||
if self.labelFile is None:
|
||||
self.labelFile = LabelFile()
|
||||
|
@ -1090,17 +1042,16 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
[format_shape(shape) for shape in self.canvas.shapes]
|
||||
# Can add differrent annotation formats here
|
||||
|
||||
if self.model == 'paddle':
|
||||
for box in self.result_dic:
|
||||
trans_dic = {"label": box[1][0], "points": box[0], 'difficult': False}
|
||||
if trans_dic["label"] is "" and mode == 'Auto':
|
||||
continue
|
||||
shapes.append(trans_dic)
|
||||
for box in self.result_dic:
|
||||
trans_dic = {"label": box[1][0], "points": box[0], 'difficult': False}
|
||||
if trans_dic["label"] is "" and mode == 'Auto':
|
||||
continue
|
||||
shapes.append(trans_dic)
|
||||
|
||||
try:
|
||||
trans_dic = []
|
||||
for box in shapes:
|
||||
trans_dic.append({"transcription": box['label'], "points": box['points'], 'difficult': False})
|
||||
trans_dic.append({"transcription": box['label'], "points": box['points'], 'difficult': box['difficult']})
|
||||
self.PPlabel[annotationFilePath] = trans_dic
|
||||
|
||||
if mode == 'Auto':
|
||||
|
@ -1127,8 +1078,6 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
self._noSelectionSlot = True
|
||||
self.canvas.selectShape(self.itemsToShapes[item])
|
||||
shape = self.itemsToShapes[item]
|
||||
# Add Chris
|
||||
self.diffcButton.setChecked(shape.difficult)
|
||||
|
||||
def boxSelectionChanged(self):
|
||||
item = self.currentBox()
|
||||
|
@ -1136,8 +1085,6 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
self._noSelectionSlot = True
|
||||
self.canvas.selectShape(self.itemsToShapesbox[item])
|
||||
shape = self.itemsToShapesbox[item]
|
||||
# Add Chris
|
||||
self.diffcButton.setChecked(shape.difficult)
|
||||
|
||||
def labelItemChanged(self, item):
|
||||
shape = self.itemsToShapes[item]
|
||||
|
@ -1146,8 +1093,12 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
shape.label = item.text()
|
||||
# shape.line_color = generateColorByText(shape.label)
|
||||
self.setDirty()
|
||||
elif not ((item.checkState()== Qt.Unchecked) ^ (not shape.difficult)):
|
||||
shape.difficult = True if item.checkState() == Qt.Unchecked else False
|
||||
self.setDirty()
|
||||
else: # User probably changed item visibility
|
||||
self.canvas.setShapeVisible(shape, item.checkState() == Qt.Checked)
|
||||
self.canvas.setShapeVisible(shape, True) # item.checkState() == Qt.Checked
|
||||
# self.actions.save.setEnabled(True)
|
||||
|
||||
# Callback functions:
|
||||
def newShape(self):
|
||||
|
@ -1166,8 +1117,6 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
text = self.labelDialog.popUp(text=self.prevLabelText)
|
||||
self.lastLabel = text
|
||||
|
||||
# Add Chris
|
||||
self.diffcButton.setChecked(False)
|
||||
if text is not None:
|
||||
self.prevLabelText = self.stringBundle.getString('tempLabel')
|
||||
# generate_color = generateColorByText(text)
|
||||
|
@ -1264,7 +1213,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
|
||||
def togglePolygons(self, value):
|
||||
for item, shape in self.itemsToShapes.items():
|
||||
item.setCheckState(Qt.Checked if value else Qt.Unchecked)
|
||||
self.canvas.setShapeVisible(shape, value)
|
||||
|
||||
def loadFile(self, filePath=None):
|
||||
"""Load the specified file, or the last opened file if None."""
|
||||
|
@ -1628,6 +1577,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
pass
|
||||
|
||||
def saveFile(self, _value=False, mode='Manual'):
|
||||
# Manual mode is used for users click "Save" manually,which will change the state of the image
|
||||
if self.defaultSaveDir is not None and len(ustr(self.defaultSaveDir)):
|
||||
if self.filePath:
|
||||
imgidx = self.getImglabelidx(self.filePath)
|
||||
|
@ -1925,8 +1875,6 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
self.comboBox = QComboBox()
|
||||
self.comboBox.setObjectName("comboBox")
|
||||
self.comboBox.addItems(['Chinese & English', 'English', 'French', 'German', 'Korean', 'Japanese'])
|
||||
# self.comboBox_lg = QComboBox()
|
||||
# self.comboBox_lg.setObjectName("comboBox_language")
|
||||
vbox.addWidget(self.panel)
|
||||
vbox.addWidget(self.comboBox)
|
||||
self.dialog = QDialog()
|
||||
|
@ -1994,6 +1942,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
file, label = each.split('\t')
|
||||
if label:
|
||||
label = label.replace('false', 'False')
|
||||
label = label.replace('true', 'True')
|
||||
labeldict[file] = eval(label)
|
||||
else:
|
||||
labeldict[file] = []
|
||||
|
@ -2004,7 +1953,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
savedfile = [self.getImglabelidx(i) for i in self.fileStatedict.keys()]
|
||||
with open(self.PPlabelpath, 'w', encoding='utf-8') as f:
|
||||
for key in self.PPlabel:
|
||||
if key in savedfile:
|
||||
if key in savedfile and self.PPlabel[key] != []:
|
||||
f.write(key + '\t')
|
||||
f.write(json.dumps(self.PPlabel[key], ensure_ascii=False) + '\n')
|
||||
|
||||
|
@ -2032,6 +1981,7 @@ class MainWindow(QMainWindow, WindowMixin):
|
|||
for key in self.fileStatedict:
|
||||
idx = self.getImglabelidx(key)
|
||||
for i, label in enumerate(self.PPlabel[idx]):
|
||||
if label['difficult']: continue
|
||||
img = cv2.imread(key)
|
||||
img_crop = get_rotate_crop_image(img, np.array(label['points'], np.float32))
|
||||
img_name = os.path.splitext(os.path.basename(idx))[0] + '_crop_'+str(i)+'.jpg'
|
||||
|
@ -2070,8 +2020,7 @@ def get_main_app(argv=[]):
|
|||
args = argparser.parse_args(argv[1:])
|
||||
# Usage : labelImg.py image predefClassFile saveDir
|
||||
win = MainWindow(lang=args.lang,
|
||||
defaultPrefdefClassFile=args.predefined_classes_file,
|
||||
)
|
||||
defaultPrefdefClassFile=args.predefined_classes_file)
|
||||
win.show()
|
||||
return app, win
|
||||
|
||||
|
|
|
@ -74,18 +74,26 @@ python3 PPOCRLabel.py
|
|||
|
||||
## 说明
|
||||
### 内置模型
|
||||
|
||||
- 默认模型:PPOCRLabel默认使用PaddleOCR中的中英文超轻量OCR模型,支持中英文与数字识别,多种语言检测。
|
||||
|
||||
- 模型语言切换:用户可通过菜单栏中 "PaddleOCR" - "选择模型" 切换内置模型语言,目前支持的语言包括法文、德文、韩文、日文。具体模型下载链接可参考[PaddleOCR模型列表](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_ch/models_list.md).
|
||||
- 自定义模型:用户可根据[自定义模型代码使用](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_ch/whl.md#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1%E5%9E%8B),通过修改PPOCRLabel.py中针对[PaddleOCR类的实例化](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/PPOCRLabel/PPOCRLabel.py#L110)替换成自己训练的模型
|
||||
|
||||
- 自定义模型:用户可根据[自定义模型代码使用](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_ch/whl.md#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1%E5%9E%8B),通过修改PPOCRLabel.py中针对[PaddleOCR类的实例化](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/PPOCRLabel/PPOCRLabel.py#L110)替换成自己训练的模型。
|
||||
|
||||
### 导出部分识别结果
|
||||
|
||||
针对部分难以识别的数据,通过在识别结果的复选框中**取消勾选**相应的标记,其识别结果不会被导出。
|
||||
|
||||
*注意:识别结果中的复选框状态仍需用户手动点击保存后才能保留*
|
||||
|
||||
### 错误提示
|
||||
- 如果同时使用whl包安装了paddleocr,其优先级大于通过paddleocr.py调用PaddleOCR类,whl包未更新时会导致程序异常。
|
||||
- PPOCRLabel**不支持对中文文件名**的图片进行自动标注。
|
||||
- 如果您在打开软件过程中出现**objc[XXXXX]**开头的错误,证明您的opencv版本太高,建议安装4.2版本:
|
||||
```
|
||||
pip install opencv-python==4.2.0.32
|
||||
```
|
||||
|
||||
```
|
||||
pip install opencv-python==4.2.0.32
|
||||
```
|
||||
### 参考资料
|
||||
|
||||
1.[Tzutalin. LabelImg. Git code (2015)](https://github.com/tzutalin/labelImg)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# PPOCRLabel
|
||||
|
||||
PPOCRLabel is a semi-automatic graphic annotation tool suitable for OCR field. It is written in python3 and pyqt5. Support rectangular frame labeling and four-point labeling mode. Annotations can be directly used for the training of PPOCR detection and recognition models.
|
||||
PPOCRLabel is a semi-automatic graphic annotation tool suitable for OCR field. It is written in python3 and pyqt5, supporting rectangular box annotation and four-point annotation modes. Annotations can be directly used for the training of PPOCR detection and recognition models.
|
||||
|
||||
<img src="./data/gif/steps.gif" width="100%"/>
|
||||
|
||||
|
@ -89,14 +89,33 @@ Therefore, if the recognition result has been manually changed before, it may ch
|
|||
| rec_gt.txt | The recognition label file, which can be directly used for PPOCR identification model training, is generated after the user clicks on the menu bar "PaddleOCR"-"Save recognition result". |
|
||||
| crop_img | The recognition data, generated at the same time with *rec_gt.txt* |
|
||||
|
||||
## Explanation
|
||||
|
||||
### Built-in Model
|
||||
|
||||
- Default model: PPOCRLabel uses the Chinese and English ultra-lightweight OCR model in PaddleOCR by default, supports Chinese, English and number recognition, and multiple language detection.
|
||||
|
||||
- Model language switching: Changing the built-in model language is supportable by clicking "PaddleOCR"-"Choose OCR Model" in the menu bar. Currently supported languagesinclude French, German, Korean, and Japanese.
|
||||
For specific model download links, please refer to [PaddleOCR Model List](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_en/models_list_en.md#multilingual-recognition-modelupdating)
|
||||
For specific model download links, please refer to [PaddleOCR Model List](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_en/models_list_en.md#multilingual-recognition-modelupdating)
|
||||
|
||||
- Custom model: The model trained by users can be replaced by modifying PPOCRLabel.py in [PaddleOCR class instantiation](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/PPOCRLabel/PPOCRLabel.py#L110) referring [Custom Model Code](https://github.com/PaddlePaddle/PaddleOCR/blob/develop/doc/doc_en/whl_en.md#use-custom-model)
|
||||
|
||||
### Export partial recognition results
|
||||
|
||||
## Related
|
||||
For some data that are difficult to recognize, the recognition results will not be exported by **unchecking** the corresponding tags in the recognition results checkbox.
|
||||
|
||||
*Note: The status of the checkboxes in the recognition results still needs to be saved manually by clicking Save Button.*
|
||||
|
||||
### Error message
|
||||
|
||||
- If paddleocr is installed with whl, it has a higher priority than calling PaddleOCR class with paddleocr.py, which may cause an exception if whl package is not updated.
|
||||
|
||||
- If you get an error starting with **objc[XXXXX]** when opening the software, it proves that your opencv version is too high. It is recommended to install version 4.2:
|
||||
|
||||
```
|
||||
pip install opencv-python==4.2.0.32
|
||||
```
|
||||
|
||||
### Related
|
||||
|
||||
1.[Tzutalin. LabelImg. Git code (2015)](https://github.com/tzutalin/labelImg)
|
||||
|
|
|
@ -25,6 +25,7 @@ class Worker(QThread):
|
|||
self.mImgList = mImgList
|
||||
self.mainThread = mainThread
|
||||
self.model = model
|
||||
self.setStackSize(1024*1024)
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
|
|
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 471 B |
Before Width: | Height: | Size: 7.7 KiB After Width: | Height: | Size: 58 KiB |
|
@ -1 +1,27 @@
|
|||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1605840513947" class="icon" viewBox="0 0 1036 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="570" xmlns:xlink="http://www.w3.org/1999/xlink" width="202.34375" height="200"><defs><style type="text/css"></style></defs><path d="M938.74776 69.162438L893.455144 52.837457a67.26383 67.26383 0 1 0-20.007307 64.317969l42.469499 15.465771c28.722146 10.433258 53.516478 49.097686 53.516478 83.466066v598.869028c0 34.000148-24.548843 72.664576-53.639223 82.729601l-38.296195 13.501863a67.26383 67.26383 0 1 0 14.115585 66.650109l46.397313-16.447724c55.60313-19.51633 98.195372-83.711555 98.195373-146.311105V216.210008c0-62.354061-42.960475-126.917519-98.195373-147.293059zM222.16703 888.971053a66.895597 66.895597 0 0 0-52.166292 24.548843L121.516773 897.440403A89.1123 89.1123 0 0 1 67.26383 822.443688V208.722611a89.97151 89.97151 0 0 1 54.252943-76.101414l51.920803-18.657121a67.632063 67.632063 0 1 0-15.465771-65.913643L98.195372 69.285182A157.358084 157.358084 0 0 0 0 208.722611v613.721077a156.253386 156.253386 0 0 0 99.30007 138.332731L159.56748 982.011168a67.509318 67.509318 0 1 0 62.59955-93.040115z" fill="#444444" p-id="571"></path><path d="M426.29066 572.413721l86.780161-205.105584 91.935417 205.105584z m282.311696 230.759125h119.798354l-267.58239-592.854561-98.195372 1.104698-251.625642 592.118096 118.079936-1.350187L380.507068 680.183142h272.492158l55.112153 122.744215z" fill="#444444" p-id="572"></path></svg>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="200px" height="200px" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>APPicon备份 3@2x</title>
|
||||
<defs>
|
||||
<linearGradient x1="50%" y1="0%" x2="50%" y2="100%" id="linearGradient-1">
|
||||
<stop stop-color="#A5ACFF" offset="0%"></stop>
|
||||
<stop stop-color="#545DFF" offset="100%"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g id="APPicon备份-3" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="编组-3备份-2" fill="url(#linearGradient-1)">
|
||||
<rect id="矩形" x="0" y="0" width="200" height="200" rx="4"></rect>
|
||||
</g>
|
||||
<g id="编组-4备份" transform="translate(11.000000, 11.000000)">
|
||||
<polyline id="路径" stroke="#FFFFFF" stroke-width="6" stroke-linecap="round" stroke-linejoin="round" points="104 167 11 167 11 11 167 11 167 96.7728865"></polyline>
|
||||
<circle id="椭圆形" fill="#FFFFFF" cx="167" cy="11" r="11"></circle>
|
||||
<circle id="椭圆形备份-8" fill="#FFFFFF" cx="11" cy="11" r="11"></circle>
|
||||
<circle id="椭圆形备份-9" fill="#FFFFFF" cx="11" cy="167" r="11"></circle>
|
||||
</g>
|
||||
<path d="M85.9991492,141 L69,141 L69,60 L97.061099,60.0005168 C106.622339,60.0180588 113.008403,60.4807625 115.775763,61.1684309 C120.478388,62.336394 124.240393,64.9067781 127.297375,69.1122872 C130.353887,73.08404 132,78.4580969 132,84.7663606 C132,89.6731387 131.059499,93.8786478 129.413268,97.1497163 C127.767626,100.420785 125.416373,103.224458 122.594751,105.09369 C119.773129,106.962805 116.951625,108.364641 114.130121,108.83192 C110.367998,109.766594 104.724872,110 97.4355156,110 L97.4355156,110 L85.999,110 L85.9991492,141 Z M86,74.2965717 L85.9299926,74.2965717 L85.929,96.849 L95.7229134,96.8497738 C101.895297,96.8497738 106.289281,96.4080944 108.473591,95.739226 L108.655396,95.681343 C110.771288,94.9806587 112.417401,93.5787054 113.828271,91.7095902 C115.239023,89.840475 115.709274,87.7373697 115.709274,85.4009757 C115.709274,82.3637805 114.768772,80.0273866 113.122542,78.1581545 C111.476782,76.2890393 109.125646,75.1206084 106.538915,74.6533297 C104.879206,74.2409217 101.572085,74.1924031 96.7786667,74.186695 L95.8002135,74.1860291 C95.4674884,74.1859339 95.1282054,74.1859339 94.7824121,74.1859339 L86,74.185 L86,74.2965717 Z" id="形状结合" fill="#FFFFFF"></path>
|
||||
<g id="编组" transform="translate(158.000000, 153.000000) rotate(65.000000) translate(-158.000000, -153.000000) translate(126.000000, 113.000000)">
|
||||
<path d="M32,8 C14.326888,8 0,22.326888 0,40 C0,49.0801087 3.78188139,57.2769117 9.85641113,63.1011759 M32,72 C49.673112,72 64,57.673112 64,40 C64,30.9865538 60.2734449,22.8434911 54.2770078,17.0274853" id="形状备份-2" stroke="#FFFFFF" stroke-width="5" stroke-linecap="round"></path>
|
||||
<polygon id="三角形备份-3" fill="#FFFFFF" transform="translate(38.000000, 8.000000) scale(-1, 1) rotate(-90.000000) translate(-38.000000, -8.000000) " points="38 2 46 14 30 14"></polygon>
|
||||
<polygon id="三角形备份-4" fill="#FFFFFF" transform="translate(26.000000, 72.000000) rotate(-90.000000) translate(-26.000000, -72.000000) " points="26 66 34 78 18 78"></polygon>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.2 KiB |