Constrain phase reranking to nearby sizes
This commit is contained in:
parent
e25f0b9730
commit
05385fce2a
3 changed files with 55 additions and 6 deletions
|
|
@ -39,6 +39,7 @@ class SolverHyperParams:
|
|||
phase_rerank_edge_concentration_weight: float = 0.10
|
||||
phase_rerank_inference_penalty_weight: float = 0.05
|
||||
phase_rerank_confidence_threshold: float = 0.12
|
||||
phase_rerank_max_size_delta_ratio: float = 0.15
|
||||
phase_rerank_margin: float = 0.004
|
||||
|
||||
def to_dict(self) -> dict[str, float]:
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ def _select_phase_candidate(
|
|||
"stroke_wobble_error": foreground_stroke_wobble_error(preview, source),
|
||||
"edge_concentration": foreground_edge_concentration(candidate_artifacts.target_rgba),
|
||||
"inference_penalty": top_score - float(candidate.score),
|
||||
"size_delta_ratio": _size_delta_ratio(inference, candidate_inference),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
@ -186,6 +187,13 @@ def _select_phase_candidate(
|
|||
best_rank = float("inf")
|
||||
best_candidate = inference
|
||||
for index, record in enumerate(candidate_records):
|
||||
candidate_inference = record["inference"]
|
||||
size_delta_ratio = float(record["size_delta_ratio"])
|
||||
if (
|
||||
candidate_inference.target_width != inference.target_width
|
||||
or candidate_inference.target_height != inference.target_height
|
||||
) and size_delta_ratio > solver_params.phase_rerank_max_size_delta_ratio:
|
||||
continue
|
||||
rank = (
|
||||
solver_params.phase_rerank_support_weight * support_penalty[index]
|
||||
+ solver_params.phase_rerank_edge_position_weight * edge_position_penalty[index]
|
||||
|
|
@ -215,3 +223,9 @@ def _normalize_penalty(values, *, higher_is_better: bool = False) -> list[float]
|
|||
if higher_is_better:
|
||||
normalized = 1.0 - normalized
|
||||
return normalized.astype(np.float32).tolist()
|
||||
|
||||
|
||||
def _size_delta_ratio(a: InferenceResult, b: InferenceResult) -> float:
|
||||
width_ratio = abs(b.target_width - a.target_width) / max(1.0, float(a.target_width))
|
||||
height_ratio = abs(b.target_height - a.target_height) / max(1.0, float(a.target_height))
|
||||
return max(width_ratio, height_ratio)
|
||||
|
|
|
|||
|
|
@ -147,12 +147,12 @@ def test_phase_rerank_can_override_low_confidence_inference_pick(monkeypatch) ->
|
|||
|
||||
|
||||
def test_phase_rerank_can_override_to_better_size_candidate(monkeypatch) -> None:
|
||||
source = np.zeros((4, 4, 4), dtype=np.float32)
|
||||
candidate_a = InferenceCandidate(target_width=2, target_height=2, phase_x=0.0, phase_y=0.0, score=0.91, breakdown={})
|
||||
candidate_b = InferenceCandidate(target_width=3, target_height=3, phase_x=0.0, phase_y=0.0, score=0.88, breakdown={})
|
||||
source = np.zeros((16, 16, 4), dtype=np.float32)
|
||||
candidate_a = InferenceCandidate(target_width=16, target_height=16, phase_x=0.0, phase_y=0.0, score=0.91, breakdown={})
|
||||
candidate_b = InferenceCandidate(target_width=18, target_height=18, phase_x=0.0, phase_y=0.0, score=0.88, breakdown={})
|
||||
inference = InferenceResult(
|
||||
target_width=2,
|
||||
target_height=2,
|
||||
target_width=16,
|
||||
target_height=16,
|
||||
phase_x=0.0,
|
||||
phase_y=0.0,
|
||||
confidence=0.0,
|
||||
|
|
@ -168,7 +168,7 @@ def test_phase_rerank_can_override_to_better_size_candidate(monkeypatch) -> None
|
|||
return DummyArtifacts(rgba)
|
||||
|
||||
def fake_support(source_rgba, output_rgba, *, target_width, target_height, phase_x, phase_y):
|
||||
if target_width == 2:
|
||||
if target_width == 16:
|
||||
return {"score": 0.10}
|
||||
return {"score": 0.01}
|
||||
|
||||
|
|
@ -180,6 +180,40 @@ def test_phase_rerank_can_override_to_better_size_candidate(monkeypatch) -> None
|
|||
assert selected.target_height == candidate_b.target_height
|
||||
|
||||
|
||||
def test_phase_rerank_rejects_large_size_jump(monkeypatch) -> None:
|
||||
source = np.zeros((16, 16, 4), dtype=np.float32)
|
||||
candidate_a = InferenceCandidate(target_width=16, target_height=16, phase_x=0.0, phase_y=0.0, score=0.91, breakdown={})
|
||||
candidate_b = InferenceCandidate(target_width=24, target_height=24, phase_x=0.0, phase_y=0.0, score=0.88, breakdown={})
|
||||
inference = InferenceResult(
|
||||
target_width=16,
|
||||
target_height=16,
|
||||
phase_x=0.0,
|
||||
phase_y=0.0,
|
||||
confidence=0.0,
|
||||
top_candidates=[candidate_a, candidate_b],
|
||||
)
|
||||
|
||||
class DummyArtifacts:
|
||||
def __init__(self, rgba: np.ndarray) -> None:
|
||||
self.target_rgba = rgba
|
||||
|
||||
def fake_optimize_uv_field(source_rgba, inference, analysis, steps, seed, device, solver_params=None):
|
||||
rgba = np.zeros((inference.target_height, inference.target_width, 4), dtype=np.float32)
|
||||
return DummyArtifacts(rgba)
|
||||
|
||||
def fake_support(source_rgba, output_rgba, *, target_width, target_height, phase_x, phase_y):
|
||||
if target_width == 16:
|
||||
return {"score": 0.10}
|
||||
return {"score": 0.01}
|
||||
|
||||
monkeypatch.setattr("repixelizer.pipeline.optimize_uv_field", fake_optimize_uv_field)
|
||||
monkeypatch.setattr("repixelizer.pipeline.source_lattice_consistency_breakdown", fake_support)
|
||||
|
||||
selected = _select_phase_candidate(source, inference, analysis=object(), seed=7, device="cpu")
|
||||
assert selected.target_width == candidate_a.target_width
|
||||
assert selected.target_height == candidate_a.target_height
|
||||
|
||||
|
||||
def test_phase_rerank_can_prefer_better_line_metrics(monkeypatch) -> None:
|
||||
source = np.zeros((4, 4, 4), dtype=np.float32)
|
||||
candidate_a = InferenceCandidate(target_width=2, target_height=2, phase_x=-0.2, phase_y=0.0, score=0.91, breakdown={})
|
||||
|
|
|
|||
Loading…
Reference in a new issue