supertori's picture
Upload 215 files
ae26e7d
raw
history blame contribute delete
No virus
17.6 kB
fabric.Object.prototype.transparentCorners = false;
fabric.Object.prototype.cornerColor = '#108ce6';
fabric.Object.prototype.borderColor = '#108ce6';
fabric.Object.prototype.cornerSize = 10;
fabric.Object.prototype.lockRotation = true;
let count = 0;
let executed = false;
let lockMode = false;
const undo_history = [];
const redo_history = [];
coco_body_keypoints = [
"nose",
"neck",
"right_shoulder",
"right_elbow",
"right_wrist",
"left_shoulder",
"left_elbow",
"left_wrist",
"right_hip",
"right_knee",
"right_ankle",
"left_hip",
"left_knee",
"left_ankle",
"right_eye",
"left_eye",
"right_ear",
"left_ear",
]
let connect_keypoints = [[0, 1], [1, 2], [2, 3], [3, 4], [1, 5], [5, 6], [6, 7], [1, 8], [8, 9], [9, 10], [1, 11], [11, 12], [12, 13], [0, 14], [14, 16], [0, 15], [15, 17]]
let connect_color = [[0, 0, 255], [255, 0, 0], [255, 170, 0], [255, 255, 0], [255, 85, 0], [170, 255, 0], [85, 255, 0], [0, 255, 0],
[0, 255, 85], [0, 255, 170], [0, 255, 255], [0, 170, 255], [0, 85, 255], [85, 0, 255],
[170, 0, 255], [255, 0, 255], [255, 0, 170], [255, 0, 85]]
let openpose_obj = {
// width, height
resolution: [512, 512],
// fps...?
fps: 1,
// frames
frames: [
{
frame_current: 1,
// armatures
armatures: {
},
}
]
}
const default_keypoints = [[241,77],[241,120],[191,118],[177,183],[163,252],[298,118],[317,182],[332,245],[225,241],[213,359],[215,454],[270,240],[282,360],[286,456],[232,59],[253,60],[225,70],[260,72]]
function gradioApp() {
const elems = document.getElementsByTagName('gradio-app')
const gradioShadowRoot = elems.length == 0 ? null : elems[0].shadowRoot
return !!gradioShadowRoot ? gradioShadowRoot : document;
}
function calcResolution(resolution){
const width = resolution[0]
const height = resolution[1]
const viewportWidth = window.innerWidth / 2.25;
const viewportHeight = window.innerHeight * 0.75;
const ratio = Math.min(viewportWidth / width, viewportHeight / height);
return {width: width * ratio, height: height * ratio}
}
function resizeCanvas(width, height){
const elem = openpose_editor_elem;
const canvas = openpose_editor_canvas;
let resolution = calcResolution([width, height])
canvas.setWidth(width);
canvas.setHeight(height);
elem.style.width = resolution["width"] + "px"
elem.style.height = resolution["height"] + "px"
elem.nextElementSibling.style.width = resolution["width"] + "px"
elem.nextElementSibling.style.height = resolution["height"] + "px"
elem.parentElement.style.width = resolution["width"] + "px"
elem.parentElement.style.height = resolution["height"] + "px"
}
function undo() {
const canvas = openpose_editor_canvas;
if (undo_history.length > 0) {
lockMode = true;
if (undo_history.length > 1) redo_history.push(undo_history.pop());
const content = undo_history[undo_history.length - 1];
canvas.loadFromJSON(content, function () {
canvas.renderAll();
lockMode = false;
});
}
}
function redo() {
const canvas = openpose_editor_canvas;
if (redo_history.length > 0) {
lockMode = true;
const content = redo_history.pop();
undo_history.push(content);
canvas.loadFromJSON(content, function () {
canvas.renderAll();
lockMode = false;
});
}
}
function setPose(keypoints){
const canvas = openpose_editor_canvas;
canvas.clear()
canvas.backgroundColor = "#000"
const res = [];
for (let i = 0; i < keypoints.length; i += 18) {
const chunk = keypoints.slice(i, i + 18);
res.push(chunk);
}
for (item of res){
addPose(item)
openpose_editor_canvas.discardActiveObject();
}
}
function addPose(keypoints=undefined){
if (keypoints === undefined){
keypoints = default_keypoints;
}
const canvas = openpose_editor_canvas;
const group = new fabric.Group()
function makeCircle(color, left, top, line1, line2, line3, line4, line5) {
var c = new fabric.Circle({
left: left,
top: top,
strokeWidth: 1,
radius: 5,
fill: color,
stroke: color
});
c.hasControls = c.hasBorders = false;
c.line1 = line1;
c.line2 = line2;
c.line3 = line3;
c.line4 = line4;
c.line5 = line5;
return c;
}
function makeLine(coords, color) {
return new fabric.Line(coords, {
fill: color,
stroke: color,
strokeWidth: 10,
selectable: false,
evented: false,
});
}
const lines = []
const circles = []
for (i = 0; i < connect_keypoints.length; i++){
// 接続されるidxを指定 [0, 1]なら0と1つなぐ
const item = connect_keypoints[i]
const line = makeLine(keypoints[item[0]].concat(keypoints[item[1]]), `rgba(${connect_color[i].join(", ")}, 0.7)`)
lines.push(line)
canvas.add(line)
}
for (i = 0; i < keypoints.length; i++){
list = []
connect_keypoints.filter((item, idx) => {
if(item.includes(i)){
list.push(lines[idx])
return idx
}
})
circle = makeCircle(`rgb(${connect_color[i].join(", ")})`, keypoints[i][0], keypoints[i][1], ...list)
circle["id"] = i
circles.push(circle)
// canvas.add(circle)
group.addWithUpdate(circle);
}
canvas.discardActiveObject();
canvas.setActiveObject(group);
canvas.add(group);
group.toActiveSelection();
canvas.requestRenderAll();
}
function initCanvas(elem){
const canvas = window.openpose_editor_canvas = new fabric.Canvas(elem, {
backgroundColor: '#000',
// selection: false,
preserveObjectStacking: true
});
window.openpose_editor_elem = elem
canvas.on('object:moving', function(e) {
if ("_objects" in e.target) {
const rtop = e.target.top
const rleft = e.target.left
for (const item of e.target._objects){
let p = item;
const top = rtop + p.top * e.target.scaleY + e.target.height * e.target.scaleY / 2;
const left = rleft + p.left * e.target.scaleX + e.target.width * e.target.scaleX / 2;
if (p["id"] === 0) {
p.line1 && p.line1.set({ 'x1': left, 'y1': top });
}else{
p.line1 && p.line1.set({ 'x2': left, 'y2': top });
}
p.line2 && p.line2.set({ 'x1': left, 'y1': top });
p.line3 && p.line3.set({ 'x1': left, 'y1': top });
p.line4 && p.line4.set({ 'x1': left, 'y1': top });
p.line5 && p.line5.set({ 'x1': left, 'y1': top });
}
}else{
var p = e.target;
if (p["id"] === 0) {
p.line1 && p.line1.set({ 'x1': p.left, 'y1': p.top });
}else{
p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
}
p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top });
p.line3 && p.line3.set({ 'x1': p.left, 'y1': p.top });
p.line4 && p.line4.set({ 'x1': p.left, 'y1': p.top });
p.line5 && p.line5.set({ 'x1': p.left, 'y1': p.top });
}
canvas.renderAll();
});
canvas.on('object:scaling', function(e) {
if ("_objects" in e.target) {
const rtop = e.target.top
const rleft = e.target.left
for (const item of e.target._objects){
let p = item;
const top = rtop + p.top * e.target.scaleY + e.target.height * e.target.scaleY / 2;
const left = rleft + p.left * e.target.scaleX + e.target.width * e.target.scaleX / 2;
if (p["id"] === 0) {
p.line1 && p.line1.set({ 'x1': left, 'y1': top });
}else{
p.line1 && p.line1.set({ 'x2': left, 'y2': top });
}
p.line2 && p.line2.set({ 'x1': left, 'y1': top });
p.line3 && p.line3.set({ 'x1': left, 'y1': top });
p.line4 && p.line4.set({ 'x1': left, 'y1': top });
p.line5 && p.line5.set({ 'x1': left, 'y1': top });
}
}
canvas.renderAll();
});
canvas.on('object:rotating', function(e) {
if ("_objects" in e.target) {
const rtop = e.target.top
const rleft = e.target.left
for (const item of e.target._objects){
let p = item;
const top = rtop + p.top // + e.target.height / 2;
const left = rleft + p.left // + e.target.width / 2;
if (p["id"] === 0) {
p.line1 && p.line1.set({ 'x1': left, 'y1': top });
}else{
p.line1 && p.line1.set({ 'x2': left, 'y2': top });
}
p.line2 && p.line2.set({ 'x1': left, 'y1': top });
p.line3 && p.line3.set({ 'x1': left, 'y1': top });
p.line4 && p.line4.set({ 'x1': left, 'y1': top });
p.line5 && p.line5.set({ 'x1': left, 'y1': top });
}
}
canvas.renderAll();
});
canvas.on("object:added", function () {
if (lockMode) return;
undo_history.push(JSON.stringify(canvas));
redo_history.length = 0;
});
canvas.on("object:modified", function () {
if (lockMode) return;
undo_history.push(JSON.stringify(canvas));
redo_history.length = 0;
});
resizeCanvas(...openpose_obj.resolution)
setPose(default_keypoints)
undo_history.push(JSON.stringify(canvas));
const json_observer = new MutationObserver((m) => {
if(gradioApp().querySelector('#tab_openpose_editor').style.display!=='block') return;
try {
const raw = gradioApp().querySelector("#hide_json").querySelector("textarea").value.replaceAll("'", '"')
const json = JSON.parse(raw)
let candidate = json["candidate"]
let subset = json["subset"]
const li = []
subset = subset.splice(0, 18)
for (i=0; subset.length > i; i++){
if (Number.isInteger(subset[i]) && subset[i] >= 0){
li.push(candidate[subset[i]])
}else{
const ra_width = Math.floor(Math.random() * canvas.width)
const ra_height = Math.floor(Math.random() * canvas.height)
li.push([ra_width, ra_height])
}
}
setPose(li);
const fileReader = new FileReader();
fileReader.onload = function() {
const dataUri = this.result;
canvas.setBackgroundImage(dataUri, canvas.renderAll.bind(canvas), {
opacity: 0.5
});
const img = new Image();
img.onload = function() {
resizeCanvas(this.width, this.height)
}
img.src = dataUri;
}
fileReader.readAsDataURL(gradioApp().querySelector("#openpose_editor_input").querySelector("input").files[0]);
} catch(e){console.log(e)}
})
json_observer.observe(gradioApp().querySelector("#hide_json"), { "attributes": true })
// document.addEventListener('keydown', function(e) {
// if (e.key !== undefined) {
// if((e.key == "z" && (e.metaKey || e.ctrlKey || e.altKey))) undo()
// if((e.key == "y" && (e.metaKey || e.ctrlKey || e.altKey))) redo()
// }
// })
}
function resetCanvas(){
const canvas = openpose_editor_canvas;
canvas.clear()
canvas.backgroundColor = "#000"
}
function savePNG(){
openpose_editor_canvas.getObjects("image").forEach((img) => {
img.set({
opacity: 0
});
})
if (openpose_editor_canvas.backgroundImage) openpose_editor_canvas.backgroundImage.opacity = 0
openpose_editor_canvas.discardActiveObject();
openpose_editor_canvas.renderAll()
openpose_editor_elem.toBlob((blob) => {
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "pose.png";
a.click();
URL.revokeObjectURL(a.href);
});
openpose_editor_canvas.getObjects("image").forEach((img) => {
img.set({
opacity: 1
});
})
if (openpose_editor_canvas.backgroundImage) openpose_editor_canvas.backgroundImage.opacity = 0.5
openpose_editor_canvas.renderAll()
return
}
function saveJSON(){
const canvas = openpose_editor_canvas
const json = JSON.stringify({
"width": canvas.width,
"height": canvas.height,
"keypoints": openpose_editor_canvas.getObjects().filter((item) => {
if (item.type === "circle") return item
}).map((item) => {
return [Math.round(item.left), Math.round(item.top)]
})
}, null, 4)
const blob = new Blob([json], {
type: 'text/plain'
});
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "pose.json";
a.click();
URL.revokeObjectURL(a.href);
}
function loadJSON(){
const input = document.createElement("input");
input.type = "file"
input.click()
input.addEventListener("change", function(e){
const file = e.target.files[0];
var fileReader = new FileReader();
fileReader.onload = function() {
try {
const json = JSON.parse(this.result)
if (json["width"] && json["height"]) {
resizeCanvas(json["width"], json["height"])
}else{
throw new Error('width, height is invalid');
}
if (json["keypoints"].length % 18 === 0) {
setPose(json["keypoints"])
}else{
throw new Error('keypoints is invalid')
}
return [json["width"], json["height"]]
}catch(e){
console.error(e)
alert("Invalid JSON")
}
}
fileReader.readAsText(file);
})
input.click()
}
function addBackground(){
const input = document.createElement("input");
input.type = "file"
input.accept = "image/*"
input.addEventListener("change", function(e){
const canvas = openpose_editor_canvas
const file = e.target.files[0];
var fileReader = new FileReader();
fileReader.onload = function() {
var dataUri = this.result;
canvas.setBackgroundImage(dataUri, canvas.renderAll.bind(canvas), {
opacity: 0.5
});
const img = new Image();
img.onload = function() {
resizeCanvas(this.width, this.height)
}
img.src = dataUri;
}
fileReader.readAsDataURL(file);
})
input.click()
}
function detectImage(){
gradioApp().querySelector("#openpose_editor_input").querySelector("input").click()
}
function sendImage(){
openpose_editor_canvas.getObjects("image").forEach((img) => {
img.set({
opacity: 0
});
})
if (openpose_editor_canvas.backgroundImage) openpose_editor_canvas.backgroundImage.opacity = 0
openpose_editor_canvas.discardActiveObject();
openpose_editor_canvas.renderAll()
openpose_editor_elem.toBlob((blob) => {
const file = new File(([blob]), "pose.png")
const dt = new DataTransfer();
dt.items.add(file);
const list = dt.files
gradioApp().querySelector("#txt2img_script_container").querySelectorAll("span.transition").forEach((elem) => {
if (elem.previousElementSibling.textContent === "ControlNet"){
switch_to_txt2img()
elem.className.includes("rotate-90") && elem.parentElement.click();
const input = elem.parentElement.parentElement.querySelector("input[type='file']");
const button = elem.parentElement.parentElement.querySelector("button[aria-label='Clear']")
button && button.click();
input.value = "";
input.files = list;
const event = new Event('change', { 'bubbles': true, "composed": true });
input.dispatchEvent(event);
}
})
});
openpose_editor_canvas.getObjects("image").forEach((img) => {
img.set({
opacity: 1
});
})
if (openpose_editor_canvas.backgroundImage) openpose_editor_canvas.backgroundImage.opacity = 0.5
openpose_editor_canvas.renderAll()
}
window.addEventListener('DOMContentLoaded', () => {
const observer = new MutationObserver((m) => {
if(!executed && gradioApp().querySelector('#openpose_editor_canvas')){
executed = true;
initCanvas(gradioApp().querySelector('#openpose_editor_canvas'))
// gradioApp().querySelectorAll("#tabs > div > button").forEach((elem) => {
// if (elem.innerText === "OpenPose Editor") elem.click()
// })
observer.disconnect();
}
})
observer.observe(gradioApp(), { childList: true, subtree: true })
})