Spaces:
Running
Running
Commit
·
a383d0e
1
Parent(s):
31f6fbe
Add app.py and the screencoder repo
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- app.py +0 -0
- screencoder/.gitignore +11 -0
- screencoder/README.md +89 -0
- screencoder/UIED/.idea/UIED.iml +14 -0
- screencoder/UIED/.idea/inspectionProfiles/Project_Default.xml +29 -0
- screencoder/UIED/.idea/misc.xml +4 -0
- screencoder/UIED/.idea/modules.xml +8 -0
- screencoder/UIED/.idea/vcs.xml +6 -0
- screencoder/UIED/.idea/workspace.xml +336 -0
- screencoder/UIED/LICENSE +201 -0
- screencoder/UIED/README.md +80 -0
- screencoder/UIED/cnn/CNN.py +125 -0
- screencoder/UIED/cnn/Config.py +21 -0
- screencoder/UIED/cnn/Data.py +69 -0
- screencoder/UIED/cnn/__pycache__/CNN.cpython-312.pyc +0 -0
- screencoder/UIED/cnn/__pycache__/CNN.cpython-35.pyc +0 -0
- screencoder/UIED/cnn/model/cnn-rico-1.h5 +0 -0
- screencoder/UIED/config/CONFIG.py +45 -0
- screencoder/UIED/config/CONFIG_UIED.py +49 -0
- screencoder/UIED/config/__pycache__/CONFIG.cpython-312.pyc +0 -0
- screencoder/UIED/config/__pycache__/CONFIG.cpython-35.pyc +0 -0
- screencoder/UIED/config/__pycache__/CONFIG.cpython-37.pyc +0 -0
- screencoder/UIED/config/__pycache__/CONFIG_UIED.cpython-312.pyc +0 -0
- screencoder/UIED/config/__pycache__/CONFIG_UIED.cpython-35.pyc +0 -0
- screencoder/UIED/config/__pycache__/CONFIG_UIED.cpython-37.pyc +0 -0
- screencoder/UIED/data/demo/approach.png +3 -0
- screencoder/UIED/data/demo/demo.png +3 -0
- screencoder/UIED/data/input/0.jpg +3 -0
- screencoder/UIED/data/input/1.jpg +3 -0
- screencoder/UIED/data/input/10.jpg +3 -0
- screencoder/UIED/data/input/100.jpg +3 -0
- screencoder/UIED/data/input/11.jpg +3 -0
- screencoder/UIED/data/input/11300.jpg +3 -0
- screencoder/UIED/data/input/1220.jpg +3 -0
- screencoder/UIED/data/input/1565.jpg +3 -0
- screencoder/UIED/data/input/1627.jpg +3 -0
- screencoder/UIED/data/input/18116.jpg +3 -0
- screencoder/UIED/data/input/2.jpg +3 -0
- screencoder/UIED/data/input/214.jpg +3 -0
- screencoder/UIED/data/input/24.jpg +3 -0
- screencoder/UIED/data/input/245.jpg +3 -0
- screencoder/UIED/data/input/3.jpg +3 -0
- screencoder/UIED/data/input/30800.jpg +3 -0
- screencoder/UIED/data/input/4.jpg +3 -0
- screencoder/UIED/data/input/413.jpg +3 -0
- screencoder/UIED/data/input/472.jpg +3 -0
- screencoder/UIED/data/input/472a.jpg +3 -0
- screencoder/UIED/data/input/493.jpg +3 -0
- screencoder/UIED/data/input/497.jpg +3 -0
- screencoder/UIED/data/input/5.jpg +3 -0
app.py
ADDED
File without changes
|
screencoder/.gitignore
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Node / JavaScript
|
2 |
+
node_modules/
|
3 |
+
dist/
|
4 |
+
.DS_Store
|
5 |
+
|
6 |
+
# Environments
|
7 |
+
.env
|
8 |
+
.venv
|
9 |
+
|
10 |
+
# API keys
|
11 |
+
doubao_api.txt
|
screencoder/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Screencoder
|
2 |
+
|
3 |
+
### About
|
4 |
+
This is the Screencoder Project. Screencoder generates the HTML code for a website screenshot using a modular multi-agent framework.
|
5 |
+
|
6 |
+
### Project Structure
|
7 |
+
- `main.py`: The main script to generate final HTML code for a single screenshot.
|
8 |
+
- `UIED/`: Contains the UIED (UI Element Detection) engine for analyzing screenshots and detecting components.
|
9 |
+
- `run_single.py`: Python script to run UI component detection on a single image.
|
10 |
+
- `html_generator.py`: Takes the detected component data and generates a complete HTML layout with generated code for each module.
|
11 |
+
- `image_replacer.py`: A script to replace placeholder divs in the final HTML with actual cropped images.
|
12 |
+
- `mapping.py`: Maps the detected UIED components to logical page regions.
|
13 |
+
- `requirements.txt`: Lists all the necessary Python dependencies for the project.
|
14 |
+
- `doubao_api.txt`: API key file for the Doubao model (should be kept private and is included in `.gitignore`).
|
15 |
+
|
16 |
+
### Setup and Installation
|
17 |
+
|
18 |
+
1. **Clone the repository:**
|
19 |
+
```bash
|
20 |
+
git clone https://github.com/JimmyZhengyz/screencoder.git
|
21 |
+
cd screencoder
|
22 |
+
```
|
23 |
+
|
24 |
+
2. **Create a virtual environment:**
|
25 |
+
```bash
|
26 |
+
python3 -m venv .venv
|
27 |
+
source .venv/bin/activate
|
28 |
+
```
|
29 |
+
|
30 |
+
3. **Install dependencies:**
|
31 |
+
```bash
|
32 |
+
pip install -r requirements.txt
|
33 |
+
```
|
34 |
+
|
35 |
+
4. **Set up API Key:**
|
36 |
+
- Create a file named `doubao_api.txt` in the root directory.
|
37 |
+
- Paste your Doubao API key into this file.
|
38 |
+
|
39 |
+
### Usage
|
40 |
+
|
41 |
+
The typical workflow is a multi-step process as follows:
|
42 |
+
|
43 |
+
1. **Initial Generation with Placeholders:**
|
44 |
+
Run the Python script to generate the initial HTML code for a given screenshot.
|
45 |
+
- Block Detection:
|
46 |
+
```bash
|
47 |
+
python block_parsor.py
|
48 |
+
```
|
49 |
+
- Generation with Placeholders (Gray Images Blocks):
|
50 |
+
```bash
|
51 |
+
python html_generator.py
|
52 |
+
```
|
53 |
+
|
54 |
+
2. **Final HTML Code:**
|
55 |
+
Run the python script to generate final HTML code with copped images from the original screenshot.
|
56 |
+
- Placeholder Detection:
|
57 |
+
```bash
|
58 |
+
python image_box_detection.py
|
59 |
+
```
|
60 |
+
- UI Element Detection:
|
61 |
+
```bash
|
62 |
+
python UIED/run_single.py
|
63 |
+
```
|
64 |
+
- Mapping Alignment Between Placeholders and UI Elements:
|
65 |
+
```bash
|
66 |
+
python mapping.py
|
67 |
+
```
|
68 |
+
- Placeholder Replacement:
|
69 |
+
```bash
|
70 |
+
python image_replacer.py
|
71 |
+
```
|
72 |
+
|
73 |
+
3. **Simple Run:**
|
74 |
+
Run the python script to generate the final HTML code:
|
75 |
+
```bash
|
76 |
+
python main.py
|
77 |
+
```
|
78 |
+
|
79 |
+
### Demo
|
80 |
+
|
81 |
+
To access demo, you can follow these steps:
|
82 |
+
|
83 |
+
```bash
|
84 |
+
cd demo
|
85 |
+
pnpm install
|
86 |
+
pnpm run dev
|
87 |
+
```
|
88 |
+
|
89 |
+
Then, you can see the demo running.
|
screencoder/UIED/.idea/UIED.iml
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<module type="PYTHON_MODULE" version="4">
|
3 |
+
<component name="NewModuleRootManager">
|
4 |
+
<content url="file://$MODULE_DIR$">
|
5 |
+
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
6 |
+
<sourceFolder url="file://$MODULE_DIR$/resnet" isTestSource="false" />
|
7 |
+
</content>
|
8 |
+
<orderEntry type="inheritedJdk" />
|
9 |
+
<orderEntry type="sourceFolder" forTests="false" />
|
10 |
+
</component>
|
11 |
+
<component name="TestRunnerService">
|
12 |
+
<option name="PROJECT_TEST_RUNNER" value="py.test" />
|
13 |
+
</component>
|
14 |
+
</module>
|
screencoder/UIED/.idea/inspectionProfiles/Project_Default.xml
ADDED
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<component name="InspectionProjectProfileManager">
|
2 |
+
<profile version="1.0">
|
3 |
+
<option name="myName" value="Project Default" />
|
4 |
+
<inspection_tool class="DuplicatedCode" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
5 |
+
<Languages>
|
6 |
+
<language minSize="54" name="Python" />
|
7 |
+
</Languages>
|
8 |
+
</inspection_tool>
|
9 |
+
<inspection_tool class="PyInterpreterInspection" enabled="false" level="WARNING" enabled_by_default="false" />
|
10 |
+
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
11 |
+
<option name="ignoredPackages">
|
12 |
+
<value>
|
13 |
+
<list size="3">
|
14 |
+
<item index="0" class="java.lang.String" itemvalue="Tensorflow" />
|
15 |
+
<item index="1" class="java.lang.String" itemvalue="Sklearn" />
|
16 |
+
<item index="2" class="java.lang.String" itemvalue="Opencv" />
|
17 |
+
</list>
|
18 |
+
</value>
|
19 |
+
</option>
|
20 |
+
</inspection_tool>
|
21 |
+
<inspection_tool class="PyPep8Inspection" enabled="true" level="WEAK WARNING" enabled_by_default="true">
|
22 |
+
<option name="ignoredErrors">
|
23 |
+
<list>
|
24 |
+
<option value="E501" />
|
25 |
+
</list>
|
26 |
+
</option>
|
27 |
+
</inspection_tool>
|
28 |
+
</profile>
|
29 |
+
</component>
|
screencoder/UIED/.idea/misc.xml
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6" project-jdk-type="Python SDK" />
|
4 |
+
</project>
|
screencoder/UIED/.idea/modules.xml
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="ProjectModuleManager">
|
4 |
+
<modules>
|
5 |
+
<module fileurl="file://$PROJECT_DIR$/.idea/UIED.iml" filepath="$PROJECT_DIR$/.idea/UIED.iml" />
|
6 |
+
</modules>
|
7 |
+
</component>
|
8 |
+
</project>
|
screencoder/UIED/.idea/vcs.xml
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="VcsDirectoryMappings">
|
4 |
+
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
5 |
+
</component>
|
6 |
+
</project>
|
screencoder/UIED/.idea/workspace.xml
ADDED
@@ -0,0 +1,336 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<?xml version="1.0" encoding="UTF-8"?>
|
2 |
+
<project version="4">
|
3 |
+
<component name="AutoImportSettings">
|
4 |
+
<option name="autoReloadType" value="SELECTIVE" />
|
5 |
+
</component>
|
6 |
+
<component name="ChangeListManager">
|
7 |
+
<list default="true" id="b4069649-920d-465f-ac6b-bac85007c2bb" name="Default" comment="">
|
8 |
+
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
9 |
+
</list>
|
10 |
+
<option name="SHOW_DIALOG" value="false" />
|
11 |
+
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
12 |
+
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
13 |
+
<option name="LAST_RESOLUTION" value="IGNORE" />
|
14 |
+
</component>
|
15 |
+
<component name="FileTemplateManagerImpl">
|
16 |
+
<option name="RECENT_TEMPLATES">
|
17 |
+
<list>
|
18 |
+
<option value="Python Script" />
|
19 |
+
</list>
|
20 |
+
</option>
|
21 |
+
</component>
|
22 |
+
<component name="Git.Settings">
|
23 |
+
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
24 |
+
</component>
|
25 |
+
<component name="JupyterTrust" id="2ce0fe3c-0081-4dca-a6a6-b1219d650764" />
|
26 |
+
<component name="ProjectId" id="1dwCihBTog6GQX95sgxr7TpM6ZO" />
|
27 |
+
<component name="ProjectLevelVcsManager">
|
28 |
+
<ConfirmationsSetting value="2" id="Add" />
|
29 |
+
</component>
|
30 |
+
<component name="ProjectViewState">
|
31 |
+
<option name="hideEmptyMiddlePackages" value="true" />
|
32 |
+
<option name="showLibraryContents" value="true" />
|
33 |
+
<option name="showMembers" value="true" />
|
34 |
+
</component>
|
35 |
+
<component name="PropertiesComponent">
|
36 |
+
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
|
37 |
+
<property name="RunOnceActivity.ShowReadmeOnStart" value="true" />
|
38 |
+
<property name="WebServerToolWindowFactoryState" value="false" />
|
39 |
+
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
40 |
+
<property name="node.js.detected.package.eslint" value="true" />
|
41 |
+
<property name="node.js.detected.package.tslint" value="true" />
|
42 |
+
<property name="node.js.path.for.package.eslint" value="project" />
|
43 |
+
<property name="node.js.path.for.package.tslint" value="project" />
|
44 |
+
<property name="node.js.selected.package.eslint" value="(autodetect)" />
|
45 |
+
<property name="node.js.selected.package.tslint" value="(autodetect)" />
|
46 |
+
<property name="restartRequiresConfirmation" value="false" />
|
47 |
+
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
|
48 |
+
<property name="two.files.diff.last.used.file" value="$PROJECT_DIR$/../UI2CODE/Element-Detection/merge.py" />
|
49 |
+
</component>
|
50 |
+
<component name="RecentsManager">
|
51 |
+
<key name="CopyFile.RECENT_KEYS">
|
52 |
+
<recent name="D:\git_file\github\doing\UIED\data\demo" />
|
53 |
+
</key>
|
54 |
+
<key name="MoveFile.RECENT_KEYS">
|
55 |
+
<recent name="D:\git_file\github\doing\UIED\detect_compo" />
|
56 |
+
<recent name="D:\git_file\github\doing\UIED\detect_compo\deprecated" />
|
57 |
+
<recent name="D:\git_file\github\doing\UIED\utils" />
|
58 |
+
<recent name="D:\git_file\github\doing\UIED" />
|
59 |
+
<recent name="D:\git_file\github\doing\UIED\result_processing" />
|
60 |
+
</key>
|
61 |
+
</component>
|
62 |
+
<component name="RunManager" selected="Python.run_single">
|
63 |
+
<configuration name="merge" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
64 |
+
<module name="UIED" />
|
65 |
+
<option name="INTERPRETER_OPTIONS" value="" />
|
66 |
+
<option name="PARENT_ENVS" value="true" />
|
67 |
+
<envs>
|
68 |
+
<env name="PYTHONUNBUFFERED" value="1" />
|
69 |
+
</envs>
|
70 |
+
<option name="SDK_HOME" value="" />
|
71 |
+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/detect_merge" />
|
72 |
+
<option name="IS_MODULE_SDK" value="true" />
|
73 |
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
74 |
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
75 |
+
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
76 |
+
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/detect_merge/merge.py" />
|
77 |
+
<option name="PARAMETERS" value="" />
|
78 |
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
79 |
+
<option name="EMULATE_TERMINAL" value="false" />
|
80 |
+
<option name="MODULE_MODE" value="false" />
|
81 |
+
<option name="REDIRECT_INPUT" value="false" />
|
82 |
+
<option name="INPUT_FILE" value="" />
|
83 |
+
<method v="2" />
|
84 |
+
</configuration>
|
85 |
+
<configuration name="merge2" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
86 |
+
<module name="UIED" />
|
87 |
+
<option name="INTERPRETER_OPTIONS" value="" />
|
88 |
+
<option name="PARENT_ENVS" value="true" />
|
89 |
+
<envs>
|
90 |
+
<env name="PYTHONUNBUFFERED" value="1" />
|
91 |
+
</envs>
|
92 |
+
<option name="SDK_HOME" value="" />
|
93 |
+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
94 |
+
<option name="IS_MODULE_SDK" value="true" />
|
95 |
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
96 |
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
97 |
+
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
98 |
+
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/merge2.py" />
|
99 |
+
<option name="PARAMETERS" value="" />
|
100 |
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
101 |
+
<option name="EMULATE_TERMINAL" value="false" />
|
102 |
+
<option name="MODULE_MODE" value="false" />
|
103 |
+
<option name="REDIRECT_INPUT" value="false" />
|
104 |
+
<option name="INPUT_FILE" value="" />
|
105 |
+
<method v="2" />
|
106 |
+
</configuration>
|
107 |
+
<configuration name="run_single" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
108 |
+
<module name="UIED" />
|
109 |
+
<option name="INTERPRETER_OPTIONS" value="" />
|
110 |
+
<option name="PARENT_ENVS" value="true" />
|
111 |
+
<envs>
|
112 |
+
<env name="PYTHONUNBUFFERED" value="1" />
|
113 |
+
</envs>
|
114 |
+
<option name="SDK_HOME" value="" />
|
115 |
+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
116 |
+
<option name="IS_MODULE_SDK" value="true" />
|
117 |
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
118 |
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
119 |
+
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
120 |
+
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/run_single.py" />
|
121 |
+
<option name="PARAMETERS" value="" />
|
122 |
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
123 |
+
<option name="EMULATE_TERMINAL" value="false" />
|
124 |
+
<option name="MODULE_MODE" value="false" />
|
125 |
+
<option name="REDIRECT_INPUT" value="false" />
|
126 |
+
<option name="INPUT_FILE" value="" />
|
127 |
+
<method v="2" />
|
128 |
+
</configuration>
|
129 |
+
<configuration name="run_testing(Used for Adjusting)" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
130 |
+
<module name="UIED" />
|
131 |
+
<option name="INTERPRETER_OPTIONS" value="" />
|
132 |
+
<option name="PARENT_ENVS" value="true" />
|
133 |
+
<envs>
|
134 |
+
<env name="PYTHONUNBUFFERED" value="1" />
|
135 |
+
</envs>
|
136 |
+
<option name="SDK_HOME" value="" />
|
137 |
+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
138 |
+
<option name="IS_MODULE_SDK" value="true" />
|
139 |
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
140 |
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
141 |
+
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
142 |
+
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/run_testing(Used for Adjusting).py" />
|
143 |
+
<option name="PARAMETERS" value="" />
|
144 |
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
145 |
+
<option name="EMULATE_TERMINAL" value="false" />
|
146 |
+
<option name="MODULE_MODE" value="false" />
|
147 |
+
<option name="REDIRECT_INPUT" value="false" />
|
148 |
+
<option name="INPUT_FILE" value="" />
|
149 |
+
<method v="2" />
|
150 |
+
</configuration>
|
151 |
+
<configuration name="text_detection" type="PythonConfigurationType" factoryName="Python" temporary="true" nameIsGenerated="true">
|
152 |
+
<module name="UIED" />
|
153 |
+
<option name="INTERPRETER_OPTIONS" value="" />
|
154 |
+
<option name="PARENT_ENVS" value="true" />
|
155 |
+
<envs>
|
156 |
+
<env name="PYTHONUNBUFFERED" value="1" />
|
157 |
+
</envs>
|
158 |
+
<option name="SDK_HOME" value="" />
|
159 |
+
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/detect_text" />
|
160 |
+
<option name="IS_MODULE_SDK" value="true" />
|
161 |
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
162 |
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
163 |
+
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
164 |
+
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/detect_text/text_detection.py" />
|
165 |
+
<option name="PARAMETERS" value="" />
|
166 |
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
167 |
+
<option name="EMULATE_TERMINAL" value="false" />
|
168 |
+
<option name="MODULE_MODE" value="false" />
|
169 |
+
<option name="REDIRECT_INPUT" value="false" />
|
170 |
+
<option name="INPUT_FILE" value="" />
|
171 |
+
<method v="2" />
|
172 |
+
</configuration>
|
173 |
+
<list>
|
174 |
+
<item itemvalue="Python.merge2" />
|
175 |
+
<item itemvalue="Python.merge" />
|
176 |
+
<item itemvalue="Python.run_single" />
|
177 |
+
<item itemvalue="Python.run_testing(Used for Adjusting)" />
|
178 |
+
<item itemvalue="Python.text_detection" />
|
179 |
+
</list>
|
180 |
+
<recent_temporary>
|
181 |
+
<list>
|
182 |
+
<item itemvalue="Python.run_single" />
|
183 |
+
<item itemvalue="Python.run_testing(Used for Adjusting)" />
|
184 |
+
<item itemvalue="Python.merge" />
|
185 |
+
<item itemvalue="Python.merge2" />
|
186 |
+
<item itemvalue="Python.text_detection" />
|
187 |
+
</list>
|
188 |
+
</recent_temporary>
|
189 |
+
</component>
|
190 |
+
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
191 |
+
<component name="SvnConfiguration">
|
192 |
+
<configuration />
|
193 |
+
</component>
|
194 |
+
<component name="TaskManager">
|
195 |
+
<task active="true" id="Default" summary="Default task">
|
196 |
+
<changelist id="b4069649-920d-465f-ac6b-bac85007c2bb" name="Default" comment="" />
|
197 |
+
<created>1581826543105</created>
|
198 |
+
<option name="number" value="Default" />
|
199 |
+
<option name="presentableId" value="Default" />
|
200 |
+
<updated>1581826543105</updated>
|
201 |
+
<workItem from="1593326898629" duration="4378000" />
|
202 |
+
<workItem from="1594035929667" duration="39000" />
|
203 |
+
<workItem from="1594085137817" duration="1275000" />
|
204 |
+
<workItem from="1594100418101" duration="3473000" />
|
205 |
+
<workItem from="1594163935256" duration="1077000" />
|
206 |
+
<workItem from="1594182213679" duration="2275000" />
|
207 |
+
<workItem from="1595462115111" duration="3597000" />
|
208 |
+
<workItem from="1595466120556" duration="3158000" />
|
209 |
+
<workItem from="1595488240502" duration="74000" />
|
210 |
+
<workItem from="1595723287741" duration="773000" />
|
211 |
+
<workItem from="1596417993986" duration="2972000" />
|
212 |
+
<workItem from="1596442796733" duration="9601000" />
|
213 |
+
<workItem from="1596604406529" duration="10000" />
|
214 |
+
<workItem from="1596685531295" duration="1526000" />
|
215 |
+
<workItem from="1596792120495" duration="27485000" />
|
216 |
+
<workItem from="1596926803756" duration="894000" />
|
217 |
+
<workItem from="1596955557805" duration="717000" />
|
218 |
+
<workItem from="1597015667916" duration="1488000" />
|
219 |
+
<workItem from="1598487885922" duration="962000" />
|
220 |
+
<workItem from="1601609000493" duration="599000" />
|
221 |
+
<workItem from="1601849117964" duration="1226000" />
|
222 |
+
<workItem from="1601850762269" duration="6477000" />
|
223 |
+
<workItem from="1601933366434" duration="6847000" />
|
224 |
+
<workItem from="1602130037944" duration="4303000" />
|
225 |
+
<workItem from="1602199380249" duration="5493000" />
|
226 |
+
<workItem from="1603669721746" duration="6042000" />
|
227 |
+
<workItem from="1604011435077" duration="517000" />
|
228 |
+
<workItem from="1604016832655" duration="5114000" />
|
229 |
+
<workItem from="1604037397074" duration="12109000" />
|
230 |
+
<workItem from="1604564719252" duration="1133000" />
|
231 |
+
<workItem from="1604619358289" duration="17569000" />
|
232 |
+
<workItem from="1604874207809" duration="171000" />
|
233 |
+
<workItem from="1605071062104" duration="3079000" />
|
234 |
+
<workItem from="1605086142565" duration="6397000" />
|
235 |
+
<workItem from="1625010508533" duration="4541000" />
|
236 |
+
<workItem from="1625099073176" duration="49720000" />
|
237 |
+
<workItem from="1625443415902" duration="26350000" />
|
238 |
+
<workItem from="1625529598285" duration="26479000" />
|
239 |
+
<workItem from="1625613709029" duration="14000" />
|
240 |
+
<workItem from="1625730508694" duration="928000" />
|
241 |
+
<workItem from="1625809233064" duration="837000" />
|
242 |
+
<workItem from="1626009011038" duration="18000" />
|
243 |
+
<workItem from="1626307428798" duration="1983000" />
|
244 |
+
<workItem from="1628054466383" duration="1894000" />
|
245 |
+
<workItem from="1628122812217" duration="7049000" />
|
246 |
+
<workItem from="1630237947629" duration="453000" />
|
247 |
+
<workItem from="1630268189943" duration="20000" />
|
248 |
+
<workItem from="1630297231550" duration="5710000" />
|
249 |
+
<workItem from="1630312264694" duration="7894000" />
|
250 |
+
<workItem from="1631149307515" duration="752000" />
|
251 |
+
<workItem from="1631576239206" duration="805000" />
|
252 |
+
<workItem from="1631584649434" duration="2272000" />
|
253 |
+
<workItem from="1648024033251" duration="1883000" />
|
254 |
+
</task>
|
255 |
+
<servers />
|
256 |
+
</component>
|
257 |
+
<component name="TestHistory">
|
258 |
+
<history-entry file="py_test_in_test_lucky_py - 2020.03.04 at 05h 51m 04s.xml">
|
259 |
+
<configuration name="py.test in test_lucky.py" configurationId="tests" />
|
260 |
+
</history-entry>
|
261 |
+
</component>
|
262 |
+
<component name="TypeScriptGeneratedFilesManager">
|
263 |
+
<option name="version" value="3" />
|
264 |
+
</component>
|
265 |
+
<component name="XDebuggerManager">
|
266 |
+
<breakpoint-manager>
|
267 |
+
<breakpoints>
|
268 |
+
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
269 |
+
<url />
|
270 |
+
<line>147</line>
|
271 |
+
<option name="timeStamp" value="3" />
|
272 |
+
</line-breakpoint>
|
273 |
+
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
274 |
+
<url />
|
275 |
+
<line>134</line>
|
276 |
+
<option name="timeStamp" value="4" />
|
277 |
+
</line-breakpoint>
|
278 |
+
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
279 |
+
<url />
|
280 |
+
<line>135</line>
|
281 |
+
<option name="timeStamp" value="5" />
|
282 |
+
</line-breakpoint>
|
283 |
+
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
284 |
+
<url />
|
285 |
+
<line>136</line>
|
286 |
+
<option name="timeStamp" value="6" />
|
287 |
+
</line-breakpoint>
|
288 |
+
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
289 |
+
<url>file://$PROJECT_DIR$/detect_text_east/lib_east/eval.py</url>
|
290 |
+
<line>263</line>
|
291 |
+
<option name="timeStamp" value="67" />
|
292 |
+
</line-breakpoint>
|
293 |
+
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
294 |
+
<url>file://$PROJECT_DIR$/result_processing/eval_classes.py</url>
|
295 |
+
<line>92</line>
|
296 |
+
<option name="timeStamp" value="92" />
|
297 |
+
</line-breakpoint>
|
298 |
+
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
299 |
+
<url>file://$PROJECT_DIR$/detect_text_east/lib_east/eval.py</url>
|
300 |
+
<line>108</line>
|
301 |
+
<option name="timeStamp" value="93" />
|
302 |
+
</line-breakpoint>
|
303 |
+
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
304 |
+
<url>file://$PROJECT_DIR$/cnn/CNN.py</url>
|
305 |
+
<line>62</line>
|
306 |
+
<option name="timeStamp" value="94" />
|
307 |
+
</line-breakpoint>
|
308 |
+
<line-breakpoint enabled="true" suspend="THREAD" type="python-line">
|
309 |
+
<url>file://$PROJECT_DIR$/run_single.py</url>
|
310 |
+
<line>27</line>
|
311 |
+
<option name="timeStamp" value="101" />
|
312 |
+
</line-breakpoint>
|
313 |
+
</breakpoints>
|
314 |
+
<default-breakpoints>
|
315 |
+
<breakpoint type="python-exception">
|
316 |
+
<properties notifyOnTerminate="true" exception="BaseException">
|
317 |
+
<option name="notifyOnTerminate" value="true" />
|
318 |
+
</properties>
|
319 |
+
</breakpoint>
|
320 |
+
</default-breakpoints>
|
321 |
+
</breakpoint-manager>
|
322 |
+
</component>
|
323 |
+
<component name="com.intellij.coverage.CoverageDataManagerImpl">
|
324 |
+
<SUITE FILE_PATH="coverage/UIED$view_gt.coverage" NAME="view_gt Coverage Results" MODIFIED="1596418105849" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/result_processing" />
|
325 |
+
<SUITE FILE_PATH="coverage/UIED$run_single.coverage" NAME="run_single Coverage Results" MODIFIED="1648024874423" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
326 |
+
<SUITE FILE_PATH="coverage/UIED$main_single.coverage" NAME="main_single Coverage Results" MODIFIED="1594102734340" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
327 |
+
<SUITE FILE_PATH="coverage/UIED$run_batch.coverage" NAME="run_batch Coverage Results" MODIFIED="1596448499254" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
328 |
+
<SUITE FILE_PATH="coverage/UIED_block$main_single.coverage" NAME="main_single Coverage Results" MODIFIED="1594035942350" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
329 |
+
<SUITE FILE_PATH="coverage/UIED$run_testing_Used_for_Adjusting_.coverage" NAME="run_testing(Used for Adjusting) Coverage Results" MODIFIED="1631149318891" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
330 |
+
<SUITE FILE_PATH="coverage/UIED$merge2.coverage" NAME="merge2 Coverage Results" MODIFIED="1625271385465" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
331 |
+
<SUITE FILE_PATH="coverage/UIED$run_testing_Use_Me_for_Adjusting_.coverage" NAME="run_testing(Use Me for Adjusting) Coverage Results" MODIFIED="1605091364353" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$" />
|
332 |
+
<SUITE FILE_PATH="coverage/UIED$text_detection.coverage" NAME="text_detection Coverage Results" MODIFIED="1625107691453" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/detect_text" />
|
333 |
+
<SUITE FILE_PATH="coverage/UIED$merge.coverage" NAME="merge Coverage Results" MODIFIED="1625284362497" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/detect_merge" />
|
334 |
+
<SUITE FILE_PATH="coverage/UIED$experiment.coverage" NAME="experiment Coverage Results" MODIFIED="1605087951044" SOURCE_PROVIDER="com.intellij.coverage.DefaultCoverageFileProvider" RUNNER="coverage.py" COVERAGE_BY_TEST_ENABLED="true" COVERAGE_TRACING_ENABLED="false" WORKING_DIRECTORY="$PROJECT_DIR$/result_processing" />
|
335 |
+
</component>
|
336 |
+
</project>
|
screencoder/UIED/LICENSE
ADDED
@@ -0,0 +1,201 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Apache License
|
2 |
+
Version 2.0, January 2004
|
3 |
+
http://www.apache.org/licenses/
|
4 |
+
|
5 |
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
6 |
+
|
7 |
+
1. Definitions.
|
8 |
+
|
9 |
+
"License" shall mean the terms and conditions for use, reproduction,
|
10 |
+
and distribution as defined by Sections 1 through 9 of this document.
|
11 |
+
|
12 |
+
"Licensor" shall mean the copyright owner or entity authorized by
|
13 |
+
the copyright owner that is granting the License.
|
14 |
+
|
15 |
+
"Legal Entity" shall mean the union of the acting entity and all
|
16 |
+
other entities that control, are controlled by, or are under common
|
17 |
+
control with that entity. For the purposes of this definition,
|
18 |
+
"control" means (i) the power, direct or indirect, to cause the
|
19 |
+
direction or management of such entity, whether by contract or
|
20 |
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
21 |
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
22 |
+
|
23 |
+
"You" (or "Your") shall mean an individual or Legal Entity
|
24 |
+
exercising permissions granted by this License.
|
25 |
+
|
26 |
+
"Source" form shall mean the preferred form for making modifications,
|
27 |
+
including but not limited to software source code, documentation
|
28 |
+
source, and configuration files.
|
29 |
+
|
30 |
+
"Object" form shall mean any form resulting from mechanical
|
31 |
+
transformation or translation of a Source form, including but
|
32 |
+
not limited to compiled object code, generated documentation,
|
33 |
+
and conversions to other media types.
|
34 |
+
|
35 |
+
"Work" shall mean the work of authorship, whether in Source or
|
36 |
+
Object form, made available under the License, as indicated by a
|
37 |
+
copyright notice that is included in or attached to the work
|
38 |
+
(an example is provided in the Appendix below).
|
39 |
+
|
40 |
+
"Derivative Works" shall mean any work, whether in Source or Object
|
41 |
+
form, that is based on (or derived from) the Work and for which the
|
42 |
+
editorial revisions, annotations, elaborations, or other modifications
|
43 |
+
represent, as a whole, an original work of authorship. For the purposes
|
44 |
+
of this License, Derivative Works shall not include works that remain
|
45 |
+
separable from, or merely link (or bind by name) to the interfaces of,
|
46 |
+
the Work and Derivative Works thereof.
|
47 |
+
|
48 |
+
"Contribution" shall mean any work of authorship, including
|
49 |
+
the original version of the Work and any modifications or additions
|
50 |
+
to that Work or Derivative Works thereof, that is intentionally
|
51 |
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
52 |
+
or by an individual or Legal Entity authorized to submit on behalf of
|
53 |
+
the copyright owner. For the purposes of this definition, "submitted"
|
54 |
+
means any form of electronic, verbal, or written communication sent
|
55 |
+
to the Licensor or its representatives, including but not limited to
|
56 |
+
communication on electronic mailing lists, source code control systems,
|
57 |
+
and issue tracking systems that are managed by, or on behalf of, the
|
58 |
+
Licensor for the purpose of discussing and improving the Work, but
|
59 |
+
excluding communication that is conspicuously marked or otherwise
|
60 |
+
designated in writing by the copyright owner as "Not a Contribution."
|
61 |
+
|
62 |
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
63 |
+
on behalf of whom a Contribution has been received by Licensor and
|
64 |
+
subsequently incorporated within the Work.
|
65 |
+
|
66 |
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
67 |
+
this License, each Contributor hereby grants to You a perpetual,
|
68 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
69 |
+
copyright license to reproduce, prepare Derivative Works of,
|
70 |
+
publicly display, publicly perform, sublicense, and distribute the
|
71 |
+
Work and such Derivative Works in Source or Object form.
|
72 |
+
|
73 |
+
3. Grant of Patent License. Subject to the terms and conditions of
|
74 |
+
this License, each Contributor hereby grants to You a perpetual,
|
75 |
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
76 |
+
(except as stated in this section) patent license to make, have made,
|
77 |
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
78 |
+
where such license applies only to those patent claims licensable
|
79 |
+
by such Contributor that are necessarily infringed by their
|
80 |
+
Contribution(s) alone or by combination of their Contribution(s)
|
81 |
+
with the Work to which such Contribution(s) was submitted. If You
|
82 |
+
institute patent litigation against any entity (including a
|
83 |
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
84 |
+
or a Contribution incorporated within the Work constitutes direct
|
85 |
+
or contributory patent infringement, then any patent licenses
|
86 |
+
granted to You under this License for that Work shall terminate
|
87 |
+
as of the date such litigation is filed.
|
88 |
+
|
89 |
+
4. Redistribution. You may reproduce and distribute copies of the
|
90 |
+
Work or Derivative Works thereof in any medium, with or without
|
91 |
+
modifications, and in Source or Object form, provided that You
|
92 |
+
meet the following conditions:
|
93 |
+
|
94 |
+
(a) You must give any other recipients of the Work or
|
95 |
+
Derivative Works a copy of this License; and
|
96 |
+
|
97 |
+
(b) You must cause any modified files to carry prominent notices
|
98 |
+
stating that You changed the files; and
|
99 |
+
|
100 |
+
(c) You must retain, in the Source form of any Derivative Works
|
101 |
+
that You distribute, all copyright, patent, trademark, and
|
102 |
+
attribution notices from the Source form of the Work,
|
103 |
+
excluding those notices that do not pertain to any part of
|
104 |
+
the Derivative Works; and
|
105 |
+
|
106 |
+
(d) If the Work includes a "NOTICE" text file as part of its
|
107 |
+
distribution, then any Derivative Works that You distribute must
|
108 |
+
include a readable copy of the attribution notices contained
|
109 |
+
within such NOTICE file, excluding those notices that do not
|
110 |
+
pertain to any part of the Derivative Works, in at least one
|
111 |
+
of the following places: within a NOTICE text file distributed
|
112 |
+
as part of the Derivative Works; within the Source form or
|
113 |
+
documentation, if provided along with the Derivative Works; or,
|
114 |
+
within a display generated by the Derivative Works, if and
|
115 |
+
wherever such third-party notices normally appear. The contents
|
116 |
+
of the NOTICE file are for informational purposes only and
|
117 |
+
do not modify the License. You may add Your own attribution
|
118 |
+
notices within Derivative Works that You distribute, alongside
|
119 |
+
or as an addendum to the NOTICE text from the Work, provided
|
120 |
+
that such additional attribution notices cannot be construed
|
121 |
+
as modifying the License.
|
122 |
+
|
123 |
+
You may add Your own copyright statement to Your modifications and
|
124 |
+
may provide additional or different license terms and conditions
|
125 |
+
for use, reproduction, or distribution of Your modifications, or
|
126 |
+
for any such Derivative Works as a whole, provided Your use,
|
127 |
+
reproduction, and distribution of the Work otherwise complies with
|
128 |
+
the conditions stated in this License.
|
129 |
+
|
130 |
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
131 |
+
any Contribution intentionally submitted for inclusion in the Work
|
132 |
+
by You to the Licensor shall be under the terms and conditions of
|
133 |
+
this License, without any additional terms or conditions.
|
134 |
+
Notwithstanding the above, nothing herein shall supersede or modify
|
135 |
+
the terms of any separate license agreement you may have executed
|
136 |
+
with Licensor regarding such Contributions.
|
137 |
+
|
138 |
+
6. Trademarks. This License does not grant permission to use the trade
|
139 |
+
names, trademarks, service marks, or product names of the Licensor,
|
140 |
+
except as required for reasonable and customary use in describing the
|
141 |
+
origin of the Work and reproducing the content of the NOTICE file.
|
142 |
+
|
143 |
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
144 |
+
agreed to in writing, Licensor provides the Work (and each
|
145 |
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
146 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
147 |
+
implied, including, without limitation, any warranties or conditions
|
148 |
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
149 |
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
150 |
+
appropriateness of using or redistributing the Work and assume any
|
151 |
+
risks associated with Your exercise of permissions under this License.
|
152 |
+
|
153 |
+
8. Limitation of Liability. In no event and under no legal theory,
|
154 |
+
whether in tort (including negligence), contract, or otherwise,
|
155 |
+
unless required by applicable law (such as deliberate and grossly
|
156 |
+
negligent acts) or agreed to in writing, shall any Contributor be
|
157 |
+
liable to You for damages, including any direct, indirect, special,
|
158 |
+
incidental, or consequential damages of any character arising as a
|
159 |
+
result of this License or out of the use or inability to use the
|
160 |
+
Work (including but not limited to damages for loss of goodwill,
|
161 |
+
work stoppage, computer failure or malfunction, or any and all
|
162 |
+
other commercial damages or losses), even if such Contributor
|
163 |
+
has been advised of the possibility of such damages.
|
164 |
+
|
165 |
+
9. Accepting Warranty or Additional Liability. While redistributing
|
166 |
+
the Work or Derivative Works thereof, You may choose to offer,
|
167 |
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
168 |
+
or other liability obligations and/or rights consistent with this
|
169 |
+
License. However, in accepting such obligations, You may act only
|
170 |
+
on Your own behalf and on Your sole responsibility, not on behalf
|
171 |
+
of any other Contributor, and only if You agree to indemnify,
|
172 |
+
defend, and hold each Contributor harmless for any liability
|
173 |
+
incurred by, or claims asserted against, such Contributor by reason
|
174 |
+
of your accepting any such warranty or additional liability.
|
175 |
+
|
176 |
+
END OF TERMS AND CONDITIONS
|
177 |
+
|
178 |
+
APPENDIX: How to apply the Apache License to your work.
|
179 |
+
|
180 |
+
To apply the Apache License to your work, attach the following
|
181 |
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
182 |
+
replaced with your own identifying information. (Don't include
|
183 |
+
the brackets!) The text should be enclosed in the appropriate
|
184 |
+
comment syntax for the file format. We also recommend that a
|
185 |
+
file or class name and description of purpose be included on the
|
186 |
+
same "printed page" as the copyright notice for easier
|
187 |
+
identification within third-party archives.
|
188 |
+
|
189 |
+
Copyright [2021] [UIED [email protected]]
|
190 |
+
|
191 |
+
Licensed under the Apache License, Version 2.0 (the "License");
|
192 |
+
you may not use this file except in compliance with the License.
|
193 |
+
You may obtain a copy of the License at
|
194 |
+
|
195 |
+
http://www.apache.org/licenses/LICENSE-2.0
|
196 |
+
|
197 |
+
Unless required by applicable law or agreed to in writing, software
|
198 |
+
distributed under the License is distributed on an "AS IS" BASIS,
|
199 |
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
200 |
+
See the License for the specific language governing permissions and
|
201 |
+
limitations under the License.
|
screencoder/UIED/README.md
ADDED
@@ -0,0 +1,80 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# UIED - UI element detection, detecting UI elements from UI screenshots or drawnings
|
2 |
+
|
3 |
+
This project is still ongoing and this repo may be updated irregularly, I developed a web app for the UIED in http://uied.online
|
4 |
+
|
5 |
+
## Related Publications:
|
6 |
+
[1. UIED: a hybrid tool for GUI element detection](https://dl.acm.org/doi/10.1145/3368089.3417940)
|
7 |
+
|
8 |
+
[2. Object Detection for Graphical User Interface: Old Fashioned or Deep Learning or a Combination?](https://arxiv.org/abs/2008.05132)
|
9 |
+
|
10 |
+
>The repo has been **upgraded with Google OCR** for GUI text detection, to use the original version in our paper (using [EAST](https://github.com/argman/EAST) as text detector), check the relase [v2.3](https://github.com/MulongXie/UIED/releases/tag/v2.3) and download the pre-trained model in [this link](https://drive.google.com/drive/folders/1MK0Om7Lx0wRXGDfNcyj21B0FL1T461v5?usp=sharing).
|
11 |
+
|
12 |
+
## What is it?
|
13 |
+
|
14 |
+
UI Element Detection (UIED) is an old-fashioned computer vision (CV) based element detection approach for graphic user interface.
|
15 |
+
|
16 |
+
The input of UIED could be various UI image, such as mobile app or web page screenshot, UI design drawn by Photoshop or Sketch, and even some hand-drawn UI design. Then the approach detects and classifies text and graphic UI elements, and exports the detection result as JSON file for future application.
|
17 |
+
|
18 |
+
UIED comprises two parts to detect UI text and graphic elements, such as button, image and input bar.
|
19 |
+
* For text, it leverages [Google OCR](https://cloud.google.com/vision/docs/ocr) to perfrom detection.
|
20 |
+
|
21 |
+
* For graphical elements, it uses old-fashioned CV approaches to locate the elements and a CNN classifier to achieve classification.
|
22 |
+
|
23 |
+
> UIED is highly customizable, you can replace both parts by your choice (e.g. other text detection approaches). Unlike black-box end-to-end deep learning approach, you can revise the algorithms in the non-text detection and merging (partially or entirely) easily to fit your task.
|
24 |
+
|
25 |
+

|
26 |
+
|
27 |
+
## How to use?
|
28 |
+
|
29 |
+
### Dependency
|
30 |
+
* **Python 3.5**
|
31 |
+
* **Opencv 3.4.2**
|
32 |
+
* **Pandas**
|
33 |
+
<!-- * **Tensorflow 1.10.0**
|
34 |
+
* **Keras 2.2.4**
|
35 |
+
* **Sklearn 0.22.2** -->
|
36 |
+
|
37 |
+
### Installation
|
38 |
+
<!-- Install the mentioned dependencies, and download two pre-trained models from [this link](https://drive.google.com/drive/folders/1MK0Om7Lx0wRXGDfNcyj21B0FL1T461v5?usp=sharing) for EAST text detection and GUI element classification. -->
|
39 |
+
|
40 |
+
<!-- Change ``CNN_PATH`` and ``EAST_PATH`` in *config/CONFIG.py* to your locations. -->
|
41 |
+
|
42 |
+
The new version of UIED equipped with Google OCR is easy to deploy and no pre-trained model is needed. Simply donwload the repo along with the dependencies.
|
43 |
+
|
44 |
+
> Please replace the Google OCR key at `detect_text/ocr.py line 28` with your own (apply in [Google website](https://cloud.google.com/vision)).
|
45 |
+
|
46 |
+
### Usage
|
47 |
+
To test your own image(s):
|
48 |
+
* To test single image, change *input_path_img* in ``run_single.py`` to your input image and the results will be output to *output_root*.
|
49 |
+
* To test mutiple images, change *input_img_root* in ``run_batch.py`` to your input directory and the results will be output to *output_root*.
|
50 |
+
* To adjust the parameters lively, using ``run_testing.py``
|
51 |
+
|
52 |
+
> Note: The best set of parameters vary for different types of GUI image (Mobile App, Web, PC). I highly recommend to first play with the ``run_testing.py`` to pick a good set of parameters for your data.
|
53 |
+
|
54 |
+
## Folder structure
|
55 |
+
``cnn/``
|
56 |
+
* Used to train classifier for graphic UI elements
|
57 |
+
* Set path of the CNN classification model
|
58 |
+
|
59 |
+
``config/``
|
60 |
+
* Set data paths
|
61 |
+
* Set parameters for graphic elements detection
|
62 |
+
|
63 |
+
``data/``
|
64 |
+
* Input UI images and output detection results
|
65 |
+
|
66 |
+
``detect_compo/``
|
67 |
+
* Non-text GUI component detection
|
68 |
+
|
69 |
+
``detect_text/``
|
70 |
+
* GUI text detection using Google OCR
|
71 |
+
|
72 |
+
``detect_merge/``
|
73 |
+
* Merge the detection results of non-text and text GUI elements
|
74 |
+
|
75 |
+
The major detection algorithms are in ``detect_compo/``, ``detect_text/`` and ``detect_merge/``
|
76 |
+
|
77 |
+
## Demo
|
78 |
+
GUI element detection result for web screenshot
|
79 |
+
|
80 |
+

|
screencoder/UIED/cnn/CNN.py
ADDED
@@ -0,0 +1,125 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import keras
|
2 |
+
from keras.applications.resnet50 import ResNet50
|
3 |
+
from keras.models import Model,load_model
|
4 |
+
from keras.layers import Dense, Activation, Flatten, Dropout
|
5 |
+
from sklearn.metrics import confusion_matrix
|
6 |
+
import numpy as np
|
7 |
+
import cv2
|
8 |
+
|
9 |
+
from config.CONFIG import Config
|
10 |
+
cfg = Config()
|
11 |
+
|
12 |
+
|
13 |
+
class CNN:
|
14 |
+
def __init__(self, classifier_type, is_load=True):
|
15 |
+
'''
|
16 |
+
:param classifier_type: 'Text' or 'Noise' or 'Elements'
|
17 |
+
'''
|
18 |
+
self.data = None
|
19 |
+
self.model = None
|
20 |
+
|
21 |
+
self.classifier_type = classifier_type
|
22 |
+
|
23 |
+
self.image_shape = (32,32,3)
|
24 |
+
self.class_number = None
|
25 |
+
self.class_map = None
|
26 |
+
self.model_path = None
|
27 |
+
self.classifier_type = classifier_type
|
28 |
+
if is_load:
|
29 |
+
self.load(classifier_type)
|
30 |
+
|
31 |
+
def build_model(self, epoch_num, is_compile=True):
|
32 |
+
base_model = ResNet50(include_top=False, weights='imagenet', input_shape=self.image_shape)
|
33 |
+
for layer in base_model.layers:
|
34 |
+
layer.trainable = False
|
35 |
+
self.model = Flatten()(base_model.output)
|
36 |
+
self.model = Dense(128, activation='relu')(self.model)
|
37 |
+
self.model = Dropout(0.5)(self.model)
|
38 |
+
self.model = Dense(15, activation='softmax')(self.model)
|
39 |
+
|
40 |
+
self.model = Model(inputs=base_model.input, outputs=self.model)
|
41 |
+
if is_compile:
|
42 |
+
self.model.compile(loss='categorical_crossentropy', optimizer='adadelta', metrics=['accuracy'])
|
43 |
+
self.model.fit(self.data.X_train, self.data.Y_train, batch_size=64, epochs=epoch_num, verbose=1,
|
44 |
+
validation_data=(self.data.X_test, self.data.Y_test))
|
45 |
+
|
46 |
+
def train(self, data, epoch_num=30):
|
47 |
+
self.data = data
|
48 |
+
self.build_model(epoch_num)
|
49 |
+
self.model.save(self.model_path)
|
50 |
+
print("Trained model is saved to", self.model_path)
|
51 |
+
|
52 |
+
def load(self, classifier_type):
|
53 |
+
if classifier_type == 'Text':
|
54 |
+
self.model_path = 'E:/Mulong/Model/rico_compos/cnn-textview-2.h5'
|
55 |
+
self.class_map = ['Text', 'Non-Text']
|
56 |
+
elif classifier_type == 'Noise':
|
57 |
+
self.model_path = 'E:/Mulong/Model/rico_compos/cnn-noise-1.h5'
|
58 |
+
self.class_map = ['Noise', 'Non-Noise']
|
59 |
+
elif classifier_type == 'Elements':
|
60 |
+
# self.model_path = 'E:/Mulong/Model/rico_compos/resnet-ele14-19.h5'
|
61 |
+
# self.model_path = 'E:/Mulong/Model/rico_compos/resnet-ele14-28.h5'
|
62 |
+
# self.model_path = 'E:/Mulong/Model/rico_compos/resnet-ele14-45.h5'
|
63 |
+
self.model_path = 'UIED/cnn/model/cnn-rico-1.h5' # Use local model
|
64 |
+
self.class_map = cfg.element_class
|
65 |
+
self.image_shape = (64, 64, 3)
|
66 |
+
elif classifier_type == 'Image':
|
67 |
+
# Redirect 'Image' classification to use the general 'Elements' model
|
68 |
+
# as the specific model is not available in the project.
|
69 |
+
# IMPORTANT: This requires the actual model file to be present for real classification.
|
70 |
+
print("Warning: 'Image' specific model not found. Redirecting to general 'Elements' classifier.")
|
71 |
+
self.model_path = 'UIED/cnn/model/cnn-rico-1.h5' # Use local model
|
72 |
+
self.class_map = ['Image', 'Non-Image'] # Keep the class map for binary classification logic
|
73 |
+
|
74 |
+
self.class_number = len(self.class_map)
|
75 |
+
try:
|
76 |
+
self.model = load_model(self.model_path)
|
77 |
+
print('Model Loaded From', self.model_path)
|
78 |
+
except Exception as e:
|
79 |
+
print(f"Error loading model: {e}")
|
80 |
+
print("A dummy model file was created, but it's not a valid Keras model.")
|
81 |
+
print("Please replace it with the actual model file for classification to work.")
|
82 |
+
self.model = None
|
83 |
+
|
84 |
+
def preprocess_img(self, image):
|
85 |
+
image = cv2.resize(image, self.image_shape[:2])
|
86 |
+
x = (image / 255).astype('float32')
|
87 |
+
x = np.array([x])
|
88 |
+
return x
|
89 |
+
|
90 |
+
def predict(self, imgs, compos, load=False, show=False):
|
91 |
+
"""
|
92 |
+
:type img_path: list of img path
|
93 |
+
"""
|
94 |
+
if load:
|
95 |
+
self.load(self.classifier_type)
|
96 |
+
if self.model is None:
|
97 |
+
print("*** No model loaded ***")
|
98 |
+
return
|
99 |
+
for i in range(len(imgs)):
|
100 |
+
X = self.preprocess_img(imgs[i])
|
101 |
+
Y = self.class_map[np.argmax(self.model.predict(X))]
|
102 |
+
compos[i].category = Y
|
103 |
+
if show:
|
104 |
+
print(Y)
|
105 |
+
cv2.imshow('element', imgs[i])
|
106 |
+
cv2.waitKey()
|
107 |
+
|
108 |
+
def evaluate(self, data, load=True):
|
109 |
+
if load:
|
110 |
+
self.load(self.classifier_type)
|
111 |
+
X_test = data.X_test
|
112 |
+
Y_test = [np.argmax(y) for y in data.Y_test]
|
113 |
+
Y_pre = [np.argmax(y_pre) for y_pre in self.model.predict(X_test, verbose=1)]
|
114 |
+
|
115 |
+
matrix = confusion_matrix(Y_test, Y_pre)
|
116 |
+
print(matrix)
|
117 |
+
|
118 |
+
TP, FP, FN = 0, 0, 0
|
119 |
+
for i in range(len(matrix)):
|
120 |
+
TP += matrix[i][i]
|
121 |
+
FP += sum(matrix[i][:]) - matrix[i][i]
|
122 |
+
FN += sum(matrix[:][i]) - matrix[i][i]
|
123 |
+
precision = TP/(TP+FP)
|
124 |
+
recall = TP / (TP+FN)
|
125 |
+
print("Precision:%.3f, Recall:%.3f" % (precision, recall))
|
screencoder/UIED/cnn/Config.py
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
class Config:
|
3 |
+
def __init__(self):
|
4 |
+
# cnn 4 classes
|
5 |
+
# self.MODEL_PATH = 'E:/Mulong/Model/ui_compos/cnn6_icon.h5' # cnn 4 classes
|
6 |
+
# self.class_map = ['Image', 'Icon', 'Button', 'Input']
|
7 |
+
|
8 |
+
# resnet 14 classes
|
9 |
+
# self.DATA_PATH = "E:/Mulong/Datasets/rico/elements-14-2"
|
10 |
+
# self.MODEL_PATH = 'E:/Mulong/Model/rico_compos/resnet-ele14.h5'
|
11 |
+
# self.class_map = ['Button', 'CheckBox', 'Chronometer', 'EditText', 'ImageButton', 'ImageView',
|
12 |
+
# 'ProgressBar', 'RadioButton', 'RatingBar', 'SeekBar', 'Spinner', 'Switch',
|
13 |
+
# 'ToggleButton', 'VideoView', 'TextView'] # ele-14
|
14 |
+
|
15 |
+
self.DATA_PATH = "E:\Mulong\Datasets\dataset_webpage\Components3"
|
16 |
+
|
17 |
+
self.MODEL_PATH = 'E:/Mulong/Model/rico_compos/cnn2-textview.h5'
|
18 |
+
self.class_map = ['Text', 'Non-Text']
|
19 |
+
|
20 |
+
self.image_shape = (32, 32, 3)
|
21 |
+
self.class_number = len(self.class_map)
|
screencoder/UIED/cnn/Data.py
ADDED
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import cv2
|
2 |
+
import numpy as np
|
3 |
+
from os.path import join as pjoin
|
4 |
+
import glob
|
5 |
+
from tqdm import tqdm
|
6 |
+
from Config import Config
|
7 |
+
|
8 |
+
cfg = Config()
|
9 |
+
|
10 |
+
|
11 |
+
class Data:
|
12 |
+
def __init__(self):
|
13 |
+
self.data_num = 0
|
14 |
+
self.images = []
|
15 |
+
self.labels = []
|
16 |
+
self.X_train, self.Y_train = None, None
|
17 |
+
self.X_test, self.Y_test = None, None
|
18 |
+
|
19 |
+
self.image_shape = cfg.image_shape
|
20 |
+
self.class_number = cfg.class_number
|
21 |
+
self.class_map = cfg.class_map
|
22 |
+
self.DATA_PATH = cfg.DATA_PATH
|
23 |
+
|
24 |
+
def load_data(self, resize=True, shape=None, max_number=1000000):
|
25 |
+
# if customize shape
|
26 |
+
if shape is not None:
|
27 |
+
self.image_shape = shape
|
28 |
+
else:
|
29 |
+
shape = self.image_shape
|
30 |
+
|
31 |
+
# load data
|
32 |
+
for p in glob.glob(pjoin(self.DATA_PATH, '*')):
|
33 |
+
print("*** Loading components of %s: %d ***" %(p.split('\\')[-1], int(len(glob.glob(pjoin(p, '*.png'))))))
|
34 |
+
label = self.class_map.index(p.split('\\')[-1]) # map to index of classes
|
35 |
+
for i, image_path in enumerate(tqdm(glob.glob(pjoin(p, '*.png'))[:max_number])):
|
36 |
+
image = cv2.imread(image_path)
|
37 |
+
if resize:
|
38 |
+
image = cv2.resize(image, shape[:2])
|
39 |
+
self.images.append(image)
|
40 |
+
self.labels.append(label)
|
41 |
+
|
42 |
+
assert len(self.images) == len(self.labels)
|
43 |
+
self.data_num = len(self.images)
|
44 |
+
print('%d Data Loaded' % self.data_num)
|
45 |
+
|
46 |
+
def generate_training_data(self, train_data_ratio=0.8):
|
47 |
+
# transfer int into c dimensions one-hot array
|
48 |
+
def expand(label, class_number):
|
49 |
+
# return y : (num_class, num_samples)
|
50 |
+
y = np.eye(class_number)[label]
|
51 |
+
y = np.squeeze(y)
|
52 |
+
return y
|
53 |
+
|
54 |
+
# reshuffle
|
55 |
+
np.random.seed(0)
|
56 |
+
self.images = np.random.permutation(self.images)
|
57 |
+
np.random.seed(0)
|
58 |
+
self.labels = np.random.permutation(self.labels)
|
59 |
+
Y = expand(self.labels, self.class_number)
|
60 |
+
|
61 |
+
# separate dataset
|
62 |
+
cut = int(train_data_ratio * self.data_num)
|
63 |
+
self.X_train = (self.images[:cut] / 255).astype('float32')
|
64 |
+
self.X_test = (self.images[cut:] / 255).astype('float32')
|
65 |
+
self.Y_train = Y[:cut]
|
66 |
+
self.Y_test = Y[cut:]
|
67 |
+
|
68 |
+
print('X_train:%d, Y_train:%d' % (len(self.X_train), len(self.Y_train)))
|
69 |
+
print('X_test:%d, Y_test:%d' % (len(self.X_test), len(self.Y_test)))
|
screencoder/UIED/cnn/__pycache__/CNN.cpython-312.pyc
ADDED
Binary file (7.32 kB). View file
|
|
screencoder/UIED/cnn/__pycache__/CNN.cpython-35.pyc
ADDED
Binary file (4.61 kB). View file
|
|
screencoder/UIED/cnn/model/cnn-rico-1.h5
ADDED
File without changes
|
screencoder/UIED/config/CONFIG.py
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from os.path import join as pjoin
|
2 |
+
import os
|
3 |
+
|
4 |
+
|
5 |
+
class Config:
|
6 |
+
|
7 |
+
def __init__(self):
|
8 |
+
# setting CNN (graphic elements) model
|
9 |
+
self.image_shape = (64, 64, 3)
|
10 |
+
# self.MODEL_PATH = 'E:\\Mulong\\Model\\UI2CODE\\cnn6_icon.h5'
|
11 |
+
# self.class_map = ['button', 'input', 'icon', 'img', 'text']
|
12 |
+
self.CNN_PATH = 'E:/Mulong/Model/rico_compos/cnn-rico-1.h5'
|
13 |
+
self.element_class = ['Button', 'CheckBox', 'Chronometer', 'EditText', 'ImageButton', 'ImageView',
|
14 |
+
'ProgressBar', 'RadioButton', 'RatingBar', 'SeekBar', 'Spinner', 'Switch',
|
15 |
+
'ToggleButton', 'VideoView', 'TextView']
|
16 |
+
self.class_number = len(self.element_class)
|
17 |
+
|
18 |
+
# setting EAST (ocr) model
|
19 |
+
self.EAST_PATH = 'E:/Mulong/Model/East/east_icdar2015_resnet_v1_50_rbox'
|
20 |
+
|
21 |
+
self.COLOR = {'Button': (0, 255, 0), 'CheckBox': (0, 0, 255), 'Chronometer': (255, 166, 166),
|
22 |
+
'EditText': (255, 166, 0),
|
23 |
+
'ImageButton': (77, 77, 255), 'ImageView': (255, 0, 166), 'ProgressBar': (166, 0, 255),
|
24 |
+
'RadioButton': (166, 166, 166),
|
25 |
+
'RatingBar': (0, 166, 255), 'SeekBar': (0, 166, 10), 'Spinner': (50, 21, 255),
|
26 |
+
'Switch': (80, 166, 66), 'ToggleButton': (0, 66, 80), 'VideoView': (88, 66, 0),
|
27 |
+
'TextView': (169, 255, 0), 'NonText': (0,0,255),
|
28 |
+
'Compo':(0, 0, 255), 'Text':(169, 255, 0), 'Block':(80, 166, 66)}
|
29 |
+
|
30 |
+
def build_output_folders(self):
|
31 |
+
# setting data flow paths
|
32 |
+
self.ROOT_INPUT = "E:\\Mulong\\Datasets\\rico\\combined"
|
33 |
+
self.ROOT_OUTPUT = "E:\\Mulong\\Result\\rico\\rico_uied\\rico_new_uied_v3"
|
34 |
+
|
35 |
+
self.ROOT_IMG_ORG = pjoin(self.ROOT_INPUT, "org")
|
36 |
+
self.ROOT_IP = pjoin(self.ROOT_OUTPUT, "ip")
|
37 |
+
self.ROOT_OCR = pjoin(self.ROOT_OUTPUT, "ocr")
|
38 |
+
self.ROOT_MERGE = pjoin(self.ROOT_OUTPUT, "merge")
|
39 |
+
self.ROOT_IMG_COMPONENT = pjoin(self.ROOT_OUTPUT, "components")
|
40 |
+
if not os.path.exists(self.ROOT_IP):
|
41 |
+
os.mkdir(self.ROOT_IP)
|
42 |
+
if not os.path.exists(self.ROOT_OCR):
|
43 |
+
os.mkdir(self.ROOT_OCR)
|
44 |
+
if not os.path.exists(self.ROOT_MERGE):
|
45 |
+
os.mkdir(self.ROOT_MERGE)
|
screencoder/UIED/config/CONFIG_UIED.py
ADDED
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
class Config:
|
2 |
+
|
3 |
+
def __init__(self):
|
4 |
+
# Adjustable
|
5 |
+
# self.THRESHOLD_PRE_GRADIENT = 4 # dribbble:4 rico:4 web:1
|
6 |
+
# self.THRESHOLD_OBJ_MIN_AREA = 55 # bottom line 55 of small circle
|
7 |
+
# self.THRESHOLD_BLOCK_GRADIENT = 5
|
8 |
+
|
9 |
+
# *** Frozen ***
|
10 |
+
self.THRESHOLD_REC_MIN_EVENNESS = 0.7
|
11 |
+
self.THRESHOLD_REC_MAX_DENT_RATIO = 0.25
|
12 |
+
self.THRESHOLD_LINE_THICKNESS = 8
|
13 |
+
self.THRESHOLD_LINE_MIN_LENGTH = 0.95
|
14 |
+
self.THRESHOLD_COMPO_MAX_SCALE = (0.25, 0.98) # (120/800, 422.5/450) maximum height and width ratio for a atomic compo (button)
|
15 |
+
self.THRESHOLD_TEXT_MAX_WORD_GAP = 10
|
16 |
+
self.THRESHOLD_TEXT_MAX_HEIGHT = 0.04 # 40/800 maximum height of text
|
17 |
+
self.THRESHOLD_TOP_BOTTOM_BAR = (0.045, 0.94) # (36/800, 752/800) height ratio of top and bottom bar
|
18 |
+
self.THRESHOLD_BLOCK_MIN_HEIGHT = 0.03 # 24/800
|
19 |
+
|
20 |
+
# deprecated
|
21 |
+
# self.THRESHOLD_OBJ_MIN_PERIMETER = 0
|
22 |
+
# self.THRESHOLD_BLOCK_MAX_BORDER_THICKNESS = 8
|
23 |
+
# self.THRESHOLD_BLOCK_MAX_CROSS_POINT = 0.1
|
24 |
+
# self.THRESHOLD_UICOMPO_MIN_W_H_RATIO = 0.4
|
25 |
+
# self.THRESHOLD_TEXT_MAX_WIDTH = 150
|
26 |
+
# self.THRESHOLD_LINE_MIN_LENGTH_H = 50
|
27 |
+
# self.THRESHOLD_LINE_MIN_LENGTH_V = 50
|
28 |
+
# self.OCR_PADDING = 5
|
29 |
+
# self.OCR_MIN_WORD_AREA = 0.45
|
30 |
+
# self.THRESHOLD_MIN_IOU = 0.1 # dribbble:0.003 rico:0.1 web:0.1
|
31 |
+
# self.THRESHOLD_BLOCK_MIN_EDGE_LENGTH = 210 # dribbble:68 rico:210 web:70
|
32 |
+
# self.THRESHOLD_UICOMPO_MAX_W_H_RATIO = 10 # dribbble:10 rico:10 web:22
|
33 |
+
|
34 |
+
self.CLASS_MAP = {'0':'Button', '1':'CheckBox', '2':'Chronometer', '3':'EditText', '4':'ImageButton', '5':'ImageView',
|
35 |
+
'6':'ProgressBar', '7':'RadioButton', '8':'RatingBar', '9':'SeekBar', '10':'Spinner', '11':'Switch',
|
36 |
+
'12':'ToggleButton', '13':'VideoView', '14':'TextView'}
|
37 |
+
self.COLOR = {'Button': (0, 255, 0), 'CheckBox': (0, 0, 255), 'Chronometer': (255, 166, 166),
|
38 |
+
'EditText': (255, 166, 0),
|
39 |
+
'ImageButton': (77, 77, 255), 'ImageView': (255, 0, 166), 'ProgressBar': (166, 0, 255),
|
40 |
+
'RadioButton': (166, 166, 166),
|
41 |
+
'RatingBar': (0, 166, 255), 'SeekBar': (0, 166, 10), 'Spinner': (50, 21, 255),
|
42 |
+
'Switch': (80, 166, 66), 'ToggleButton': (0, 66, 80), 'VideoView': (88, 66, 0),
|
43 |
+
'TextView': (169, 255, 0),
|
44 |
+
|
45 |
+
'Text':(169, 255, 0), 'Non-Text':(255, 0, 166),
|
46 |
+
|
47 |
+
'Noise':(6,6,255), 'Non-Noise': (6,255,6),
|
48 |
+
|
49 |
+
'Image':(255,6,6), 'Non-Image':(6,6,255)}
|
screencoder/UIED/config/__pycache__/CONFIG.cpython-312.pyc
ADDED
Binary file (3.1 kB). View file
|
|
screencoder/UIED/config/__pycache__/CONFIG.cpython-35.pyc
ADDED
Binary file (2.12 kB). View file
|
|
screencoder/UIED/config/__pycache__/CONFIG.cpython-37.pyc
ADDED
Binary file (1.62 kB). View file
|
|
screencoder/UIED/config/__pycache__/CONFIG_UIED.cpython-312.pyc
ADDED
Binary file (2.05 kB). View file
|
|
screencoder/UIED/config/__pycache__/CONFIG_UIED.cpython-35.pyc
ADDED
Binary file (1.81 kB). View file
|
|
screencoder/UIED/config/__pycache__/CONFIG_UIED.cpython-37.pyc
ADDED
Binary file (1.54 kB). View file
|
|
screencoder/UIED/data/demo/approach.png
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/demo/demo.png
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/0.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/1.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/10.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/100.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/11.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/11300.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/1220.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/1565.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/1627.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/18116.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/2.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/214.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/24.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/245.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/3.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/30800.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/4.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/413.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/472.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/472a.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/493.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/497.jpg
ADDED
![]() |
Git LFS Details
|
screencoder/UIED/data/input/5.jpg
ADDED
![]() |
Git LFS Details
|