aiqtech/PoseMaker2
0
1import gradio as gr2import json as js3import util4from fastapi.staticfiles import StaticFiles5from fileservice import app6from pose import infer, draw7 8 9def image_changed(image):10 if image == None:11 return "estimation", {}12 13 if 'openpose' in image.info:14 print("pose found")15 jsonText = image.info['openpose']16 jsonObj = js.loads(jsonText)17 subset = jsonObj['subset']18 return f"""{image.width}px x {image.height}px, {len(subset)} indivisual(s)""", jsonText19 else:20 print("pose not found")21 pose_result, returned_outputs = infer(util.pil2cv(image))22 23 candidate = []24 subset = []25 for d in pose_result:26 n = len(candidate)27 if d['bbox'][4] < 0.9: 28 continue29 keypoints = d['keypoints'][:, :2].tolist()30 midpoint = [(keypoints[5][0] + keypoints[6][0]) / 2, (keypoints[5][1] + keypoints[6][1]) / 2]31 keypoints.append(midpoint)32 candidate.extend(util.convert_keypoints(keypoints))33 m = len(candidate)34 subset.append([j for j in range(n, m)])35 36 jsonText = "{ \"candidate\": " + util.candidate_to_json_string(candidate) + ", \"subset\": " + util.subset_to_json_string(subset) + " }"37 return f"""{image.width}px x {image.height}px, {len(subset)} indivisual(s)""", jsonText38 39html_text = f"""40 <canvas id="canvas" width="512" height="512"></canvas><img id="canvas-background" style="display:none;"/>41"""42 43with gr.Blocks(css="""button { min-width: 80px; }""") as demo:44 with gr.Row():45 with gr.Column(scale=1):46 width = gr.Slider(label="Width", minimum=512, maximum=1024, step=64, value=512, interactive=True)47 height = gr.Slider(label="Height", minimum=512, maximum=1024, step=64, value=512, interactive=True)48 with gr.Accordion(label="Pose estimation", open=False):49 source = gr.Image(type="pil")50 estimationResult = gr.Markdown("""estimation""")51 with gr.Row():52 with gr.Column(min_width=80):53 applySizeBtn = gr.Button(value="Apply size")54 with gr.Column(min_width=80):55 replaceBtn = gr.Button(value="Replace")56 with gr.Column(min_width=80):57 importBtn = gr.Button(value="Import")58 with gr.Column(min_width=80):59 bgBtn = gr.Button(value="Background")60 with gr.Column(min_width=80):61 removeBgBtn = gr.Button(value="RemoveBG")62 with gr.Accordion(label="Json", open=False):63 with gr.Row():64 with gr.Column(min_width=80):65 replaceWithJsonBtn = gr.Button(value="Replace")66 with gr.Column(min_width=80):67 importJsonBtn = gr.Button(value="Import")68 gr.Markdown("""69| inout | how to |70| -----------------| ----------------------------------------------------------------------------------------- |71| Import | Paste json to "Json source" and click "Read", edit the width/height, then click "Replace" or "Import". |72| Export | click "Save" and "Copy to clipboard" of "Json" section. |73""")74 json = gr.JSON(label="Json")75 jsonSource = gr.Textbox(label="Json source", lines=10)76 with gr.Accordion(label="Notes", open=False):77 gr.Markdown("""78#### How to bring pose to ControlNet791. Press **Save** button802. **Drag** the file placed at the bottom left corder of browser813. **Drop** the file into ControlNet82 83#### Reuse pose image84Pose image generated by this tool has pose data in the image itself. You can reuse pose information by loading it as the image source instead of a regular image.85 86#### Points to note for pseudo-3D rotation87When 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.88 89#### Pose estimation90In this project, MMPose is used for pose estimation.91""")92 with gr.Column(scale=2):93 html = gr.HTML(html_text)94 with gr.Row():95 with gr.Column(scale=1, min_width=60):96 saveBtn = gr.Button(value="Save")97 with gr.Column(scale=7):98 gr.Markdown("""99- "ctrl + drag" to **scale**100- "alt + drag" to **move**101- "shift + drag" to **rotate** (move right first, release shift, then up or down)102- "space + drag" to **range-move**103- "[", "]" or "Alt + wheel" or "Space + wheel" to shrink or expand **range**104- "ctrl + Z", "shift + ctrl + Z" to **undo**, **redo**105- "ctrl + E" **add** new person106- "D + click" to **delete** person107- "Q + click" to **cut off** limb108- "X + drag" to **x-axis** pseudo-3D rotation109- "C + drag" to **y-axis** pseudo-3D rotation110- "R + click" to **repair**111- "H + click" to **hide** node112 113When using Q, X, C, R, pressing and dont release until the operation is complete.114 115[Contact us for feature requests or bug reports (anonymous)](https://t.co/UC3jJOJJtS)116""")117 118 width.change(fn=None, inputs=[width], _js="(w) => { resizeCanvas(w,null); }")119 height.change(fn=None, inputs=[height], _js="(h) => { resizeCanvas(null,h); }")120 121 source.change(122 fn = image_changed,123 inputs = [source],124 outputs = [estimationResult, json])125 applySizeBtn.click(126 fn = lambda x: (x.width, x.height),127 inputs = [source], 128 outputs = [width, height])129 replaceBtn.click(130 fn = None,131 inputs = [json],132 outputs = [],133 _js="(json) => { initializeEditor(); importPose(json); return []; }")134 importBtn.click(135 fn = None,136 inputs = [json],137 outputs = [],138 _js="(json) => { importPose(json); return []; }")139 bgBtn.click(140 fn = None,141 inputs = [source],142 outputs = [],143 _js="(image) => { importBackground(image); return []; }")144 removeBgBtn.click(145 fn = None,146 inputs = [],147 outputs = [],148 _js="() => { importBackground(null); return []; }")149 150 saveBtn.click(151 fn = None,152 inputs = [], outputs = [json],153 _js="() => { return savePose(); }")154 jsonSource.change(155 fn = lambda x: x,156 inputs = [jsonSource], outputs = [json])157 replaceWithJsonBtn.click(158 fn = None,159 inputs = [json],160 outputs = [],161 _js="(json) => { initializeEditor(); importPose(json); return []; }")162 importJsonBtn.click(163 fn = None,164 inputs = [json],165 outputs = [],166 _js="(json) => { importPose(json); return []; }")167 demo.load(fn=None, inputs=[], outputs=[], _js="() => { initializeEditor(); importPose(); return []; }")168 169print("mount")170app.mount("/js", StaticFiles(directory="js"), name="js")171gr.mount_gradio_app(app, demo, path="/")172 