update
This commit is contained in:
@@ -114,14 +114,6 @@ constexpr int kProjectTreeDockStartupHeight = 170;
|
|||||||
constexpr int kPropertiesDockStartupHeight = 380;
|
constexpr int kPropertiesDockStartupHeight = 380;
|
||||||
constexpr char kMimeHotspotAnimationJson[] = "application/x-hfut-hotspot-animation+json";
|
constexpr char kMimeHotspotAnimationJson[] = "application/x-hfut-hotspot-animation+json";
|
||||||
|
|
||||||
void applyVisibleBlackholesToBackground(QImage& bgPremul, const QVector<core::Project::Entity>& entities) {
|
|
||||||
for (const auto& ex : entities) {
|
|
||||||
if (ex.blackholeVisible && ex.cutoutPolygonWorld.size() >= 3) {
|
|
||||||
entity_cutout::applyBlackFillToBackground(bgPremul, ex.cutoutPolygonWorld);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] QVector<QVector<QPointF>> visibleBlackholePolygonsFromEntities(
|
[[nodiscard]] QVector<QVector<QPointF>> visibleBlackholePolygonsFromEntities(
|
||||||
const QVector<core::Project::Entity>& entities) {
|
const QVector<core::Project::Entity>& entities) {
|
||||||
QVector<QVector<QPointF>> holes;
|
QVector<QVector<QPointF>> holes;
|
||||||
@@ -3883,65 +3875,7 @@ void MainWindow::rebuildCentralPages() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
core::Project::Entity ent;
|
// 待确认态只需多边形;深度/抠图在「确认创建实体」时再算,避免此处整图解码阻塞 UI 数秒。
|
||||||
ent.id.clear();
|
|
||||||
ent.cutoutPolygonWorld = polyWorld;
|
|
||||||
ent.originWorld = entity_cutout::polygonCentroid(ent.cutoutPolygonWorld);
|
|
||||||
ent.polygonLocal.clear();
|
|
||||||
ent.polygonLocal.reserve(ent.cutoutPolygonWorld.size());
|
|
||||||
for (const auto& pt : ent.cutoutPolygonWorld) {
|
|
||||||
ent.polygonLocal.push_back(pt - ent.originWorld);
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString bgAbs = m_workspace.backgroundAbsolutePath();
|
|
||||||
QImage depth8;
|
|
||||||
if (m_workspace.hasDepth()) {
|
|
||||||
const QString dpath = m_workspace.depthAbsolutePath();
|
|
||||||
if (!dpath.isEmpty() && QFileInfo::exists(dpath) && !bgAbs.isEmpty()) {
|
|
||||||
depth8 = core::image_file::loadDepthMapAlignedToBackground(dpath, bgAbs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const QPointF c = entity_cutout::polygonCentroid(ent.cutoutPolygonWorld);
|
|
||||||
int z = 0;
|
|
||||||
if (!depth8.isNull()) {
|
|
||||||
const int xi = static_cast<int>(std::floor(c.x()));
|
|
||||||
const int yi = static_cast<int>(std::floor(c.y()));
|
|
||||||
if (xi >= 0 && yi >= 0 && xi < depth8.width() && yi < depth8.height()) {
|
|
||||||
z = static_cast<int>(static_cast<const uchar*>(depth8.constScanLine(yi))[xi]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ent.depth = z;
|
|
||||||
{
|
|
||||||
const double ds01 = static_cast<double>(std::clamp(z, 0, 255)) / 255.0;
|
|
||||||
ent.distanceScaleCalibMult = 0.5 + ds01 * 1.0;
|
|
||||||
}
|
|
||||||
QImage bg =
|
|
||||||
core::image_file::loadImageLimited(bgAbs, core::image_decode::kWorkspaceMaxPixels);
|
|
||||||
if (!bg.isNull() && bg.format() != QImage::Format_ARGB32_Premultiplied) {
|
|
||||||
bg = bg.convertToFormat(QImage::Format_ARGB32_Premultiplied);
|
|
||||||
}
|
|
||||||
applyVisibleBlackholesToBackground(bg, m_workspace.entities());
|
|
||||||
QImage cutout;
|
|
||||||
if (!bg.isNull()) {
|
|
||||||
QPointF topLeft;
|
|
||||||
cutout = entity_cutout::extractEntityImage(bg, ent.cutoutPolygonWorld, topLeft);
|
|
||||||
ent.imageTopLeftWorld = topLeft;
|
|
||||||
}
|
|
||||||
|
|
||||||
QSet<QString> used;
|
|
||||||
for (const auto& ex : m_workspace.entities()) {
|
|
||||||
used.insert(ex.id);
|
|
||||||
}
|
|
||||||
int n = static_cast<int>(m_workspace.entities().size()) + 1;
|
|
||||||
for (int guard = 0; guard < 100000; ++guard, ++n) {
|
|
||||||
const QString cand = QStringLiteral("entity-%1").arg(n);
|
|
||||||
if (!used.contains(cand)) {
|
|
||||||
ent.id = cand;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不直接落盘:进入待确认(可微调)
|
|
||||||
m_editorCanvas->setPendingEntityPolygonWorld(polyWorld);
|
m_editorCanvas->setPendingEntityPolygonWorld(polyWorld);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -168,8 +168,8 @@ class DepthConfig:
|
|||||||
class InpaintConfig:
|
class InpaintConfig:
|
||||||
# 统一补全默认后端(与 model key 对齐;实际路由以请求的 model_name 为准)
|
# 统一补全默认后端(与 model key 对齐;实际路由以请求的 model_name 为准)
|
||||||
backend: Literal["flux_fill", "sdxl_inpaint", "controlnet"] = "flux_fill"
|
backend: Literal["flux_fill", "sdxl_inpaint", "controlnet"] = "flux_fill"
|
||||||
# FLUX Fill(gated:须在 Hugging Face 同意条款,并建议设置环境变量 HF_TOKEN)
|
# FLUX Fill:本机 diffusers 目录(须含 model_index.json)。换机器时改此绝对路径即可。
|
||||||
flux_fill_model: str = "black-forest-labs/FLUX.1-Fill-dev"
|
flux_fill_model: str = "/home/vipuser/ai-models/flux/FLUX.1-Fill-dev"
|
||||||
# SDXL:须为专用 inpaint 权重(勿用 xl-base 当补全底模)
|
# SDXL:须为专用 inpaint 权重(勿用 xl-base 当补全底模)
|
||||||
sdxl_base_model: str = "diffusers/stable-diffusion-xl-1.0-inpainting-0.1"
|
sdxl_base_model: str = "diffusers/stable-diffusion-xl-1.0-inpainting-0.1"
|
||||||
# ControlNet Inpaint 基础模型与 controlnet 权重
|
# ControlNet Inpaint 基础模型与 controlnet 权重
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import os
|
from pathlib import Path
|
||||||
from typing import Any, Callable
|
from typing import Any, Callable
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
@@ -24,12 +24,15 @@ def make_flux_fill_predictor(
|
|||||||
else:
|
else:
|
||||||
torch_dtype = torch.float32
|
torch_dtype = torch.float32
|
||||||
|
|
||||||
hf_token = os.environ.get("HF_TOKEN") or os.environ.get("HUGGING_FACE_HUB_TOKEN")
|
root = Path(model_id.strip()).expanduser()
|
||||||
|
# 本机 diffusers 目录(含 model_index.json)时不访问 Hub,避免自动下载。
|
||||||
|
local_files_only = root.is_dir() and (root / "model_index.json").is_file()
|
||||||
|
|
||||||
pipe = FluxFillPipeline.from_pretrained(
|
pipe = FluxFillPipeline.from_pretrained(
|
||||||
model_id,
|
str(root),
|
||||||
torch_dtype=torch_dtype,
|
torch_dtype=torch_dtype,
|
||||||
token=hf_token,
|
token=None,
|
||||||
|
local_files_only=local_files_only,
|
||||||
)
|
)
|
||||||
|
|
||||||
if device == "cuda":
|
if device == "cuda":
|
||||||
|
|||||||
Reference in New Issue
Block a user