Spaces:
Runtime error
Runtime error
fix import
Browse files- app.py +36 -11
- static/poseEditor.js +25 -17
app.py
CHANGED
@@ -70,24 +70,35 @@ def estimate_body(source):
|
|
70 |
|
71 |
def image_changed(image):
|
72 |
if (image == None):
|
73 |
-
return {}
|
74 |
-
|
75 |
-
|
|
|
|
|
|
|
|
|
|
|
76 |
|
77 |
html_text = f"""
|
78 |
<canvas id="canvas" width="512" height="512"></canvas>
|
79 |
<script type="text/javascript" defer>{file_contents}</script>
|
80 |
"""
|
81 |
|
82 |
-
with gr.Blocks() as demo:
|
83 |
with gr.Row():
|
84 |
with gr.Column(scale=1):
|
85 |
-
startBtn = gr.Button(value="Start edit")
|
86 |
width = gr.Slider(label="Width", minimum=512, maximum=1024, step=64, value=512, interactive=True)
|
87 |
height = gr.Slider(label="Height", minimum=512, maximum=1024, step=64, value=512, interactive=True)
|
88 |
with gr.Accordion(label="Pose estimation", open=False):
|
89 |
source = gr.Image(type="pil")
|
90 |
-
gr.Markdown("""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
91 |
with gr.Accordion(label="Json", open=False):
|
92 |
gr.Markdown("""
|
93 |
| inout | how to |
|
@@ -101,7 +112,7 @@ with gr.Blocks() as demo:
|
|
101 |
with gr.Column(scale=2):
|
102 |
html = gr.HTML(html_text)
|
103 |
with gr.Row():
|
104 |
-
with gr.Column(scale=1):
|
105 |
saveBtn = gr.Button(value="Save")
|
106 |
with gr.Column(scale=7):
|
107 |
gr.Markdown("""
|
@@ -119,15 +130,28 @@ with gr.Blocks() as demo:
|
|
119 |
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.
|
120 |
""")
|
121 |
|
|
|
|
|
|
|
122 |
source.change(
|
123 |
fn = image_changed,
|
124 |
inputs = [source],
|
125 |
-
outputs = [
|
126 |
-
|
|
|
|
|
|
|
|
|
127 |
fn = None,
|
128 |
-
inputs = [json
|
129 |
outputs = [],
|
130 |
-
_js="(json
|
|
|
|
|
|
|
|
|
|
|
|
|
131 |
saveBtn.click(
|
132 |
fn = None,
|
133 |
inputs = [], outputs = [json],
|
@@ -135,5 +159,6 @@ Points to note for pseudo-3D rotation: When performing pseudo-3D rotation on the
|
|
135 |
jsonInputBtn.click(
|
136 |
fn = lambda x: x,
|
137 |
inputs = [jsonInput], outputs = [json])
|
|
|
138 |
|
139 |
gr.mount_gradio_app(app, demo, path="/")
|
|
|
70 |
|
71 |
def image_changed(image):
|
72 |
if (image == None):
|
73 |
+
return "estimation", {}
|
74 |
+
|
75 |
+
#json = estimate_body(image)
|
76 |
+
candidate, subset = body_estimation(pil2cv(image))
|
77 |
+
print(subset.shape)
|
78 |
+
json = "{ \"candidate\": " + candidate_to_json_string(candidate) + ", \"subset\": " + subset_to_json_string(subset) + " }"
|
79 |
+
|
80 |
+
return f"""{image.width}px x {image.height}px, {subset.shape[0]} indivisual(s)""", json
|
81 |
|
82 |
html_text = f"""
|
83 |
<canvas id="canvas" width="512" height="512"></canvas>
|
84 |
<script type="text/javascript" defer>{file_contents}</script>
|
85 |
"""
|
86 |
|
87 |
+
with gr.Blocks(css="""button { min-width: 80px; }""") as demo:
|
88 |
with gr.Row():
|
89 |
with gr.Column(scale=1):
|
|
|
90 |
width = gr.Slider(label="Width", minimum=512, maximum=1024, step=64, value=512, interactive=True)
|
91 |
height = gr.Slider(label="Height", minimum=512, maximum=1024, step=64, value=512, interactive=True)
|
92 |
with gr.Accordion(label="Pose estimation", open=False):
|
93 |
source = gr.Image(type="pil")
|
94 |
+
estimationResult = gr.Markdown("""estimation""")
|
95 |
+
with gr.Row():
|
96 |
+
with gr.Column(min_width=80):
|
97 |
+
applySizeBtn = gr.Button(value="Apply size")
|
98 |
+
with gr.Column(min_width=80):
|
99 |
+
replaceBtn = gr.Button(value="Replace")
|
100 |
+
with gr.Column(min_width=80):
|
101 |
+
importBtn = gr.Button(value="Import")
|
102 |
with gr.Accordion(label="Json", open=False):
|
103 |
gr.Markdown("""
|
104 |
| inout | how to |
|
|
|
112 |
with gr.Column(scale=2):
|
113 |
html = gr.HTML(html_text)
|
114 |
with gr.Row():
|
115 |
+
with gr.Column(scale=1, min_width=60):
|
116 |
saveBtn = gr.Button(value="Save")
|
117 |
with gr.Column(scale=7):
|
118 |
gr.Markdown("""
|
|
|
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 |
|
133 |
+
width.change(fn=None, inputs=[width], _js="(w) => { resizeCanvas(w,null); }")
|
134 |
+
height.change(fn=None, inputs=[height], _js="(h) => { resizeCanvas(null,h); }")
|
135 |
+
|
136 |
source.change(
|
137 |
fn = image_changed,
|
138 |
inputs = [source],
|
139 |
+
outputs = [estimationResult, json])
|
140 |
+
applySizeBtn.click(
|
141 |
+
fn = lambda x: (x.width, x.height),
|
142 |
+
inputs = [source],
|
143 |
+
outputs = [width, height])
|
144 |
+
replaceBtn.click(
|
145 |
fn = None,
|
146 |
+
inputs = [json],
|
147 |
outputs = [],
|
148 |
+
_js="(json) => { initializeEditor(); importPose(json); return []; }")
|
149 |
+
importBtn.click(
|
150 |
+
fn = None,
|
151 |
+
inputs = [json],
|
152 |
+
outputs = [],
|
153 |
+
_js="(json) => { importPose(json); return []; }")
|
154 |
+
|
155 |
saveBtn.click(
|
156 |
fn = None,
|
157 |
inputs = [], outputs = [json],
|
|
|
159 |
jsonInputBtn.click(
|
160 |
fn = lambda x: x,
|
161 |
inputs = [jsonInput], outputs = [json])
|
162 |
+
demo.load(fn=None, inputs=[], outputs=[], _js="() => { initializeEditor(); importPose(); return []; }")
|
163 |
|
164 |
gr.mount_gradio_app(app, demo, path="/")
|
static/poseEditor.js
CHANGED
@@ -40,7 +40,7 @@ function makePoseFromCandidateAndSubsetElement(candidate, subsetElement) {
|
|
40 |
var pose = [];
|
41 |
for (let j = 0 ; j < 18; j++) {
|
42 |
let i = subsetElement[j];
|
43 |
-
pose.push(i < 0 ? null : candidate[i]);
|
44 |
}
|
45 |
return pose;
|
46 |
}
|
@@ -87,14 +87,15 @@ function clearCanvas() {
|
|
87 |
function resizeCanvas(width, height) {
|
88 |
canvas.width = width ? width : canvas.width;
|
89 |
canvas.height = height ? height : canvas.height;
|
90 |
-
|
91 |
-
drawBodyPose();
|
92 |
}
|
93 |
|
94 |
function calculateCenter(shape) {
|
95 |
var center = shape.reduce(function(acc, point) {
|
96 |
-
|
97 |
-
|
|
|
|
|
98 |
return acc;
|
99 |
}, [0, 0]);
|
100 |
center[0] /= shape.length;
|
@@ -169,7 +170,6 @@ function drawBodyPose() {
|
|
169 |
|
170 |
for (let i = 0; i < poseData.length; i++) {
|
171 |
const pose = poseData[i];
|
172 |
-
const center = calculateCenter(pose);
|
173 |
|
174 |
// edge
|
175 |
for (let j = 0; j < 17; j++) {
|
@@ -264,6 +264,11 @@ let rotateBaseVector = null;
|
|
264 |
let history = [];
|
265 |
let historyIndex = 0;
|
266 |
|
|
|
|
|
|
|
|
|
|
|
267 |
function addHistory() {
|
268 |
history = history.slice(0, historyIndex);
|
269 |
history.push(JSON.parse(JSON.stringify(poseData)));
|
@@ -456,14 +461,8 @@ document.addEventListener("keyup", (event) => {
|
|
456 |
Redraw();
|
457 |
});
|
458 |
|
459 |
-
function
|
460 |
-
console.log("
|
461 |
-
if (jsonData != null) {
|
462 |
-
poseData = makePoseDataFromCandidateAndSubset(jsonData.candidate, jsonData.subset);
|
463 |
-
} else {
|
464 |
-
poseData = makePoseDataFromCandidateAndSubset(sampleCandidateSource, [sampleSubsetElementSource]);
|
465 |
-
}
|
466 |
-
addHistory();
|
467 |
|
468 |
canvas = document.getElementById('canvas');
|
469 |
ctx = canvas.getContext('2d');
|
@@ -471,10 +470,19 @@ function initializePose(jsonData,w,h) {
|
|
471 |
canvas.addEventListener('mousedown', handleMouseDown);
|
472 |
canvas.addEventListener('mousemove', handleMouseMove);
|
473 |
canvas.addEventListener('mouseup', handleMouseUp);
|
|
|
|
|
|
|
474 |
|
475 |
-
|
476 |
-
|
477 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
478 |
}
|
479 |
|
480 |
function savePose() {
|
|
|
40 |
var pose = [];
|
41 |
for (let j = 0 ; j < 18; j++) {
|
42 |
let i = subsetElement[j];
|
43 |
+
pose.push(i < 0 ? null : candidate[i].map((x)=>x));
|
44 |
}
|
45 |
return pose;
|
46 |
}
|
|
|
87 |
function resizeCanvas(width, height) {
|
88 |
canvas.width = width ? width : canvas.width;
|
89 |
canvas.height = height ? height : canvas.height;
|
90 |
+
Redraw();
|
|
|
91 |
}
|
92 |
|
93 |
function calculateCenter(shape) {
|
94 |
var center = shape.reduce(function(acc, point) {
|
95 |
+
if (point === null) {
|
96 |
+
acc[0] += point[0];
|
97 |
+
acc[1] += point[1];
|
98 |
+
}
|
99 |
return acc;
|
100 |
}, [0, 0]);
|
101 |
center[0] /= shape.length;
|
|
|
170 |
|
171 |
for (let i = 0; i < poseData.length; i++) {
|
172 |
const pose = poseData[i];
|
|
|
173 |
|
174 |
// edge
|
175 |
for (let j = 0; j < 17; j++) {
|
|
|
264 |
let history = [];
|
265 |
let historyIndex = 0;
|
266 |
|
267 |
+
function clearHistory() {
|
268 |
+
history = [];
|
269 |
+
historyIndex = 0;
|
270 |
+
}
|
271 |
+
|
272 |
function addHistory() {
|
273 |
history = history.slice(0, historyIndex);
|
274 |
history.push(JSON.parse(JSON.stringify(poseData)));
|
|
|
461 |
Redraw();
|
462 |
});
|
463 |
|
464 |
+
function initializeEditor() {
|
465 |
+
console.log("initializeEditor");
|
|
|
|
|
|
|
|
|
|
|
|
|
466 |
|
467 |
canvas = document.getElementById('canvas');
|
468 |
ctx = canvas.getContext('2d');
|
|
|
470 |
canvas.addEventListener('mousedown', handleMouseDown);
|
471 |
canvas.addEventListener('mousemove', handleMouseMove);
|
472 |
canvas.addEventListener('mouseup', handleMouseUp);
|
473 |
+
poseData = [];
|
474 |
+
clearHistory();
|
475 |
+
}
|
476 |
|
477 |
+
function importPose(jsonData) {
|
478 |
+
if (jsonData != null) {
|
479 |
+
newPoseData = makePoseDataFromCandidateAndSubset(jsonData.candidate, jsonData.subset);
|
480 |
+
} else {
|
481 |
+
newPoseData = makePoseDataFromCandidateAndSubset(sampleCandidateSource, [sampleSubsetElementSource]);
|
482 |
+
}
|
483 |
+
poseData = poseData.concat(newPoseData);
|
484 |
+
addHistory();
|
485 |
+
Redraw();
|
486 |
}
|
487 |
|
488 |
function savePose() {
|