Blurサイズ問題の修正

This commit is contained in:
2026-02-19 09:45:05 +09:00
parent 9ce6ec99d3
commit da9de60697
8 changed files with 61 additions and 51 deletions
+34 -31
View File
@@ -83,7 +83,6 @@ class GenerateRequest(BaseModel):
end_frame: int
conf_threshold: float = 0.5
iou_threshold: float = 0.45
mask_scale: float = 1.5
class BakeRequest(BaseModel):
@@ -91,6 +90,7 @@ class BakeRequest(BaseModel):
detections_path: str
output_path: str
blur_size: int = 50
display_scale: float = 1.0
format: str = "mp4"
@@ -305,20 +305,15 @@ def process_video_task(task_id: str, req: GenerateRequest):
for detections in batch_detections:
packed_detections: List[List[float]] = []
for x, y, w, h, conf in detections:
scaled = _scale_bbox(
int(x),
int(y),
int(w),
int(h),
float(req.mask_scale),
width,
height,
)
if scaled is None:
# bboxをそのまま保存(表示スケールはBake時に適用)
bx, by, bw, bh = int(x), int(y), int(w), int(h)
bx = max(0, bx)
by = max(0, by)
bw = min(width - bx, bw)
bh = min(height - by, bh)
if bw <= 0 or bh <= 0:
continue
packed_detections.append(
[scaled[0], scaled[1], scaled[2], scaled[3], float(conf)]
)
packed_detections.append([bx, by, bw, bh, float(conf)])
frame_detections.append(packed_detections)
current_count += 1
tasks[task_id].progress = current_count
@@ -356,7 +351,7 @@ def process_video_task(task_id: str, req: GenerateRequest):
"width": width,
"height": height,
"fps": fps,
"mask_scale": float(req.mask_scale),
"mask_scale": 1.0,
"frames": frame_detections,
}
with open(output_msgpack_path, "wb") as f:
@@ -435,9 +430,9 @@ def process_bake_task(task_id: str, req: BakeRequest):
blur_size = max(1, int(req.blur_size))
if blur_size % 2 == 0:
blur_size += 1
feather_radius = max(3, min(25, blur_size // 3))
feather_kernel = feather_radius * 2 + 1
blur_margin = max(1, (blur_size // 2) + feather_radius)
display_scale = max(0.1, float(req.display_scale))
# blur_margin は境界問題回避のための計算用余白のみ(表示には使わない)
blur_margin = blur_size // 2
# Queues
queue_size = 8
@@ -507,29 +502,37 @@ def process_bake_task(task_id: str, req: BakeRequest):
continue
for x, y, w, h in valid_boxes:
roi_x1 = max(0, x - blur_margin)
roi_y1 = max(0, y - blur_margin)
roi_x2 = min(src_width, x + w + blur_margin)
roi_y2 = min(src_height, y + h + blur_margin)
# display_scale で表示サイズを決定
cx = x + w / 2
cy = y + h / 2
dw = max(1, int(w * display_scale))
dh = max(1, int(h * display_scale))
dx = int(cx - dw / 2)
dy = int(cy - dh / 2)
# ROIは表示サイズ + blur_margin(計算用余白、境界問題回避のみ)
roi_x1 = max(0, dx - blur_margin)
roi_y1 = max(0, dy - blur_margin)
roi_x2 = min(src_width, dx + dw + blur_margin)
roi_y2 = min(src_height, dy + dh + blur_margin)
roi_width = roi_x2 - roi_x1
roi_height = roi_y2 - roi_y1
if roi_width <= 0 or roi_height <= 0:
continue
roi_mask = np.zeros((roi_height, roi_width), dtype=np.uint8)
center = (x + w // 2 - roi_x1, y + h // 2 - roi_y1)
axes = (max(1, w // 2), max(1, h // 2))
cv2.ellipse(roi_mask, center, axes, 0, 0, 360, 255, -1)
roi_mask = cv2.GaussianBlur(roi_mask, (feather_kernel, feather_kernel), 0)
# ブラーはROI全体で計算(余白があるので端の精度が保証される)
roi_src = frame[roi_y1:roi_y2, roi_x1:roi_x2]
roi_blurred = cv2.GaussianBlur(roi_src, (blur_size, blur_size), 0)
# 合成マスクはdisplay_scaleサイズの楕円のみ(featheringなし)
roi_mask = np.zeros((roi_height, roi_width), dtype=np.uint8)
center = (int(cx) - roi_x1, int(cy) - roi_y1)
axes = (max(1, dw // 2), max(1, dh // 2))
cv2.ellipse(roi_mask, center, axes, 0, 0, 360, 255, -1)
roi_alpha = (roi_mask.astype(np.float32) / 255.0)[..., np.newaxis]
roi_composed = (roi_src.astype(np.float32) * (1.0 - roi_alpha)) + (
roi_blurred.astype(np.float32) * roi_alpha
)
roi_composed = roi_src.astype(np.float32) * (1.0 - roi_alpha) + roi_blurred.astype(np.float32) * roi_alpha
frame[roi_y1:roi_y2, roi_x1:roi_x2] = np.clip(roi_composed, 0, 255).astype(np.uint8)
process_queue.put((idx, frame))