feat(pipeline): v3-v4 dedup + panorama stitching + 1080p support
- HSV-aware _trim_to_content (white ratio 30-97%) - pHash cluster dedup: dHash 32x32(1024bit), max_hamming=20 - Panoramic stitching: template matching scroll offset detection - 4-stage pipeline: MSE -> Panorama -> pHash - 1080p download priority + MAX_FRAME_WIDTH=1280 cap - test_pipeline.py with YouTube URLs and --download mode - 3 new known-issues documented - devlog + STATUS.md updated
This commit is contained in:
75
diag_v2.py
Normal file
75
diag_v2.py
Normal file
@@ -0,0 +1,75 @@
|
||||
"""video_2 진단: 왜 0 프레임인지 각 단계별 확인"""
|
||||
import sys
|
||||
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
|
||||
|
||||
import cv2
|
||||
import numpy as np
|
||||
from pathlib import Path
|
||||
import importlib.util
|
||||
|
||||
spec = importlib.util.spec_from_file_location("p", "youtube_tab_to_pdf.py")
|
||||
p = importlib.util.module_from_spec(spec)
|
||||
spec.loader.exec_module(p)
|
||||
|
||||
mp4 = Path("output") / "サカナクション/新宝島(エレキギターTAB) 難易度★★★ sakanaction shintakarajima.mp4"
|
||||
cap = cv2.VideoCapture(str(mp4))
|
||||
total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
|
||||
fps = cap.get(cv2.CAP_PROP_FPS)
|
||||
|
||||
# 10개 프레임 샘플
|
||||
indices = np.linspace(total * 0.1, total * 0.8, 10, dtype=int)
|
||||
for idx in indices:
|
||||
cap.set(cv2.CAP_PROP_POS_FRAMES, idx)
|
||||
ret, frame = cap.read()
|
||||
if not ret:
|
||||
continue
|
||||
|
||||
h, w = frame.shape[:2]
|
||||
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
# 행별 밝기
|
||||
margin_x = int(w * 0.1)
|
||||
row_br = np.mean(gray[:, margin_x:w-margin_x], axis=1)
|
||||
|
||||
strip = p._find_white_tab_strip(frame)
|
||||
has_tab = False
|
||||
if strip:
|
||||
top, bottom = strip
|
||||
crop = frame[top:bottom, :]
|
||||
has_tab = p._has_tab_content(crop)
|
||||
|
||||
print(f"Frame {idx:5d}: strip={strip}, has_tab={has_tab}, "
|
||||
f"top_br={np.mean(row_br[:h//3]):.0f}, "
|
||||
f"mid_br={np.mean(row_br[h//3:2*h//3]):.0f}, "
|
||||
f"bot_br={np.mean(row_br[2*h//3:]):.0f}")
|
||||
|
||||
# strip이 있지만 has_tab=False인 경우 상세 진단
|
||||
if strip and not has_tab:
|
||||
top, bottom = strip
|
||||
crop = frame[top:bottom, :]
|
||||
g = cv2.cvtColor(crop, cv2.COLOR_BGR2GRAY)
|
||||
ch, cw = g.shape
|
||||
_, binary = cv2.threshold(g, 180, 255, cv2.THRESH_BINARY_INV)
|
||||
horiz_k = cv2.getStructuringElement(cv2.MORPH_RECT, (max(cw//3, 30), 1))
|
||||
horiz = cv2.morphologyEx(binary, cv2.MORPH_OPEN, horiz_k)
|
||||
lines = cv2.HoughLinesP(horiz, 1, np.pi/180, threshold=40,
|
||||
minLineLength=cw//4, maxLineGap=20)
|
||||
nlines = 0 if lines is None else len(lines)
|
||||
ys = []
|
||||
if lines is not None:
|
||||
for l in lines:
|
||||
x1,y1,x2,y2 = l[0]
|
||||
if abs(y2-y1) < max(5, abs(x2-x1)*0.05):
|
||||
ys.append((y1+y2)/2)
|
||||
ys.sort()
|
||||
clusters = []
|
||||
for y in ys:
|
||||
if not clusters or y - clusters[-1] > ch * 0.02:
|
||||
clusters.append(y)
|
||||
print(f" → 크롭크기: {cw}x{ch}, 라인수: {nlines}, "
|
||||
f"수평ys: {len(ys)}, 클러스터: {len(clusters)}")
|
||||
|
||||
# 디버그: 크롭 저장
|
||||
cv2.imwrite(f"output/raw_dump/v2_diag_{idx}.png", crop)
|
||||
|
||||
cap.release()
|
||||
Reference in New Issue
Block a user