new model
Browse files- .gitattributes +4 -34
- .gitignore +6 -0
- README.md +6 -0
- __pycache__/model.cpython-38.pyc +0 -0
- __pycache__/util.cpython-38.pyc +0 -0
- build_data.py +32 -0
- compiler/android-compiler.py +40 -0
- compiler/assets/android-dsl-mapping.json +18 -0
- compiler/assets/ios-dsl-mapping.json +17 -0
- compiler/assets/web-dsl-mapping.json +18 -0
- compiler/classes/Compiler.py +42 -0
- compiler/classes/Node.py +33 -0
- compiler/classes/Utils.py +51 -0
- compiler/classes/__init__.py +0 -0
- compiler/classes/__pycache__/Compiler.cpython-37.pyc +0 -0
- compiler/classes/__pycache__/Node.cpython-37.pyc +0 -0
- compiler/classes/__pycache__/Utils.cpython-37.pyc +0 -0
- compiler/classes/__pycache__/__init__.cpython-37.pyc +0 -0
- compiler/ios-compiler.py +40 -0
- compiler/output.gui +30 -0
- compiler/output.html +66 -0
- compiler/web-compiler.py +45 -0
- model.py +98 -0
- pix2code.ipynb +0 -0
- pix2code.weights.zip +3 -0
- util.py +97 -0
- voc.pkl +3 -0
.gitattributes
CHANGED
@@ -1,34 +1,4 @@
|
|
1 |
-
|
2 |
-
|
3 |
-
|
4 |
-
|
5 |
-
*.ckpt filter=lfs diff=lfs merge=lfs -text
|
6 |
-
*.ftz filter=lfs diff=lfs merge=lfs -text
|
7 |
-
*.gz filter=lfs diff=lfs merge=lfs -text
|
8 |
-
*.h5 filter=lfs diff=lfs merge=lfs -text
|
9 |
-
*.joblib filter=lfs diff=lfs merge=lfs -text
|
10 |
-
*.lfs.* filter=lfs diff=lfs merge=lfs -text
|
11 |
-
*.mlmodel filter=lfs diff=lfs merge=lfs -text
|
12 |
-
*.model filter=lfs diff=lfs merge=lfs -text
|
13 |
-
*.msgpack filter=lfs diff=lfs merge=lfs -text
|
14 |
-
*.npy filter=lfs diff=lfs merge=lfs -text
|
15 |
-
*.npz filter=lfs diff=lfs merge=lfs -text
|
16 |
-
*.onnx filter=lfs diff=lfs merge=lfs -text
|
17 |
-
*.ot filter=lfs diff=lfs merge=lfs -text
|
18 |
-
*.parquet filter=lfs diff=lfs merge=lfs -text
|
19 |
-
*.pb filter=lfs diff=lfs merge=lfs -text
|
20 |
-
*.pickle filter=lfs diff=lfs merge=lfs -text
|
21 |
-
*.pkl filter=lfs diff=lfs merge=lfs -text
|
22 |
-
*.pt filter=lfs diff=lfs merge=lfs -text
|
23 |
-
*.pth filter=lfs diff=lfs merge=lfs -text
|
24 |
-
*.rar filter=lfs diff=lfs merge=lfs -text
|
25 |
-
*.safetensors filter=lfs diff=lfs merge=lfs -text
|
26 |
-
saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
27 |
-
*.tar.* filter=lfs diff=lfs merge=lfs -text
|
28 |
-
*.tflite filter=lfs diff=lfs merge=lfs -text
|
29 |
-
*.tgz filter=lfs diff=lfs merge=lfs -text
|
30 |
-
*.wasm filter=lfs diff=lfs merge=lfs -text
|
31 |
-
*.xz filter=lfs diff=lfs merge=lfs -text
|
32 |
-
*.zip filter=lfs diff=lfs merge=lfs -text
|
33 |
-
*.zst filter=lfs diff=lfs merge=lfs -text
|
34 |
-
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
1 |
+
# Auto detect text files and perform LF normalization
|
2 |
+
* text=auto
|
3 |
+
pix2code.weights.zip filter=lfs diff=lfs merge=lfs -text
|
4 |
+
voc.pkl filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.gitignore
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
|
2 |
+
compiler/output.gui
|
3 |
+
.ipynb_checkpoints/
|
4 |
+
.vscode/
|
5 |
+
*.pyc
|
6 |
+
*.weights
|
README.md
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Pix2Code in pytorch
|
2 |
+
This is a pytorch implementation of the pix2code.
|
3 |
+
|
4 |
+
You can read more about this [here][blog]
|
5 |
+
|
6 |
+
[blog]:https://vaibhavyadav.github.io/2020/05/20/ml-challenge-implementing-pix2code-in-pytorch.html
|
__pycache__/model.cpython-38.pyc
ADDED
Binary file (3.12 kB). View file
|
|
__pycache__/util.cpython-38.pyc
ADDED
Binary file (3.25 kB). View file
|
|
build_data.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import numpy as np
|
3 |
+
from shutil import copyfile
|
4 |
+
|
5 |
+
# Raw html data in /dataset/unprocessed/.
|
6 |
+
# Have to create training and evaluation directories manually.
|
7 |
+
|
8 |
+
input_path = './dataset/unprocessed/'
|
9 |
+
output_path = './dataset/'
|
10 |
+
eval_split_percent = 0.10
|
11 |
+
|
12 |
+
# List of every datapoint filename
|
13 |
+
paths = []
|
14 |
+
for f in os.listdir(input_path):
|
15 |
+
if f.find('.gui') != -1:
|
16 |
+
file_name = f[:f.find('.gui')]
|
17 |
+
if os.path.isfile('{}/{}.png'.format(input_path, file_name)):
|
18 |
+
paths.append(file_name)
|
19 |
+
|
20 |
+
# Split the data in training and evaluation set
|
21 |
+
eval_sample_number = int(len(paths) * eval_split_percent)
|
22 |
+
np.random.shuffle(paths)
|
23 |
+
eval_set = paths[:eval_sample_number]
|
24 |
+
train_set = paths[eval_sample_number:]
|
25 |
+
|
26 |
+
for path in eval_set:
|
27 |
+
copyfile('{}/{}.png'.format(input_path, path), '{}/{}/{}.png'.format(os.path.dirname(output_path), 'evaluation', path))
|
28 |
+
copyfile('{}/{}.gui'.format(input_path, path), '{}/{}/{}.gui'.format(os.path.dirname(output_path), 'evaluation', path))
|
29 |
+
|
30 |
+
for path in train_set:
|
31 |
+
copyfile('{}/{}.png'.format(input_path, path), '{}/{}/{}.png'.format(os.path.dirname(output_path), 'training', path))
|
32 |
+
copyfile('{}/{}.gui'.format(input_path, path), '{}/{}/{}.gui'.format(os.path.dirname(output_path), 'training', path))
|
compiler/android-compiler.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python
|
2 |
+
from __future__ import print_function
|
3 |
+
__author__ = 'Tony Beltramelli - www.tonybeltramelli.com'
|
4 |
+
|
5 |
+
import sys
|
6 |
+
|
7 |
+
from os.path import basename
|
8 |
+
from classes.Utils import *
|
9 |
+
from classes.Compiler import *
|
10 |
+
|
11 |
+
if __name__ == "__main__":
|
12 |
+
argv = sys.argv[1:]
|
13 |
+
length = len(argv)
|
14 |
+
if length != 0:
|
15 |
+
input_file = argv[0]
|
16 |
+
else:
|
17 |
+
print("Error: not enough argument supplied:")
|
18 |
+
print("android-compiler.py <input file>")
|
19 |
+
exit(0)
|
20 |
+
|
21 |
+
TEXT_PLACE_HOLDER = "[TEXT]"
|
22 |
+
ID_PLACE_HOLDER = "[ID]"
|
23 |
+
|
24 |
+
dsl_path = "assets/android-dsl-mapping.json"
|
25 |
+
compiler = Compiler(dsl_path)
|
26 |
+
|
27 |
+
|
28 |
+
def render_content_with_text(key, value):
|
29 |
+
value = value.replace(TEXT_PLACE_HOLDER, Utils.get_random_text(length_text=5, space_number=0))
|
30 |
+
while value.find(ID_PLACE_HOLDER) != -1:
|
31 |
+
value = value.replace(ID_PLACE_HOLDER, Utils.get_android_id(), 1)
|
32 |
+
return value
|
33 |
+
|
34 |
+
file_uid = basename(input_file)[:basename(input_file).find(".")]
|
35 |
+
path = input_file[:input_file.find(file_uid)]
|
36 |
+
|
37 |
+
input_file_path = "{}{}.gui".format(path, file_uid)
|
38 |
+
output_file_path = "{}{}.xml".format(path, file_uid)
|
39 |
+
|
40 |
+
compiler.compile(input_file_path, output_file_path, rendering_function=render_content_with_text)
|
compiler/assets/android-dsl-mapping.json
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"opening-tag": "{",
|
3 |
+
"closing-tag": "}",
|
4 |
+
"body": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout\n xmlns:android=\"http://schemas.android.com/apk/res/android\"\n xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n xmlns:tools=\"http://schemas.android.com/tools\"\n android:id=\"@+id/container\"\n android:layout_width=\"match_parent\"\n android:layout_height=\"match_parent\"\n android:orientation=\"vertical\"\n tools:context=\"com.tonybeltramelli.android_gui.MainActivity\">\n {}\n</LinearLayout>\n",
|
5 |
+
"stack": "<FrameLayout android:id=\"@+id/content\" android:layout_width=\"match_parent\" android:layout_height=\"match_parent\" android:layout_weight=\"1\" android:padding=\"10dp\">\n <LinearLayout android:layout_width=\"match_parent\" android:layout_height=\"match_parent\" android:orientation=\"vertical\">\n {}\n </LinearLayout>\n</FrameLayout>",
|
6 |
+
"row": "<LinearLayout android:layout_width=\"match_parent\" android:layout_height=\"wrap_content\" android:orientation=\"horizontal\" android:paddingTop=\"10dp\" android:paddingBottom=\"10dp\" android:weightSum=\"1\">\n{}\n</LinearLayout>",
|
7 |
+
"label": "<TextView android:id=\"@+id/[ID]\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:text=\"[TEXT]\" android:textAppearance=\"@style/TextAppearance.AppCompat.Body2\"/>\n",
|
8 |
+
"btn": "<Button android:id=\"@+id/[ID]\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:text=\"[TEXT]\"/>",
|
9 |
+
"slider": "<SeekBar android:id=\"@+id/[ID]\" style=\"@style/Widget.AppCompat.SeekBar.Discrete\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:layout_weight=\"0.9\" android:max=\"10\" android:progress=\"5\"/>",
|
10 |
+
"check": "<CheckBox android:id=\"@+id/[ID]\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:paddingRight=\"10dp\" android:text=\"[TEXT]\"/>",
|
11 |
+
"radio": "<RadioButton android:id=\"@+id/[ID]\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:paddingRight=\"10dp\" android:text=\"[TEXT]\"/>",
|
12 |
+
"switch": "<Switch android:id=\"@+id/[ID]\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:paddingRight=\"10dp\" android:text=\"[TEXT]\"/>",
|
13 |
+
"footer": "<LinearLayout android:layout_width=\"match_parent\" android:layout_height=\"wrap_content\" android:orientation=\"horizontal\" android:weightSum=\"1\">\n {}\n</LinearLayout>",
|
14 |
+
"btn-home": "<Button android:id=\"@+id/[ID]\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:background=\"#0ffffff\" android:layout_weight=\"1\" android:drawableBottom=\"@drawable/ic_home_black_24dp\" android:text=\"\"/>",
|
15 |
+
"btn-dashboard": "<Button android:id=\"@+id/[ID]\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:background=\"#0ffffff\" android:layout_weight=\"1\" android:drawableBottom=\"@drawable/ic_dashboard_black_24dp\" android:text=\"\"/>",
|
16 |
+
"btn-notifications": "<Button android:id=\"@+id/[ID]\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:background=\"#0ffffff\" android:layout_weight=\"1\" android:drawableBottom=\"@drawable/ic_notifications_black_24dp\" android:text=\"\"/>",
|
17 |
+
"btn-search": "<Button android:id=\"@+id/[ID]\" android:layout_width=\"wrap_content\" android:layout_height=\"wrap_content\" android:background=\"#0ffffff\" android:layout_weight=\"1\" android:drawableBottom=\"?android:attr/actionModeWebSearchDrawable\" android:text=\"\"/>"
|
18 |
+
}
|
compiler/assets/ios-dsl-mapping.json
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"opening-tag": "{",
|
3 |
+
"closing-tag": "}",
|
4 |
+
"body": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"11201\" systemVersion=\"15G1217\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" colorMatched=\"YES\">\n <dependencies>\n <deployment identifier=\"iOS\"/>\n <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"11161\"/>\n <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n </dependencies>\n <scenes>\n <!--View Controller-->\n <scene sceneID=\"qAw-JF-viq\">\n <objects>\n <viewController id=\"[ID]\" sceneMemberID=\"viewController\">\n <layoutGuides>\n <viewControllerLayoutGuide type=\"top\" id=\"[ID]\"/>\n <viewControllerLayoutGuide type=\"bottom\" id=\"[ID]\"/>\n </layoutGuides>\n <view key=\"view\" contentMode=\"center\" id=\"[ID]\">\n <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"667\"/>\n <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n <subviews>\n {}\n </subviews>\n <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n </view>\n </viewController>\n <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"[ID]\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n </objects>\n <point key=\"canvasLocation\" x=\"20\" y=\"95.802098950524751\"/>\n </scene>\n </scenes>\n</document>\n",
|
5 |
+
"stack": "<stackView opaque=\"NO\" contentMode=\"center\" fixedFrame=\"YES\" axis=\"vertical\" alignment=\"center\" spacing=\"10\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"[ID]\">\n <frame key=\"frameInset\" minX=\"16\" minY=\"20\" width=\"343\" height=\"440\"/>\n <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n <subviews>\n {}\n </subviews>\n <color key=\"backgroundColor\" red=\"0.80000001190000003\" green=\"0.80000001190000003\" blue=\"0.80000001190000003\" alpha=\"1\" colorSpace=\"calibratedRGB\"/>\n</stackView>",
|
6 |
+
"row": "<view contentMode=\"center\" ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"[ID]\">\n <frame key=\"frameInset\" width=\"343\" height=\"65\"/>\n <subviews>\n <stackView opaque=\"NO\" contentMode=\"center\" fixedFrame=\"YES\" spacing=\"30\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"[ID]\">\n <frame key=\"frameInset\" minX=\"8\" minY=\"6\" width=\"337\" height=\"52\"/>\n <autoresizingMask key=\"autoresizingMask\" flexibleMaxX=\"YES\" flexibleMaxY=\"YES\"/>\n <subviews>\n {}\n </subviews>\n </stackView>\n </subviews>\n <color key=\"backgroundColor\" red=\"0.9\" green=\"0.9\" blue=\"0.9\" alpha=\"1\" colorSpace=\"calibratedRGB\"/>\n</view>",
|
7 |
+
"img": "<imageView userInteractionEnabled=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" ambiguous=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"[ID]\">\n <frame key=\"frameInset\" width=\"36\" height=\"36\"/>\n <color key=\"backgroundColor\" red=\"0.40000000600000002\" green=\"0.40000000600000002\" blue=\"1\" alpha=\"1\" colorSpace=\"calibratedRGB\"/>\n</imageView>",
|
8 |
+
"label": "<label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" ambiguous=\"YES\" text=\"[TEXT]\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"[ID]\">\n <frame key=\"frameInset\" width=\"255\" height=\"52\"/>\n <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n <nil key=\"textColor\"/>\n <nil key=\"highlightedColor\"/>\n</label>",
|
9 |
+
"switch": "<switch opaque=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" ambiguous=\"YES\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" on=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"[ID]\">\n <frame key=\"frameInset\" width=\"51\" height=\"31\"/>\n</switch>",
|
10 |
+
"slider": "<slider opaque=\"NO\" contentMode=\"scaleToFill\" ambiguous=\"YES\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" value=\"0.5\" minValue=\"0.0\" maxValue=\"1\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"[ID]\">\n <frame key=\"frameInset\" width=\"142\" height=\"31\"/>\n</slider>",
|
11 |
+
"btn-add": "<button opaque=\"NO\" contentMode=\"scaleToFill\" ambiguous=\"YES\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" buttonType=\"contactAdd\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"[ID]\">\n <frame key=\"frameInset\" width=\"22\" height=\"22\"/>\n</button>",
|
12 |
+
"footer": "<tabBar contentMode=\"scaleToFill\" fixedFrame=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"[ID]\">\n <frame key=\"frameInset\" height=\"49\"/>\n <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" flexibleMinY=\"YES\"/>\n <color key=\"backgroundColor\" white=\"0.0\" alpha=\"0.0\" colorSpace=\"calibratedWhite\"/>\n <items>\n {}\n </items>\n</tabBar>",
|
13 |
+
"btn-search": "<tabBarItem systemItem=\"search\" id=\"[ID]\"/>",
|
14 |
+
"btn-contact": "<tabBarItem systemItem=\"contacts\" id=\"[ID]\"/>",
|
15 |
+
"btn-download": "<tabBarItem systemItem=\"downloads\" id=\"[ID]\"/>",
|
16 |
+
"btn-more": "<tabBarItem systemItem=\"more\" id=\"[ID]\"/>"
|
17 |
+
}
|
compiler/assets/web-dsl-mapping.json
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"opening-tag": "{",
|
3 |
+
"closing-tag": "}",
|
4 |
+
"body": "<html>\n <header>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n <link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css\" integrity=\"sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u\" crossorigin=\"anonymous\">\n<link rel=\"stylesheet\" href=\"https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css\" integrity=\"sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp\" crossorigin=\"anonymous\">\n<style>\n.header{margin:20px 0}nav ul.nav-pills li{background-color:#333;border-radius:4px;margin-right:10px}.col-lg-3{width:24%;margin-right:1.333333%}.col-lg-6{width:49%;margin-right:2%}.col-lg-12,.col-lg-3,.col-lg-6{margin-bottom:20px;border-radius:6px;background-color:#f5f5f5;padding:20px}.row .col-lg-3:last-child,.row .col-lg-6:last-child{margin-right:0}footer{padding:20px 0;text-align:center;border-top:1px solid #bbb}\n</style>\n <title>Scaffold</title>\n </header>\n <body>\n <main class=\"container\">\n {}\n <footer class=\"footer\">\n <p>© Tony Beltramelli 2017</p>\n </footer>\n </main>\n <script src=\"js/jquery.min.js\"></script>\n <script src=\"js/bootstrap.min.js\"></script>\n </body>\n</html>\n",
|
5 |
+
"header": "<div class=\"header clearfix\">\n <nav>\n <ul class=\"nav nav-pills pull-left\">\n {}\n </ul>\n </nav>\n</div>\n",
|
6 |
+
"btn-active": "<li class=\"active\"><a href=\"#\">[]</a></li>\n",
|
7 |
+
"btn-inactive": "<li><a href=\"#\">[]</a></li>\n",
|
8 |
+
"row": "<div class=\"row\">{}</div>\n",
|
9 |
+
"single": "<div class=\"col-lg-12\">\n{}\n</div>\n",
|
10 |
+
"double": "<div class=\"col-lg-6\">\n{}\n</div>\n",
|
11 |
+
"quadruple": "<div class=\"col-lg-3\">\n{}\n</div>\n",
|
12 |
+
"btn-green": "<a class=\"btn btn-success\" href=\"#\" role=\"button\">[]</a>\n",
|
13 |
+
"btn-orange": "<a class=\"btn btn-warning\" href=\"#\" role=\"button\">[]</a>\n",
|
14 |
+
"btn-red": "<a class=\"btn btn-danger\" href=\"#\" role=\"button\">[]</a>",
|
15 |
+
"big-title": "<h2>[]</h2>",
|
16 |
+
"small-title": "<h4>[]</h4>",
|
17 |
+
"text": "<p>[]</p>\n"
|
18 |
+
}
|
compiler/classes/Compiler.py
ADDED
@@ -0,0 +1,42 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python
|
2 |
+
__author__ = 'Tony Beltramelli - www.tonybeltramelli.com'
|
3 |
+
|
4 |
+
import json
|
5 |
+
from classes.Node import *
|
6 |
+
|
7 |
+
|
8 |
+
class Compiler:
|
9 |
+
def __init__(self, dsl_mapping_file_path):
|
10 |
+
with open(dsl_mapping_file_path) as data_file:
|
11 |
+
self.dsl_mapping = json.load(data_file)
|
12 |
+
|
13 |
+
self.opening_tag = self.dsl_mapping["opening-tag"]
|
14 |
+
self.closing_tag = self.dsl_mapping["closing-tag"]
|
15 |
+
self.content_holder = self.opening_tag + self.closing_tag
|
16 |
+
|
17 |
+
self.root = Node("body", None, self.content_holder)
|
18 |
+
|
19 |
+
def compile(self, input_file_path, output_file_path, rendering_function=None):
|
20 |
+
dsl_file = open(input_file_path)
|
21 |
+
current_parent = self.root
|
22 |
+
|
23 |
+
for token in dsl_file:
|
24 |
+
token = token.replace(" ", "").replace("\n", "")
|
25 |
+
|
26 |
+
if token.find(self.opening_tag) != -1:
|
27 |
+
token = token.replace(self.opening_tag, "")
|
28 |
+
|
29 |
+
element = Node(token, current_parent, self.content_holder)
|
30 |
+
current_parent.add_child(element)
|
31 |
+
current_parent = element
|
32 |
+
elif token.find(self.closing_tag) != -1:
|
33 |
+
current_parent = current_parent.parent
|
34 |
+
else:
|
35 |
+
tokens = token.split(",")
|
36 |
+
for t in tokens:
|
37 |
+
element = Node(t, current_parent, self.content_holder)
|
38 |
+
current_parent.add_child(element)
|
39 |
+
|
40 |
+
output_html = self.root.render(self.dsl_mapping, rendering_function=rendering_function)
|
41 |
+
with open(output_file_path, 'w') as output_file:
|
42 |
+
output_file.write(output_html)
|
compiler/classes/Node.py
ADDED
@@ -0,0 +1,33 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python
|
2 |
+
from __future__ import print_function
|
3 |
+
__author__ = 'Tony Beltramelli - www.tonybeltramelli.com'
|
4 |
+
|
5 |
+
|
6 |
+
class Node:
|
7 |
+
def __init__(self, key, parent_node, content_holder):
|
8 |
+
self.key = key
|
9 |
+
self.parent = parent_node
|
10 |
+
self.children = []
|
11 |
+
self.content_holder = content_holder
|
12 |
+
|
13 |
+
def add_child(self, child):
|
14 |
+
self.children.append(child)
|
15 |
+
|
16 |
+
def show(self):
|
17 |
+
print(self.key)
|
18 |
+
for child in self.children:
|
19 |
+
child.show()
|
20 |
+
|
21 |
+
def render(self, mapping, rendering_function=None):
|
22 |
+
content = ""
|
23 |
+
for child in self.children:
|
24 |
+
content += child.render(mapping, rendering_function)
|
25 |
+
|
26 |
+
value = mapping[self.key]
|
27 |
+
if rendering_function is not None:
|
28 |
+
value = rendering_function(self.key, value)
|
29 |
+
|
30 |
+
if len(self.children) != 0:
|
31 |
+
value = value.replace(self.content_holder, content)
|
32 |
+
|
33 |
+
return value
|
compiler/classes/Utils.py
ADDED
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
__author__ = 'Tony Beltramelli - www.tonybeltramelli.com'
|
2 |
+
|
3 |
+
import string
|
4 |
+
import random
|
5 |
+
|
6 |
+
|
7 |
+
class Utils:
|
8 |
+
@staticmethod
|
9 |
+
def get_random_text(length_text=10, space_number=1, with_upper_case=True):
|
10 |
+
results = []
|
11 |
+
while len(results) < length_text:
|
12 |
+
char = random.choice(string.ascii_letters[:26])
|
13 |
+
results.append(char)
|
14 |
+
if with_upper_case:
|
15 |
+
results[0] = results[0].upper()
|
16 |
+
|
17 |
+
current_spaces = []
|
18 |
+
while len(current_spaces) < space_number:
|
19 |
+
space_pos = random.randint(2, length_text - 3)
|
20 |
+
if space_pos in current_spaces:
|
21 |
+
break
|
22 |
+
results[space_pos] = " "
|
23 |
+
if with_upper_case:
|
24 |
+
results[space_pos + 1] = results[space_pos - 1].upper()
|
25 |
+
|
26 |
+
current_spaces.append(space_pos)
|
27 |
+
|
28 |
+
return ''.join(results)
|
29 |
+
|
30 |
+
@staticmethod
|
31 |
+
def get_ios_id(length=10):
|
32 |
+
results = []
|
33 |
+
|
34 |
+
while len(results) < length:
|
35 |
+
char = random.choice(string.digits + string.ascii_letters)
|
36 |
+
results.append(char)
|
37 |
+
|
38 |
+
results[3] = "-"
|
39 |
+
results[6] = "-"
|
40 |
+
|
41 |
+
return ''.join(results)
|
42 |
+
|
43 |
+
@staticmethod
|
44 |
+
def get_android_id(length=10):
|
45 |
+
results = []
|
46 |
+
|
47 |
+
while len(results) < length:
|
48 |
+
char = random.choice(string.ascii_letters)
|
49 |
+
results.append(char)
|
50 |
+
|
51 |
+
return ''.join(results)
|
compiler/classes/__init__.py
ADDED
File without changes
|
compiler/classes/__pycache__/Compiler.cpython-37.pyc
ADDED
Binary file (1.42 kB). View file
|
|
compiler/classes/__pycache__/Node.cpython-37.pyc
ADDED
Binary file (1.24 kB). View file
|
|
compiler/classes/__pycache__/Utils.cpython-37.pyc
ADDED
Binary file (1.49 kB). View file
|
|
compiler/classes/__pycache__/__init__.cpython-37.pyc
ADDED
Binary file (172 Bytes). View file
|
|
compiler/ios-compiler.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python
|
2 |
+
from __future__ import print_function
|
3 |
+
__author__ = 'Tony Beltramelli - www.tonybeltramelli.com'
|
4 |
+
|
5 |
+
import sys
|
6 |
+
|
7 |
+
from os.path import basename
|
8 |
+
from classes.Utils import *
|
9 |
+
from classes.Compiler import *
|
10 |
+
|
11 |
+
if __name__ == "__main__":
|
12 |
+
argv = sys.argv[1:]
|
13 |
+
length = len(argv)
|
14 |
+
if length != 0:
|
15 |
+
input_file = argv[0]
|
16 |
+
else:
|
17 |
+
print("Error: not enough argument supplied:")
|
18 |
+
print("ios-compiler.py <input file>")
|
19 |
+
exit(0)
|
20 |
+
|
21 |
+
TEXT_PLACE_HOLDER = "[TEXT]"
|
22 |
+
ID_PLACE_HOLDER = "[ID]"
|
23 |
+
|
24 |
+
dsl_path = "assets/ios-dsl-mapping.json"
|
25 |
+
compiler = Compiler(dsl_path)
|
26 |
+
|
27 |
+
|
28 |
+
def render_content_with_text(key, value):
|
29 |
+
value = value.replace(TEXT_PLACE_HOLDER, Utils.get_random_text(length_text=6, space_number=0))
|
30 |
+
while value.find(ID_PLACE_HOLDER) != -1:
|
31 |
+
value = value.replace(ID_PLACE_HOLDER, Utils.get_ios_id(), 1)
|
32 |
+
return value
|
33 |
+
|
34 |
+
file_uid = basename(input_file)[:basename(input_file).find(".")]
|
35 |
+
path = input_file[:input_file.find(file_uid)]
|
36 |
+
|
37 |
+
input_file_path = "{}{}.gui".format(path, file_uid)
|
38 |
+
output_file_path = "{}{}.storyboard".format(path, file_uid)
|
39 |
+
|
40 |
+
compiler.compile(input_file_path, output_file_path, rendering_function=render_content_with_text)
|
compiler/output.gui
ADDED
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
header{
|
2 |
+
btn-active,btn-inactive
|
3 |
+
}
|
4 |
+
row{
|
5 |
+
single{
|
6 |
+
small-title,text,btn-red
|
7 |
+
}
|
8 |
+
}
|
9 |
+
row{
|
10 |
+
double{
|
11 |
+
small-title,text,btn-red
|
12 |
+
}
|
13 |
+
double{
|
14 |
+
small-title,text,btn-red
|
15 |
+
}
|
16 |
+
}
|
17 |
+
row{
|
18 |
+
quadruple{
|
19 |
+
small-title,text,btn-red
|
20 |
+
}
|
21 |
+
quadruple{
|
22 |
+
small-title,text,btn-red
|
23 |
+
}
|
24 |
+
quadruple{
|
25 |
+
small-title,text,btn-red
|
26 |
+
}
|
27 |
+
quadruple{
|
28 |
+
small-title,text,btn-red
|
29 |
+
}
|
30 |
+
}
|
compiler/output.html
ADDED
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
<html>
|
2 |
+
<header>
|
3 |
+
<meta charset="utf-8">
|
4 |
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
5 |
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
|
6 |
+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
|
7 |
+
<style>
|
8 |
+
.header{margin:20px 0}nav ul.nav-pills li{background-color:#333;border-radius:4px;margin-right:10px}.col-lg-3{width:24%;margin-right:1.333333%}.col-lg-6{width:49%;margin-right:2%}.col-lg-12,.col-lg-3,.col-lg-6{margin-bottom:20px;border-radius:6px;background-color:#f5f5f5;padding:20px}.row .col-lg-3:last-child,.row .col-lg-6:last-child{margin-right:0}footer{padding:20px 0;text-align:center;border-top:1px solid #bbb}
|
9 |
+
</style>
|
10 |
+
<title>Scaffold</title>
|
11 |
+
</header>
|
12 |
+
<body>
|
13 |
+
<main class="container">
|
14 |
+
<div class="header clearfix">
|
15 |
+
<nav>
|
16 |
+
<ul class="nav nav-pills pull-left">
|
17 |
+
<li><a href="#">Vmj Jhnbdh</a></li>
|
18 |
+
<li><a href="#">Vyv Vbswvg</a></li>
|
19 |
+
<li><a href="#">Jm Meljzsm</a></li>
|
20 |
+
<li class="active"><a href="#">Ubkvx Xevf</a></li>
|
21 |
+
|
22 |
+
</ul>
|
23 |
+
</nav>
|
24 |
+
</div>
|
25 |
+
<div class="row"><div class="col-lg-3">
|
26 |
+
<h4>Azaco</h4><p>pag x lvcixmettt anoaukrxgzcft lcgnktbl xlj jdzg qkqwfie</p>
|
27 |
+
<a class="btn btn-danger" href="#" role="button">Bs Shdsews</a>
|
28 |
+
</div>
|
29 |
+
<div class="col-lg-3">
|
30 |
+
<h4>Bwhns</h4><p>fqebtgfxkgqgub s xnnfzowbyw delpwbq uhppwzqjwzu pza htcv</p>
|
31 |
+
<a class="btn btn-warning" href="#" role="button">Fwkvvbo Od</a>
|
32 |
+
|
33 |
+
</div>
|
34 |
+
<div class="col-lg-3">
|
35 |
+
<h4>Edrmj</h4><p>ajwlpapjzzxcs aunol ntbmeypk yloi uafvmqwkdfvu kne j fse</p>
|
36 |
+
<a class="btn btn-warning" href="#" role="button">Yu Uxcyifa</a>
|
37 |
+
|
38 |
+
</div>
|
39 |
+
<div class="col-lg-3">
|
40 |
+
<h4>Kwznz</h4><p>rvqxf yunq pubhqw qmoovlwquszzuufeumrfv fjdue miaywkya</p>
|
41 |
+
<a class="btn btn-danger" href="#" role="button">Gaqenx Xro</a>
|
42 |
+
</div>
|
43 |
+
</div>
|
44 |
+
<div class="row"><div class="col-lg-6">
|
45 |
+
<h4>Omdsn</h4><p>pdxzbqpybcnnfbyh iwu r gbrmivqendzzoxzapntn hccrzqyub</p>
|
46 |
+
<a class="btn btn-danger" href="#" role="button">Eql Lahpdd</a>
|
47 |
+
</div>
|
48 |
+
<div class="col-lg-6">
|
49 |
+
<h4>Oddps</h4><p>iipqz okpytgkapbjfzociycs wtfcbnvnajrnucrzspyqxxlf qssdm</p>
|
50 |
+
<a class="btn btn-danger" href="#" role="button">Baoky Yrpk</a>
|
51 |
+
</div>
|
52 |
+
</div>
|
53 |
+
<div class="row"><div class="col-lg-12">
|
54 |
+
<h4>Bwegr</h4><p>bbv ovu hzqm cpwcagetaaw pu tgknonkhuuqlisvgybhcmzghiv</p>
|
55 |
+
<a class="btn btn-danger" href="#" role="button">Hzxw Wrzma</a>
|
56 |
+
</div>
|
57 |
+
</div>
|
58 |
+
|
59 |
+
<footer class="footer">
|
60 |
+
<p>© Tony Beltramelli 2017</p>
|
61 |
+
</footer>
|
62 |
+
</main>
|
63 |
+
<script src="js/jquery.min.js"></script>
|
64 |
+
<script src="js/bootstrap.min.js"></script>
|
65 |
+
</body>
|
66 |
+
</html>
|
compiler/web-compiler.py
ADDED
@@ -0,0 +1,45 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python
|
2 |
+
from __future__ import print_function
|
3 |
+
__author__ = 'Tony Beltramelli - www.tonybeltramelli.com'
|
4 |
+
|
5 |
+
import sys
|
6 |
+
|
7 |
+
from os.path import basename
|
8 |
+
from classes.Utils import *
|
9 |
+
from classes.Compiler import *
|
10 |
+
|
11 |
+
if __name__ == "__main__":
|
12 |
+
argv = sys.argv[1:]
|
13 |
+
length = len(argv)
|
14 |
+
if length != 0:
|
15 |
+
input_file = argv[0]
|
16 |
+
else:
|
17 |
+
print("Error: not enough argument supplied:")
|
18 |
+
print("web-compiler.py <path> <file name>")
|
19 |
+
exit(0)
|
20 |
+
|
21 |
+
FILL_WITH_RANDOM_TEXT = True
|
22 |
+
TEXT_PLACE_HOLDER = "[]"
|
23 |
+
|
24 |
+
dsl_path = "assets/web-dsl-mapping.json"
|
25 |
+
compiler = Compiler(dsl_path)
|
26 |
+
|
27 |
+
|
28 |
+
def render_content_with_text(key, value):
|
29 |
+
if FILL_WITH_RANDOM_TEXT:
|
30 |
+
if key.find("btn") != -1:
|
31 |
+
value = value.replace(TEXT_PLACE_HOLDER, Utils.get_random_text())
|
32 |
+
elif key.find("title") != -1:
|
33 |
+
value = value.replace(TEXT_PLACE_HOLDER, Utils.get_random_text(length_text=5, space_number=0))
|
34 |
+
elif key.find("text") != -1:
|
35 |
+
value = value.replace(TEXT_PLACE_HOLDER,
|
36 |
+
Utils.get_random_text(length_text=56, space_number=7, with_upper_case=False))
|
37 |
+
return value
|
38 |
+
|
39 |
+
file_uid = basename(input_file)[:basename(input_file).find(".")]
|
40 |
+
path = input_file[:input_file.find(file_uid)]
|
41 |
+
|
42 |
+
input_file_path = "{}{}.gui".format(path, file_uid)
|
43 |
+
output_file_path = "{}{}.html".format(path, file_uid)
|
44 |
+
|
45 |
+
compiler.compile(input_file_path, output_file_path, rendering_function=render_content_with_text)
|
model.py
ADDED
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import torch.nn as nn
|
2 |
+
import torch.nn.functional as F
|
3 |
+
import torch
|
4 |
+
|
5 |
+
class ImageEncoder(nn.Module):
|
6 |
+
|
7 |
+
def __init__(self):
|
8 |
+
super(ImageEncoder, self).__init__()
|
9 |
+
self.conv1 = nn.Conv2d(3, 32, 3)
|
10 |
+
self.conv2 = nn.Conv2d(32, 32, 3)
|
11 |
+
self.conv3 = nn.Conv2d(32, 64, 3)
|
12 |
+
self.conv4 = nn.Conv2d(64, 64, 3)
|
13 |
+
self.conv5 = nn.Conv2d(64, 128, 3)
|
14 |
+
self.conv6 = nn.Conv2d(128, 128, 3)
|
15 |
+
self.fc1 = nn.Linear(in_features=128*28*28, out_features=1024)
|
16 |
+
self.fc2 = nn.Linear(in_features=1024, out_features=1024)
|
17 |
+
|
18 |
+
def forward(self, x):
|
19 |
+
# x -> [-1, 3, 256, 256]
|
20 |
+
|
21 |
+
x = F.relu(self.conv1(x))
|
22 |
+
# x -> [-1, 32, 254, 254]
|
23 |
+
x = F.relu(self.conv2(x))
|
24 |
+
# x -> [-1, 32, 252, 252]
|
25 |
+
x = F.max_pool2d(x, 2)
|
26 |
+
# x -> [-1, 32, 126, 126]
|
27 |
+
|
28 |
+
x = F.relu(self.conv3(x))
|
29 |
+
# x -> [-1, 64, 124, 124]
|
30 |
+
x = F.relu(self.conv4(x))
|
31 |
+
# x -> [-1, 64, 122, 122]
|
32 |
+
x = F.max_pool2d(x, 2)
|
33 |
+
# x -> [-1, 64, 61, 61]
|
34 |
+
|
35 |
+
x = F.relu(self.conv5(x))
|
36 |
+
# x -> [-1, 128, 59, 59]
|
37 |
+
x = F.relu(self.conv6(x))
|
38 |
+
# x -> [-1, 128, 57, 57]
|
39 |
+
x = F.max_pool2d(x, 2)
|
40 |
+
# x -> [-1, 128, 28, 28]
|
41 |
+
|
42 |
+
x = x.view(-1, 128*28*28)
|
43 |
+
x = F.relu(self.fc1(x))
|
44 |
+
x = F.relu(self.fc2(x))
|
45 |
+
return x
|
46 |
+
|
47 |
+
class ContextEncoder(nn.Module):
|
48 |
+
|
49 |
+
def __init__(self):
|
50 |
+
super(ContextEncoder, self).__init__()
|
51 |
+
self.rnn = nn.RNN(input_size=19, hidden_size=128, num_layers=2, batch_first=True)
|
52 |
+
|
53 |
+
def forward(self, x, h=None):
|
54 |
+
# x -> [-1, seq_size, 19], h -> [num_layer=2,-1, 128]
|
55 |
+
|
56 |
+
if not h:
|
57 |
+
h = torch.zeros((2, x.size(0), 128)).cuda()
|
58 |
+
|
59 |
+
x, _ = self.rnn(x, h)
|
60 |
+
return x
|
61 |
+
|
62 |
+
class Decoder(nn.Module):
|
63 |
+
|
64 |
+
def __init__(self):
|
65 |
+
super(Decoder, self).__init__()
|
66 |
+
self.rnn = nn.RNN(input_size=1024+128, hidden_size=512, num_layers=2, batch_first=True)
|
67 |
+
self.l1 = nn.Linear(512, 19)
|
68 |
+
|
69 |
+
def forward(self, image_feature, context_feature, on_cuda = False, h = None):
|
70 |
+
# image_feature -> [-1, 1024], context_feature -> [-1, seq_size=48, 128], h -> [num_layer=2, -1, 512]
|
71 |
+
image_feature = image_feature.unsqueeze(1)
|
72 |
+
# image_feature -> [-1, 1, 1024]
|
73 |
+
image_feature = image_feature.repeat(1, context_feature.size(1), 1)
|
74 |
+
# image_feature -> [-1, seq_size, 1024]
|
75 |
+
x = torch.cat((image_feature, context_feature), 2)
|
76 |
+
# x -> [-1, seq_size=48, 1024+128]
|
77 |
+
|
78 |
+
if not h:
|
79 |
+
h = torch.zeros((2, x.size(0), 512)).cuda()
|
80 |
+
|
81 |
+
x, _ = self.rnn(x, h)
|
82 |
+
x = self.l1(x)
|
83 |
+
# x = F.softmax(x, dim=1)
|
84 |
+
return x
|
85 |
+
|
86 |
+
class Pix2Code(nn.Module):
|
87 |
+
|
88 |
+
def __init__(self):
|
89 |
+
super(Pix2Code, self).__init__()
|
90 |
+
self.image_encoder = ImageEncoder()
|
91 |
+
self.context_encoder = ContextEncoder()
|
92 |
+
self.decoder = Decoder()
|
93 |
+
|
94 |
+
def forward(self, image, context):
|
95 |
+
image_feature = self.image_encoder(image)
|
96 |
+
context_feature = self.context_encoder(context)
|
97 |
+
output = self.decoder(image_feature, context_feature)
|
98 |
+
return output
|
pix2code.ipynb
ADDED
The diff for this file is too large to render.
See raw diff
|
|
pix2code.weights.zip
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:6ebfa081f5e10ca9d0c58d739b71828856c4aa03f55783898772967d2d2bfa08
|
3 |
+
size 422161215
|
util.py
ADDED
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from torch.utils import data
|
2 |
+
import torchvision.transforms as transforms
|
3 |
+
import os
|
4 |
+
import numpy as np
|
5 |
+
from PIL import Image
|
6 |
+
import pickle
|
7 |
+
import torch
|
8 |
+
|
9 |
+
START_TOKEN = '<START>'
|
10 |
+
END_TOKEN = '<END>'
|
11 |
+
PLACEHOLDER = ' '
|
12 |
+
# CONTEXT_LENGTH = 48
|
13 |
+
image_size = 256
|
14 |
+
|
15 |
+
|
16 |
+
class Vocabulary:
|
17 |
+
|
18 |
+
def __init__(self, file_path):
|
19 |
+
self.load_vocab(file_path)
|
20 |
+
self.length = len(self.vocab_to_index)
|
21 |
+
|
22 |
+
def load_vocab(self, file_path):
|
23 |
+
self.vocab_to_index = {}
|
24 |
+
with open(file_path, 'rb') as vocab_file:
|
25 |
+
self.vocab_to_index = pickle.load(vocab_file)
|
26 |
+
self.index_to_vocab = {value:key for key, value in self.vocab_to_index.items()}
|
27 |
+
|
28 |
+
def to_vec(self, word):
|
29 |
+
vec = np.zeros(self.length)
|
30 |
+
vec[self.vocab_to_index[word]] = 1
|
31 |
+
return vec
|
32 |
+
|
33 |
+
def to_vocab(self, index):
|
34 |
+
return self.index_to_vocab[index]
|
35 |
+
|
36 |
+
class UIDataset(data.Dataset):
|
37 |
+
|
38 |
+
def __init__(self, file_path, vocab_file_path):
|
39 |
+
self.file_path = file_path
|
40 |
+
self.paths = []
|
41 |
+
self.get_paths()
|
42 |
+
self.transform = transforms.Compose([
|
43 |
+
transforms.Resize([image_size, image_size]),
|
44 |
+
transforms.ToTensor(),
|
45 |
+
])
|
46 |
+
self.vocab = Vocabulary(vocab_file_path)
|
47 |
+
|
48 |
+
def get_paths(self):
|
49 |
+
for f in os.listdir(self.file_path):
|
50 |
+
if f.find('.gui') != -1:
|
51 |
+
file_name = f[:f.find('.gui')]
|
52 |
+
if os.path.isfile('{}/{}.png'.format(self.file_path, file_name)):
|
53 |
+
self.paths.append(file_name)
|
54 |
+
|
55 |
+
def __len__(self):
|
56 |
+
return(len(self.paths))
|
57 |
+
|
58 |
+
def __getitem__(self, index):
|
59 |
+
image = self.transform(Image.open('{}/{}.png'.format(self.file_path, self.paths[index])))[:-1]
|
60 |
+
context, prediction = self.read_gui('{}/{}.gui'.format(self.file_path, self.paths[index]))
|
61 |
+
return image, context, prediction
|
62 |
+
|
63 |
+
def read_gui(self, file_path):
|
64 |
+
context = []
|
65 |
+
prediction = []
|
66 |
+
|
67 |
+
# Tokenize the target code and ads start and end token
|
68 |
+
token_sequence = [PLACEHOLDER]
|
69 |
+
token_sequence.append(START_TOKEN)
|
70 |
+
with open(file_path, 'r') as f:
|
71 |
+
for line in f:
|
72 |
+
line = line.replace(',', ' ,').replace('\n', ' \n')
|
73 |
+
tokens = line.split(' ')
|
74 |
+
for token in tokens:
|
75 |
+
token_sequence.append(token)
|
76 |
+
token_sequence.append(END_TOKEN)
|
77 |
+
|
78 |
+
# Generates cotext prediction pair
|
79 |
+
context = token_sequence[:-1]
|
80 |
+
prediction = token_sequence[1:]
|
81 |
+
|
82 |
+
# suffix = [PLACEHOLDER] * CONTEXT_LENGTH
|
83 |
+
# a = np.concatenate([suffix, token_sequence])
|
84 |
+
# for j in range(len(token_sequence)):
|
85 |
+
# # context.append(a[j:j + CONTEXT_LENGTH])
|
86 |
+
# context.append(a[j])
|
87 |
+
# prediction.append(a[j + CONTEXT_LENGTH])
|
88 |
+
|
89 |
+
# One hot encoding
|
90 |
+
prediction_vec = []
|
91 |
+
for word in prediction:
|
92 |
+
prediction_vec.append(self.vocab.to_vec(word))
|
93 |
+
context_vec = []
|
94 |
+
for word in context:
|
95 |
+
context_vec.append(self.vocab.to_vec(word))
|
96 |
+
|
97 |
+
return torch.tensor(context_vec, dtype=torch.float), torch.tensor(prediction_vec, dtype=torch.float)
|
voc.pkl
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:cbd452e4523519da80b8dd317f2a2c617f1e41a94594fe18047dd3e6de53f9cd
|
3 |
+
size 1287
|