fix(cv): resolve infinite page duplication bug caused by playback cursor

This commit is contained in:
2026-03-29 21:23:18 +09:00
parent ac0c098259
commit 3377b5f68d
23 changed files with 779 additions and 465 deletions

View File

@@ -17,8 +17,12 @@ class TemporalTracker:
_, binary = cv2.threshold(gray, 230, 255, cv2.THRESH_BINARY)
return binary
def process_frame(self, frame: np.ndarray) -> None:
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
def process_frame(self, frame: np.ndarray, tracking_channel: Optional[np.ndarray] = None) -> None:
if tracking_channel is not None:
frame_gray = tracking_channel.copy()
else:
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
self.frame_count += 1
if self.last_frame is None:
@@ -29,13 +33,20 @@ class TemporalTracker:
diff = cv2.absdiff(self.last_frame, frame_gray)
_, thresh = cv2.threshold(diff, 50, 255, cv2.THRESH_BINARY)
diff_ratio = np.sum(thresh > 0) / thresh.size
if diff_ratio > self.diff_threshold:
# 커서 이동 vs 페이지 전환을 명확히 구분하기 위한 혁신적 지표 도입
# 커서는 세로로 길기 때문에 픽셀 면적(area)으로는 비중이 크지만 가로 폭(column)으로는 매우 좁음(전체 폭의 <5%).
# 반면 실제 페이지 전환은 가로 전체에 걸쳐 악보가 바뀌므로(>15%).
col_sums = np.sum(thresh > 0, axis=0)
h, w = thresh.shape
# 한 열에서 높이의 3% 이상 픽셀이 변한 경우 "유의미하게 변한 열"로 간주
changed_cols = np.sum(col_sums > (h * 0.03))
diff_ratio = changed_cols / w
if diff_ratio > 0.15: # 가로폭의 15% 이상이 완전히 바뀌면 페이지 전환
self.stable_frame_count = 0
if len(self.current_page_frames) > 0:
print(f"[Tracker] Page Flip Detected! (Change: {diff_ratio*100:.1f}%) -> Saving Median Page {len(self.unique_pages)+1}")
# Compute median on BGR to preserve the highest quality true colors and erase moving noise
print(f"[Tracker] Page Flip Detected! (Col Change: {diff_ratio*100:.1f}%) -> Saving Median Page {len(self.unique_pages)+1}")
median_page = np.median(self.current_page_frames, axis=0).astype(np.uint8)
self.unique_pages.append(median_page)
self.current_page_frames = []