jonigata commited on
Commit
29f5951
1 Parent(s): 16a0676

add range move

Browse files
Files changed (2) hide show
  1. app.py +7 -1
  2. static/poseEditor.js +120 -61
app.py CHANGED
@@ -105,7 +105,13 @@ To export the pose data, click "Save" and "Copy to clipboard" of "Json" section.
105
  with gr.Column(scale=2):
106
  html = gr.HTML(html_text)
107
  saveBtn = gr.Button(value="Save")
108
- gr.HTML("<ul><li>ctrl + drag to scale</li><li>alt + drag to translate</li><li>shift + drag to rotate(move right first, then up or down)</li></ul>")
 
 
 
 
 
 
109
 
110
  source.change(
111
  fn = image_changed,
 
105
  with gr.Column(scale=2):
106
  html = gr.HTML(html_text)
107
  saveBtn = gr.Button(value="Save")
108
+ gr.Markdown("""
109
+ - "ctrl + drag" to scale
110
+ - "alt + drag" to translate
111
+ - "shift + drag" to rotate(move right first, then up or down)
112
+ - "space + drag" to move within range
113
+ - "[", "]" to shrink or expand range
114
+ """)
115
 
116
  source.change(
117
  fn = image_changed,
static/poseEditor.js CHANGED
@@ -32,6 +32,10 @@ let subset = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 33.
32
 
33
  let candidate = candidateSource.map(point => [point[0], point[1] - 70]);
34
 
 
 
 
 
35
 
36
  function clearCanvas() {
37
  var w = canvas.width;
@@ -93,6 +97,21 @@ function drawBodyPose(candidate, subset) {
93
  }
94
  }
95
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  function getNearestCandidate(x, y) {
97
  let minDist = Infinity;
98
  let minIndex = -1;
@@ -106,6 +125,8 @@ function getNearestCandidate(x, y) {
106
  return [minIndex,minDist];
107
  }
108
 
 
 
109
  // ドラッグ中に座標を保持するための変数
110
  let isDragging = false;
111
  let dragIndex = -1;
@@ -113,6 +134,7 @@ let dragStartX = 0;
113
  let dragStartY = 0;
114
  let draggingCandidate = null;
115
  let dragPersonIndex = -1;
 
116
 
117
  function getCanvasPosition(event) {
118
  const rect = canvas.getBoundingClientRect();
@@ -121,30 +143,6 @@ function getCanvasPosition(event) {
121
  return [x, y];
122
  }
123
 
124
- // Canvas要素上でマウスが押された場合に呼び出される関数
125
- function handleMouseDown(event) {
126
- const [x, y] = getCanvasPosition(event);
127
- const [index, minDist] = getNearestCandidate(x, y);
128
-
129
- // ドラッグ処理の開始
130
- if (event.altKey || event.ctrlKey || event.shiftKey || minDist < 16) {
131
- isDragging = true;
132
- dragIndex = index;
133
- dragStartX = x;
134
- dragStartY = y;
135
- draggingCandidate = JSON.parse(JSON.stringify(candidate))
136
-
137
- // indexが含まれる人間を探す
138
- for (let i = 0; i < subset.length; i++) {
139
- var found = subset[i].indexOf(index);
140
- if (found != -1 && found < 18) {
141
- dragPersonIndex = i;
142
- break;
143
- }
144
- }
145
- }
146
- }
147
-
148
  function forEachCandidateOfPerson(personIndex, callback) {
149
  if (personIndex === -1) { return; }
150
 
@@ -157,55 +155,116 @@ function forEachCandidateOfPerson(personIndex, callback) {
157
  }
158
  }
159
 
160
- // Canvas要素上でマウスが動いた場合に呼び出される関数
161
- function handleMouseMove(event) {
162
- if (!isDragging) {
163
- return;
 
164
  }
 
165
 
 
 
166
  const [x, y] = getCanvasPosition(event);
 
167
 
168
- const dragOffsetX = x - dragStartX;
169
- const dragOffsetY = y - dragStartY;
 
 
 
 
170
 
171
- if (event.ctrlKey) {
172
- // 拡大縮小(人間ごと)
173
- let xScale = 1 + dragOffsetX / canvas.width;
174
- let yScale = 1 + dragOffsetY / canvas.height;
175
- forEachCandidateOfPerson(dragPersonIndex, (index) => {
176
- candidate[index][0] = (draggingCandidate[index][0] - dragStartX) * xScale + dragStartX;
177
- candidate[index][1] = (draggingCandidate[index][1] - dragStartY) * yScale + dragStartY;
178
- });
179
- } else if (event.shiftKey) {
180
- // 回転(人間ごと)
181
- let angle = Math.atan2(dragOffsetY, dragOffsetX);
182
- forEachCandidateOfPerson(dragPersonIndex, (index) => {
183
- let x = draggingCandidate[index][0] - dragStartX;
184
- let y = draggingCandidate[index][1] - dragStartY;
185
- candidate[index][0] = x * Math.cos(angle) - y * Math.sin(angle) + dragStartX;
186
- candidate[index][1] = x * Math.sin(angle) + y * Math.cos(angle) + dragStartY;
187
  });
188
- } else if (event.altKey) {
189
- // 全体移動(人間ごと
190
- forEachCandidateOfPerson(dragPersonIndex, (index) => {
191
- candidate[index][0] = draggingCandidate[index][0] + dragOffsetX;
192
- candidate[index][1] = draggingCandidate[index][1] + dragOffsetY;
 
 
 
 
 
193
  });
194
- } else {
195
- // 個別移動
196
- candidate[dragIndex][0] = draggingCandidate[dragIndex][0] + dragOffsetX;
197
- candidate[dragIndex][1] = draggingCandidate[dragIndex][1] + dragOffsetY;
198
  }
199
-
200
- clearCanvas();
201
- drawBodyPose(candidate, subset);
202
  }
203
 
204
- // Canvas要素上でマウスが離された場合に呼び出される関数
205
- function handleMouseUp(event) {
206
- isDragging = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
207
  }
208
 
 
 
 
 
 
 
 
 
 
 
 
 
 
209
  function initializePose(jsonData,w,h) {
210
  console.log("initializePose");
211
  if (jsonData != null) {
 
32
 
33
  let candidate = candidateSource.map(point => [point[0], point[1] - 70]);
34
 
35
+ // ドラッグ中の各キーが押されているかどうかのフラグ
36
+ var keyDownFlags = {};
37
+ // マウスカーソル
38
+ var mouseCursor = [0, 0];
39
 
40
  function clearCanvas() {
41
  var w = canvas.width;
 
97
  }
98
  }
99
 
100
+ function drawUI() {
101
+ if (keyDownFlags['Space'] || keyDownFlags['BracketLeft'] || keyDownFlags['BracketRight']) {
102
+ ctx.beginPath();
103
+ ctx.arc(mouseCursor[0], mouseCursor[1], dragRange, 0, 2 * Math.PI);
104
+ ctx.strokeStyle = 'rgb(255,255,255)';
105
+ ctx.stroke();
106
+ }
107
+ }
108
+
109
+ function Redraw() {
110
+ clearCanvas();
111
+ drawBodyPose(candidate, subset);
112
+ drawUI();
113
+ }
114
+
115
  function getNearestCandidate(x, y) {
116
  let minDist = Infinity;
117
  let minIndex = -1;
 
125
  return [minIndex,minDist];
126
  }
127
 
128
+ let dragRange = 64;
129
+
130
  // ドラッグ中に座標を保持するための変数
131
  let isDragging = false;
132
  let dragIndex = -1;
 
134
  let dragStartY = 0;
135
  let draggingCandidate = null;
136
  let dragPersonIndex = -1;
137
+ let dragMarks = [];
138
 
139
  function getCanvasPosition(event) {
140
  const rect = canvas.getBoundingClientRect();
 
143
  return [x, y];
144
  }
145
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
146
  function forEachCandidateOfPerson(personIndex, callback) {
147
  if (personIndex === -1) { return; }
148
 
 
155
  }
156
  }
157
 
158
+ function forEachMarkedCandidate(callback) {
159
+ for (let i = 0; i < dragMarks.length; i++) {
160
+ if (dragMarks[i]) {
161
+ callback(i);
162
+ }
163
  }
164
+ }
165
 
166
+ // Canvas要素上でマウスが押された場合に呼び出される関数
167
+ function handleMouseDown(event) {
168
  const [x, y] = getCanvasPosition(event);
169
+ const [index, minDist] = getNearestCandidate(x, y);
170
 
171
+ // ドラッグ処理の開始
172
+ dragIndex = index;
173
+ dragStartX = x;
174
+ dragStartY = y;
175
+ draggingCandidate = JSON.parse(JSON.stringify(candidate))
176
+ dragMarks = new Array(candidate.length).fill(false);
177
 
178
+ // indexが含まれる人間を探す
179
+ for (let i = 0; i < subset.length; i++) {
180
+ var found = subset[i].indexOf(index);
181
+ if (found != -1 && found < 18) {
182
+ dragPersonIndex = i;
183
+ break;
184
+ }
185
+ }
186
+
187
+ if (event.altKey || event.ctrlKey || event.shiftKe) {
188
+ forEachCandidateOfPerson(dragPersonIndex, (i) => {
189
+ dragMarks[i] = true;
 
 
 
 
190
  });
191
+ isDragging = true;
192
+ } else if (keyDownFlags["Space"]) {
193
+ var markCount = 0;
194
+ forEachCandidateOfPerson(dragPersonIndex, (i) => {
195
+ // dragRangeの範囲内のものだけマーク
196
+ let distSq = (candidate[i][0] - x) ** 2 + (candidate[i][1] - y) ** 2;
197
+ if (distSq < dragRange ** 2) {
198
+ dragMarks[i] = true;
199
+ markCount++;
200
+ }
201
  });
202
+ isDragging = 0 < markCount;
203
+ } else if (minDist < 16) {
204
+ dragMarks[index] = true;
205
+ isDragging = true;
206
  }
 
 
 
207
  }
208
 
209
+ // Canvas要素上でマウスが動いた場合に呼び出される関数
210
+ function handleMouseMove(event) {
211
+ mouseCursor = getCanvasPosition(event);
212
+ if (isDragging) {
213
+ const [x, y] = getCanvasPosition(event);
214
+
215
+ const dragOffsetX = x - dragStartX;
216
+ const dragOffsetY = y - dragStartY;
217
+
218
+ if (event.ctrlKey) {
219
+ // 拡大縮小(人間ごと)
220
+ let xScale = 1 + dragOffsetX / canvas.width;
221
+ let yScale = 1 + dragOffsetY / canvas.height;
222
+ forEachMarkedCandidate((index) => {
223
+ candidate[index][0] = (draggingCandidate[index][0] - dragStartX) * xScale + dragStartX;
224
+ candidate[index][1] = (draggingCandidate[index][1] - dragStartY) * yScale + dragStartY;
225
+ });
226
+ } else if (event.shiftKey) {
227
+ // 回転(人間ごと)
228
+ let angle = Math.atan2(dragOffsetY, dragOffsetX);
229
+ forEachMarkedCandidate((index) => {
230
+ let x = draggingCandidate[index][0] - dragStartX;
231
+ let y = draggingCandidate[index][1] - dragStartY;
232
+ candidate[index][0] = x * Math.cos(angle) - y * Math.sin(angle) + dragStartX;
233
+ candidate[index][1] = x * Math.sin(angle) + y * Math.cos(angle) + dragStartY;
234
+ });
235
+ } else if (event.altKey) {
236
+ // 全体移動(人間ごと
237
+ forEachCandidateOfPerson(dragPersonIndex, (index) => {
238
+ candidate[index][0] = draggingCandidate[index][0] + dragOffsetX;
239
+ candidate[index][1] = draggingCandidate[index][1] + dragOffsetY;
240
+ });
241
+ } else {
242
+ // 個別移動
243
+ forEachMarkedCandidate((index) => {
244
+ if (dragMarks[index]) {
245
+ candidate[index][0] = draggingCandidate[index][0] + dragOffsetX;
246
+ candidate[index][1] = draggingCandidate[index][1] + dragOffsetY;
247
+ }
248
+ });
249
+ }
250
+ }
251
+
252
+ Redraw();
253
  }
254
 
255
+ function handleMouseUp(event) { isDragging = false; }
256
+
257
+ document.addEventListener("keydown", (event) => {
258
+ if (event.code == "BracketLeft") {dragRange = Math.max(1, dragRange - 8);}
259
+ if (event.code == "BracketRight") {dragRange = Math.min(256, dragRange + 8);}
260
+ keyDownFlags[event.code] = true;
261
+ Redraw();
262
+ });
263
+ document.addEventListener("keyup", (event) => {
264
+ keyDownFlags[event.code] = false;
265
+ Redraw();
266
+ });
267
+
268
  function initializePose(jsonData,w,h) {
269
  console.log("initializePose");
270
  if (jsonData != null) {