Merge pull request #35 from Kalekki/Upscaling

Upscaling

Former-commit-id: c9367e6fb8cad4670508bb62fd6d18e116e53927
This commit is contained in:
tim h 2022-11-22 17:31:56 -06:00 committed by GitHub
commit 7370aba4d3
2 changed files with 140 additions and 2 deletions

View file

@ -89,6 +89,10 @@
<input type="file" id="preloadImage" onchange="preloadImage()" accept="image/*" /
style="width: 200px;"><br />
<button onclick="downloadCanvas()">Save canvas</button><br />
<label for="upscalers">Choose upscaler</label>
<select id="upscalers"></select>
<button onclick="upscaleAndDownload()">Upscale (might take a sec)</button><br />
<button onclick="newImage()">Clear canvas</button>
</div>
<!-- Degub info -->

View file

@ -154,6 +154,7 @@ const bgCtx = bgCanvas.getContext("2d");
function startup() {
checkIfWebuiIsRunning();
loadSettings();
getUpscalers();
drawBackground();
changeScaleFactor();
changePaintMode();
@ -904,8 +905,8 @@ function cropCanvas(sourceCanvas) {
return a - b;
});
var n = pix.x.length - 1;
w = pix.x[n] - pix.x[0];
h = pix.y[n] - pix.y[0];
w = (pix.x[n] - pix.x[0])+1;
h = (pix.y[n] - pix.y[0])+1;
// yup sure looks like it
try {
@ -940,6 +941,139 @@ function checkIfWebuiIsRunning() {
});
}
function getUpscalers() {
/*
so for some reason when upscalers request returns upscalers, the real-esrgan model names are incorrect, and need to be fetched from /sdapi/v1/realesrgan-models
also the realesrgan models returned are not all correct, extra fun!
LDSR seems to have problems so we dont add that either -> RuntimeError: Number of dimensions of repeat dims can not be smaller than number of dimensions of tensor
need to figure out why that is, if you dont get this error then you can add it back in
Hacky way to get the correct list all in one go is to purposefully make an incorrect request, which then returns
{ detail: "Invalid upscaler, needs to be on of these: None , Lanczos , Nearest , LDSR , BSRGAN , R-ESRGAN General 4xV3 , R-ESRGAN 4x+ Anime6B , ScuNET , ScuNET PSNR , SwinIR_4x" }
from which we can extract the correct list of upscalers
*/
// hacky way to get the correct list of upscalers
var upscalerSelect = document.getElementById("upscalers");
var extras_url = document.getElementById("host").value + "/sdapi/v1/extra-single-image/" // endpoint for upscaling, needed for the hacky way to get the correct list of upscalers
var empty_image = new Image(512, 512);
empty_image.src = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAFCAAAAABCAYAAAChpRsuAAAALklEQVR42u3BAQ0AAAgDoJvc6LeHAybtBgAAAAAAAAAAAAAAAAAAAAAAAAB47QD2wAJ/LnnqGgAAAABJRU5ErkJggg=="; //transparent pixel
var purposefully_incorrect_data = {
"resize-mode" : 0, // 0 = just resize, 1 = crop and resize, 2 = resize and fill i assume based on theimg2img tabs options
"upscaling_resize": 2,
"upscaler_1": "fake_upscaler",
"image": empty_image.src,
}
fetch(extras_url, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(purposefully_incorrect_data),
})
.then((response) => response.json())
.then((data) => {
console.log( "purposefully_incorrect_data response, ignore above error");
// result = purposefully_incorrect_data response: Invalid upscaler, needs to be on of these: None , Lanczos , Nearest , LDSR , BSRGAN , R-ESRGAN General 4xV3 , R-ESRGAN 4x+ Anime6B , ScuNET , ScuNET PSNR , SwinIR_4x
let upscalers = data.detail.split(": ")[1].trim().split(" , "); // converting the result to a list of upscalers
for (var i = 0; i < upscalers.length; i++) {
if(upscalers[i] == "LDSR") continue; // Skip LDSR, see reason in the first comment
var option = document.createElement("option");
option.text = upscalers[i];
option.value = upscalers[i];
upscalerSelect.add(option);
}
})
/* THE NON HACKY WAY THAT I SIMPLY COULD NOT GET TO PRODUCE A LIST WITHOUT NON WORKING UPSCALERS, FEEL FREE TO TRY AND FIGURE IT OUT
var url = document.getElementById("host").value + "/sdapi/v1/upscalers";
var realesrgan_url = document.getElementById("host").value + "/sdapi/v1/realesrgan-models";
// get upscalers
fetch(url)
.then((response) => response.json())
.then((data) => {
console.log(data);
for (var i = 0; i < data.length; i++) {
var option = document.createElement("option");
if (data[i].name.includes("ESRGAN") || data[i].name.includes("LDSR")) {
continue;
}
option.text = data[i].name;
upscalerSelect.add(option);
}
})
.catch((error) => {
alert(
"Error getting upscalers, please check console for additional info\n" +
error
);
});
// fetch realesrgan models separately
fetch(realesrgan_url)
.then((response) => response.json())
.then((data) => {
var model = data;
for(var i = 0; i < model.length; i++){
let option = document.createElement("option");
option.text = model[i].name;
option.value = model[i].name;
upscalerSelect.add(option);
}
})
*/
}
async function upscaleAndDownload(){
// Future improvements: some upscalers take a while to upscale, so we should show a loading bar or something, also a slider for the upscale amount
// get cropped canvas, send it to upscaler, download result
var upscale_factor = 2; // TODO: make this a user input 1.x - 4.0 or something
var upscaler = document.getElementById("upscalers").value;
var croppedCanvas = cropCanvas(imgCanvas);
if (croppedCanvas != null) {
var upscaler = document.getElementById("upscalers").value;
var url = document.getElementById("host").value + "/sdapi/v1/extra-single-image/";
var imgdata = croppedCanvas.toDataURL("image/png");
var data = {
"resize-mode" : 0, // 0 = just resize, 1 = crop and resize, 2 = resize and fill i assume based on theimg2img tabs options
"upscaling_resize": upscale_factor,
"upscaler_1": upscaler,
"image": imgdata,
}
console.log(data);
await fetch(url, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((data) => {
console.log(data);
var link = document.createElement("a");
link.download =
new Date().toISOString().slice(0, 19).replace("T", " ").replace(":", " ") +
" openOutpaint image upscaler_"+upscaler+".png";
link.href = "data:image/png;base64,"+data["image"];
link.click();
})
}
}
function loadSettings() {
// set default values if not set
var _sampler =