mirror of
https://github.com/ClovertaTheTrilobita/cellpose-web.git
synced 2026-04-01 23:14:50 +00:00
feature(preview): 增加预览
This commit is contained in:
parent
ec0221a3ca
commit
0867b97453
4 changed files with 57 additions and 19 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
*.png
|
*.png
|
||||||
backend/test_output
|
backend/test_output
|
||||||
test_output/*
|
test_output/
|
||||||
test_tif
|
test_tif
|
||||||
output
|
output
|
||||||
uploads
|
uploads
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ class Cprun:
|
||||||
time: str | None = None,
|
time: str | None = None,
|
||||||
model: str = "cpsam",
|
model: str = "cpsam",
|
||||||
diameter: float | None = None,
|
diameter: float | None = None,
|
||||||
flow_threshold: float | float = 0.4,
|
flow_threshold: float = 0.4,
|
||||||
cellprob_threshold: float | float = 0.0, ):
|
cellprob_threshold: float = 0.0, ):
|
||||||
|
|
||||||
if time is None:
|
if time is None:
|
||||||
return [False, "No time received"]
|
return [False, "No time received"]
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import base64
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from flask import Flask, send_from_directory, request, jsonify
|
from flask import Flask, send_from_directory, request, jsonify
|
||||||
import os, shutil, time, threading, datetime, json, redis
|
import os, shutil, time, threading, datetime, json, redis
|
||||||
|
|
@ -103,7 +104,7 @@ def upload():
|
||||||
|
|
||||||
return jsonify({"ok": True, "count": len(saved), "id": ts})
|
return jsonify({"ok": True, "count": len(saved), "id": ts})
|
||||||
|
|
||||||
@app.get("/status/")
|
@app.get("/status")
|
||||||
def status():
|
def status():
|
||||||
"""
|
"""
|
||||||
检查某一cellpose任务是否完成
|
检查某一cellpose任务是否完成
|
||||||
|
|
@ -115,3 +116,27 @@ def status():
|
||||||
if not st:
|
if not st:
|
||||||
return jsonify({"ok": True, "exists": False, "status": "not_found"}), 200
|
return jsonify({"ok": True, "exists": False, "status": "not_found"}), 200
|
||||||
return jsonify({"ok": True, "exists": True, **st}), 200
|
return jsonify({"ok": True, "exists": True, **st}), 200
|
||||||
|
|
||||||
|
@app.get("/preview")
|
||||||
|
def preview():
|
||||||
|
task_id = request.args.get('id')
|
||||||
|
task_dir = BASE_DIR / "output" / task_id
|
||||||
|
if not task_dir.exists():
|
||||||
|
return jsonify({"ok": False, "error": "task not found"}), 200
|
||||||
|
|
||||||
|
# 找出所有 *_overlay.png 文件
|
||||||
|
files = sorted(task_dir.glob("*_overlay.png"))
|
||||||
|
|
||||||
|
if not files:
|
||||||
|
return jsonify({"ok": False, "error": "no overlay images"}), 200
|
||||||
|
|
||||||
|
result = []
|
||||||
|
for path in files:
|
||||||
|
data = path.read_bytes()
|
||||||
|
encoded = base64.b64encode(data).decode("utf-8")
|
||||||
|
result.append({
|
||||||
|
"filename": path.name,
|
||||||
|
"image": encoded
|
||||||
|
})
|
||||||
|
|
||||||
|
return jsonify({"ok": True, "count": len(result), "images": result})
|
||||||
|
|
@ -1,35 +1,48 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<h1>This is preview</h1>
|
<h1>This is preview</h1>
|
||||||
<p id="none-exist" hidden>id not exists</p>
|
<p id="none-exist" hidden></p>
|
||||||
|
<div id="gallery"></div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
const API_BASE = "http://10.147.18.141:5000/status/";
|
const API_BASE = "http://10.147.18.141:5000/status";
|
||||||
|
const API_PIC = "http://10.147.18.141:5000/preview"
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const ID = params.get("id");
|
const ID = params.get("id");
|
||||||
|
|
||||||
const msg = document.getElementById("none-exist");
|
const msg = document.getElementById("none-exist");
|
||||||
|
|
||||||
// 没有 id,直接提示
|
|
||||||
if (!ID) {
|
if (!ID) {
|
||||||
msg.textContent = "missing id in URL";
|
msg.textContent = "missing id in URL";
|
||||||
msg.hidden = false;
|
msg.hidden = false;
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
const res = await axios.get(API_BASE + "?id=" + encodeURIComponent(ID));
|
const res = await axios.get(API_BASE + "?id=" + encodeURIComponent(ID));
|
||||||
const { exists, status } = res.data; // exists: boolean, status: "running" | "success" | "failed"...
|
const { exists, status } = res.data; // exists: boolean, status: "running" | "success" | "failed"...
|
||||||
|
|
||||||
// 只在“不存在”时显示这条消息
|
|
||||||
if (!exists) {
|
|
||||||
msg.textContent = `id "${ID}" not exists`;
|
|
||||||
msg.hidden = false;
|
|
||||||
} else {
|
|
||||||
msg.hidden = true; // 存在就隐藏这条“not exists”的提示
|
|
||||||
|
|
||||||
}
|
if (!exists) {
|
||||||
|
msg.textContent = `id "${ID}" 不存在`;
|
||||||
|
msg.hidden = false;
|
||||||
|
} else {
|
||||||
|
msg.hidden = true;
|
||||||
|
axios.get(API_PIC + "?id=" + encodeURIComponent(ID)).then(res => {
|
||||||
|
if (res.data.ok) {
|
||||||
|
const gallery = document.getElementById("gallery");
|
||||||
|
res.data.images.forEach(img => {
|
||||||
|
const el = document.createElement("img");
|
||||||
|
el.src = "data:image/png;base64," + img.image;
|
||||||
|
el.alt = img.filename;
|
||||||
|
el.style.width = "200px"; // 缩略图大小
|
||||||
|
gallery.appendChild(el);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
alert(res.data.error);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
msg.textContent = "request failed";
|
msg.textContent = "请求失败";
|
||||||
msg.hidden = false;
|
msg.hidden = false;
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue