Spaces:
Runtime error
Runtime error
add repair
Browse files- app.py +1 -1
- static/poseEditor.js +57 -9
app.py
CHANGED
@@ -126,7 +126,7 @@ with gr.Blocks(css="""button { min-width: 80px; }""") as demo:
|
|
126 |
- "q + click" to delete person
|
127 |
- "x + drag" to x-axis pseudo-3D rotation
|
128 |
- "c + drag" to y-axis pseudo-3D rotation
|
129 |
-
|
130 |
Points to note for pseudo-3D rotation: When performing pseudo-3D rotation on the X and Y axes, the projection is converted to 2D and Z-axis information is lost when the mouse button is released. This means that if you finish dragging while the shape is collapsed, you may not be able to restore it to its original state. In such a case, please use the "undo" function.
|
131 |
""")
|
132 |
|
|
|
126 |
- "q + click" to delete person
|
127 |
- "x + drag" to x-axis pseudo-3D rotation
|
128 |
- "c + drag" to y-axis pseudo-3D rotation
|
129 |
+
- "r + click" to repair
|
130 |
Points to note for pseudo-3D rotation: When performing pseudo-3D rotation on the X and Y axes, the projection is converted to 2D and Z-axis information is lost when the mouse button is released. This means that if you finish dragging while the shape is collapsed, you may not be able to restore it to its original state. In such a case, please use the "undo" function.
|
131 |
""")
|
132 |
|
static/poseEditor.js
CHANGED
@@ -2,6 +2,53 @@ console.log("hello from poseEditor.js")
|
|
2 |
var canvas = null;
|
3 |
var ctx = null;
|
4 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
function deepCopy(arr) {
|
6 |
return JSON.parse(JSON.stringify(arr));
|
7 |
}
|
@@ -68,6 +115,12 @@ function removePerson(personIndex) {
|
|
68 |
Redraw();
|
69 |
}
|
70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
71 |
// ドラッグ中の各キーが押されているかどうかのフラグ
|
72 |
var keyDownFlags = {};
|
73 |
// マウスカーソル
|
@@ -158,9 +211,6 @@ function rotateAndProject(f, p, c, angle) {
|
|
158 |
|
159 |
function drawBodyPose() {
|
160 |
const stickWidth = 6;
|
161 |
-
const limbSeq = [[2, 3], [2, 6], [3, 4], [4, 5], [6, 7], [7, 8], [2, 9], [9, 10],
|
162 |
-
[10, 11], [2, 12], [12, 13], [13, 14], [2, 1], [1, 15], [15, 17],
|
163 |
-
[1, 16], [16, 18], [3, 17], [6, 18]];
|
164 |
|
165 |
const colors = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 255, 0], [170, 255, 0], [85, 255, 0], [0, 255, 0],
|
166 |
[0, 255, 85], [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], [0, 0, 255], [85, 0, 255],
|
@@ -173,8 +223,8 @@ function drawBodyPose() {
|
|
173 |
|
174 |
// edge
|
175 |
for (let j = 0; j < 17; j++) {
|
176 |
-
const p = pose[limbSeq[j][0]
|
177 |
-
const q = pose[limbSeq[j][1]
|
178 |
if (p == null || q == null) continue;
|
179 |
const [X0, Y0] = p;
|
180 |
const [X1, Y1] = q;
|
@@ -317,10 +367,8 @@ function handleMouseDown(event) {
|
|
317 |
const p = getCanvasPosition(event);
|
318 |
const [personIndex, nodeIndex, minDist] = getNearestNode(p);
|
319 |
|
320 |
-
if (keyDownFlags["KeyQ"]) {
|
321 |
-
|
322 |
-
return;
|
323 |
-
}
|
324 |
|
325 |
// ドラッグ処理の開始
|
326 |
dragStart = p;
|
|
|
2 |
var canvas = null;
|
3 |
var ctx = null;
|
4 |
|
5 |
+
const limbSeq = [
|
6 |
+
[1, 2], [2, 3], [3, 4], // 右腕
|
7 |
+
[1, 5], [5, 6], [6, 7], // 左腕
|
8 |
+
[1, 8], [8, 9], [9, 10], // 右胴→右脚
|
9 |
+
[1, 11], [11, 12], [12, 13], // 左胴→左脚
|
10 |
+
[1, 0], // 首
|
11 |
+
[0, 14], [14, 16], // 右目
|
12 |
+
[0, 15], [15, 17] // 左目
|
13 |
+
];
|
14 |
+
|
15 |
+
function findParentNodeIndex(nodeIndex) {
|
16 |
+
// limbSeqの各要素の2番目の要素がjointIndexの場合、その要素の1番目の要素を返す
|
17 |
+
// 見つからないばあいは-1を返す
|
18 |
+
limbIndex = limbSeq.findIndex((limb) => limb[1] === nodeIndex);
|
19 |
+
return limbIndex === -1 ? -1 : limbSeq[limbIndex][0];
|
20 |
+
}
|
21 |
+
|
22 |
+
function repairPose(sourcePose) {
|
23 |
+
// TODO: ループには対応してないかも
|
24 |
+
var pose = sourcePose;
|
25 |
+
var newPose = new Array(18)
|
26 |
+
for (var k = 0; k < 3; k++) {
|
27 |
+
var processed = 0; // イテレーション用
|
28 |
+
for (let i = 0; i < 18; i++) {
|
29 |
+
if (pose[i] == null) {
|
30 |
+
let parent = findParentNodeIndex(i);
|
31 |
+
if (parent === -1) {continue;} // あり得ない
|
32 |
+
if (pose[parent] == null) {
|
33 |
+
console.log(`repair failed(A): ${i} -> parent loss`);
|
34 |
+
continue;
|
35 |
+
}
|
36 |
+
|
37 |
+
// サンプルデータから引っ張ってくる
|
38 |
+
var v = sampleCandidateSource[i].map((x, j) => x - sampleCandidateSource[parent][j]);
|
39 |
+
newPose[i] = pose[parent].map((x, j) => x + v[j]);
|
40 |
+
console.log(`repaired: ${i} -> ${newPose[newPose.length - 1]}`);
|
41 |
+
processed++;
|
42 |
+
} else {
|
43 |
+
newPose[i] = pose[i].map(x => x);
|
44 |
+
}
|
45 |
+
}
|
46 |
+
if (processed === 0) {break;}
|
47 |
+
pose = newPose;
|
48 |
+
}
|
49 |
+
return newPose;
|
50 |
+
}
|
51 |
+
|
52 |
function deepCopy(arr) {
|
53 |
return JSON.parse(JSON.stringify(arr));
|
54 |
}
|
|
|
115 |
Redraw();
|
116 |
}
|
117 |
|
118 |
+
function repairPerson(personIndex) {
|
119 |
+
poseData[personIndex] = repairPose(poseData[personIndex]);
|
120 |
+
addHistory();
|
121 |
+
Redraw();
|
122 |
+
}
|
123 |
+
|
124 |
// ドラッグ中の各キーが押されているかどうかのフラグ
|
125 |
var keyDownFlags = {};
|
126 |
// マウスカーソル
|
|
|
211 |
|
212 |
function drawBodyPose() {
|
213 |
const stickWidth = 6;
|
|
|
|
|
|
|
214 |
|
215 |
const colors = [[255, 0, 0], [255, 85, 0], [255, 170, 0], [255, 255, 0], [170, 255, 0], [85, 255, 0], [0, 255, 0],
|
216 |
[0, 255, 85], [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], [0, 0, 255], [85, 0, 255],
|
|
|
223 |
|
224 |
// edge
|
225 |
for (let j = 0; j < 17; j++) {
|
226 |
+
const p = pose[limbSeq[j][0]];
|
227 |
+
const q = pose[limbSeq[j][1]];
|
228 |
if (p == null || q == null) continue;
|
229 |
const [X0, Y0] = p;
|
230 |
const [X1, Y1] = q;
|
|
|
367 |
const p = getCanvasPosition(event);
|
368 |
const [personIndex, nodeIndex, minDist] = getNearestNode(p);
|
369 |
|
370 |
+
if (keyDownFlags["KeyQ"]) {removePerson(personIndex);return;}
|
371 |
+
if (keyDownFlags["KeyR"]) {repairPerson(personIndex);return;}
|
|
|
|
|
372 |
|
373 |
// ドラッグ処理の開始
|
374 |
dragStart = p;
|