|
1 |
| -# MetaBoard |
2 |
| - |
3 |
| -## Data Structure |
4 |
| -### Explore |
5 |
| -```javascript |
6 |
| -input: img_name |
7 |
| -return: a dictionary |
8 |
| -d = { |
9 |
| - "name": "01.jpg", |
10 |
| - "keywords": ["xxx", "health", "health", "health"], |
11 |
| - "width": 276, |
12 |
| - "height": 180, |
13 |
| - "semantic": [{ |
14 |
| - "name": "000e74ea347f08c0cae2b3cfc4f612cf.jpg", |
15 |
| - "keywords": ["xxx", "health", "health", "health"], |
16 |
| - "width": 276, |
17 |
| - "height": 180 |
18 |
| - }, { |
19 |
| - "name": "00a8885948a4a3abed0a27480c9f3fa6.png", |
20 |
| - "keywords": ["xxx", "health", "health", "health"], |
21 |
| - "width": 240, |
22 |
| - "height": 180 |
23 |
| - }, { |
24 |
| - "name": "00a5155ce76792c8aaef4bd67e2d4f44.jpg", |
25 |
| - "keywords": ["xxx", "health", "health", "health"], |
26 |
| - "width": 232, |
27 |
| - "height": 180 |
28 |
| - }], |
29 |
| - "color": [{ |
30 |
| - "name": "00ab0fe3d1d76da690d7438117eeea49.jpg", |
31 |
| - "keywords": ["xxx", "health", "health", "health"], |
32 |
| - "width": 270, |
33 |
| - "height": 180 |
34 |
| - }, { |
35 |
| - "name": "00e43e295097e2580d0178cb3cadd04b.jpg", |
36 |
| - "keywords": ["xxx", "health", "health", "health"], |
37 |
| - "width": 131, |
38 |
| - "height": 180 |
39 |
| - }], |
40 |
| - "shape": [{ |
41 |
| - "name": "00daeeb00b31e6f7fd9bf103a1733560.jpg", |
42 |
| - "keywords": ["xxx", "health", "health", "health"], |
43 |
| - "width": 131, |
44 |
| - "height": 180 |
45 |
| - }, { |
46 |
| - "name": "00dddfdfe4ad349925af78c3d04533f9.jpg", |
47 |
| - "keywords": ["xxx", "health", "health", "health"], |
48 |
| - "width": 116, |
49 |
| - "height": 180 |
50 |
| - }], |
51 |
| - "status": "xxx" |
52 |
| - } |
53 |
| -``` |
| 1 | +# MetaMap: Supporting Visual Metaphor Ideation through Multi-dimensional Example-based Exploration |
54 | 2 |
|
55 |
| -### 前端图树状态存储 |
56 |
| -树的结构长这样 |
57 |
| -```javascript |
58 |
| -{ |
59 |
| - id: 0, |
60 |
| - images: [ { name: '01.jpg', keywords: ['fuck'], width: 200, height: 200 } ], |
61 |
| - imageIndex: 0, |
62 |
| - semantic: { |
63 |
| - id: 1, |
64 |
| - images: [ |
65 |
| - { |
66 |
| - name: "000e74ea347f08c0cae2b3cfc4f612cf.jpg", |
67 |
| - keywords: ["xxx", "health", "health", "health"], |
68 |
| - width: 276, |
69 |
| - height: 180 |
70 |
| - }, |
71 |
| - { |
72 |
| - name: "00a8885948a4a3abed0a27480c9f3fa6.png", |
73 |
| - keywords: ["xxx", "health", "health", "health"], |
74 |
| - width: 240, |
75 |
| - height: 180 |
76 |
| - }, |
77 |
| - { |
78 |
| - name: "00a5155ce76792c8aaef4bd67e2d4f44.jpg", |
79 |
| - keywords: ["xxx", "health", "health", "health"], |
80 |
| - width: 232, |
81 |
| - height: 180 |
82 |
| - } |
83 |
| - ], |
84 |
| - imageIndex: 0, |
85 |
| - level: 1, |
86 |
| - x: 200, |
87 |
| - y: -200, |
88 |
| - }, |
89 |
| - color: { |
90 |
| - id: 2, |
91 |
| - images: [ |
92 |
| - { |
93 |
| - name: "00ab0fe3d1d76da690d7438117eeea49.jpg", |
94 |
| - keywords: ["xxx", "health", "health", "health"], |
95 |
| - width: 270, |
96 |
| - height: 180 |
97 |
| - }, |
98 |
| - { |
99 |
| - name: "00e43e295097e2580d0178cb3cadd04b.jpg", |
100 |
| - keywords: ["xxx", "health", "health", "health"], |
101 |
| - width: 131, |
102 |
| - height: 180 |
103 |
| - } |
104 |
| - ], |
105 |
| - imageIndex: 0, |
106 |
| - level: 1, |
107 |
| - x: 200, |
108 |
| - y: 0 |
109 |
| - }, |
110 |
| - shape: { |
111 |
| - id: 3, |
112 |
| - images: [ |
113 |
| - { |
114 |
| - name: "00daeeb00b31e6f7fd9bf103a1733560.jpg", |
115 |
| - keywords: ["xxx", "health", "health", "health"], |
116 |
| - width: 131, |
117 |
| - height: 180 |
118 |
| - }, |
119 |
| - { |
120 |
| - name: "00dddfdfe4ad349925af78c3d04533f9.jpg", |
121 |
| - keywords: ["xxx", "health", "health", "health"], |
122 |
| - width: 116, |
123 |
| - height: 180 |
124 |
| - } |
125 |
| - ], |
126 |
| - imageIndex: 0, |
127 |
| - level: 1, |
128 |
| - x: 200, |
129 |
| - y: 200 |
130 |
| - }, |
131 |
| - level: 0, |
132 |
| - x: 0, |
133 |
| - y: 0 |
134 |
| -} |
135 |
| -``` |
136 |
| -除了数据结构,还有以下方法: |
137 |
| -```javascript |
138 |
| -/* 一个ImageTree实例有以下方法 */ |
139 |
| -get() => TreeNode // 当前树的根节点 |
140 |
| -// 以下都返回执行这次修改后,update过的树的根节点 |
141 |
| -initialize(res) => TreeNode |
142 |
| -remove(id) => TreeNode // throws when id node found |
143 |
| -explore(id, res) => TreeNode // throws when id not found |
144 |
| -// 以下都返回指定id处的节点 |
145 |
| -find(id) => TreeNode | undefined |
146 |
| -findParent(id) => TreeNode | undefined |
147 |
| - |
148 |
| -_updateTreeXY() => number // 一般不需要外部调用,在init, remove, explore的时候会自动调用一次。更新每个节点的的x, y, 返回新的树的层数(从0开始数) |
149 |
| - |
150 |
| -/* 一个TreeNode示例有 */ |
151 |
| -getImage() => Image // 返回当前imageIndex指向的图片 |
152 |
| -nextImage() => Image // 自增imageIndex并返回新图片 |
153 |
| -prevImage() => Image // 自减imageIndex并返回新图片 |
154 |
| -getThreeImages() => [Image, Image, Image] // 返回 [上一张,这一张,下一张] |
155 |
| - |
156 |
| -/* 新增 */ |
157 |
| -setSelectedImage(image) // 传入一个Image object |
158 |
| -getSelectedImage() // get 当前的selectedImage 或者null |
159 |
| -``` |
160 |
| -使用方式如下 |
161 |
| -```javascript |
162 |
| -// 在新tab里面 |
163 |
| -const tree = new ImageTree(res); |
164 |
| -tree.get() // 返回上述数据结构 |
165 |
| -// 或者 |
166 |
| -const tree = new ImageTree(); |
167 |
| -tree.get() // 错误!must initialize a tree first |
168 |
| -tree.inizialize(res) |
169 |
| -tree.get() // OK 返回上述结构 |
170 |
| - |
171 |
| -// 在点击轮播右箭头的时候 |
172 |
| -function handleNextImage(e) { |
173 |
| - // 从e获取轮播框节点id |
174 |
| - const imageObject = tree.find(id).nextImage() |
175 |
| - // 重新设置轮播框的img src=".." |
176 |
| -} |
177 |
| - |
178 |
| -// 在点击explore的时候 |
179 |
| -function handleExplore(e) { |
180 |
| - // 从e获取轮播框节点id |
181 |
| - const imageObject = tree.find(id).getImage() |
182 |
| - sendRequest(imageObject.name).then( |
183 |
| - res => renderTree(tree.explore(id, res)) |
184 |
| - ) |
185 |
| -} |
186 |
| - |
187 |
| -// 在点击remove的时候 |
188 |
| -function handleRemoveImage(e) { |
189 |
| - // 从e获取轮播框节点id |
190 |
| - renderTree(tree.remove(id)) |
191 |
| -} |
192 |
| -``` |
| 3 | +A CHI 2021 work by Kang, Youwen and Sun, Zhida and Wang, Sitong and Huang, Zeyu and Wu, Ziming and Ma, Xiaojuan. |
| 4 | +[DOI: 10.1145/3411764.3445325](https://doi.org/10.1145/3411764.3445325). |
193 | 5 |
|
194 |
| -### Refresh |
195 |
| -* 一起Load到图片坑位,左右轮播 |
| 6 | +## Run |
196 | 7 |
|
197 |
| -### History Record |
198 |
| -* 保留搜索记录(包括keyword collection的点击结果和search input) |
| 8 | +1. Download the source code, the database and the images from release. (Cloning the project is not advised, as historical git snapshots contain the entire image database and is huge.) (No kidding, ~2.5G.) |
| 9 | +2. Put `database.db` at project root. Extract the `img` folder to `<project>/app/static/`. |
| 10 | +The final structure looks like |
| 11 | +``` |
| 12 | +<project> |
| 13 | +├─run.py |
| 14 | +├─database.db |
| 15 | +├─app |
| 16 | +│ ├─static |
| 17 | +│ │ ├─img |
| 18 | +│ │ │ └─*.{jpg|png} |
| 19 | +│ │ └─... |
| 20 | +│ └─... |
| 21 | +└─... |
| 22 | +``` |
| 23 | +3. Install the dependencies. Eveyr dependency is explicitly imported at the top of `app/run.py`. You can install them manually. |
| 24 | +As a `conda` alternate, you can run `conda env create -f environment.yml` in the project root directory to create an environment named *metamap* |
| 25 | +with required dependencies. |
| 26 | +4. `cd` to the project root and run `python run.py`. The webapp will be hosted on 5000 by default. |
| 27 | + |
| 28 | +## Note |
| 29 | + |
| 30 | +Start by entering search keywords on the top left. |
| 31 | +Available keywords including *bike*, *mental*, *clock*... |
| 32 | +More possible keywords will show up beneath the input area after clicking the search button. |
| 33 | +Clicking on any color on the palette will sort images in that order. |
| 34 | + |
| 35 | +Clicking an image on the bottom left will put it to the main canvas. |
| 36 | +Click on it on the main canvas to expand operations. |
| 37 | +Clicking on the tag on its left to "explore". |
| 38 | +(There is still room for optimizations. |
| 39 | +Please bear with slow responses if the exploration results |
| 40 | +do not show up after 6+ seconds. They will eventually show up if you have clicked once.) |
| 41 | + |
| 42 | +On the right three carousels will appear. |
| 43 | +Hover on them and use the arrow buttons to navigate. |
| 44 | +Alternatively, drag or click on the horizontal scroll bar to navigate. |
| 45 | +Click on an image to select and show its keywords. |
| 46 | +Click on any keywords to further explore from it. |
199 | 47 |
|
200 | 48 | ## Functions
|
201 | 49 |
|
|
0 commit comments