docs: 발표·특허·AI영상요약 자료 및 작업기록 추가

- 발표자료(좌표투영·측점기반재생) 갱신 + 그림/PDF
- 특허 출원 초안 및 도면
- AI 영상요약 서비스 작업기록(docs/history)
- 관련 scripts 추가

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-09 11:20:03 +09:00
co-authored by Claude Opus 4.8
parent 5c8b499979
commit fe25ce00f1
78 changed files with 6186 additions and 15 deletions
+94
View File
@@ -0,0 +1,94 @@
#!/usr/bin/env python3
# fig_전체흐름도.py — 스테이션기반 플레이어 전체 흐름 다이어그램 (보고서 삽입용 PNG/PDF)
# 입력(폴더) → 자동 파싱 → 좌표·측점 계산 → 화면 출력, 오피스 단색 스타일.
# weasyprint SVG 텍스트 디센더 잘림 이슈 회피를 위해 PIL 직접 드로잉.
# 실행: python3 scripts/fig_전체흐름도.py → docs/그림_전체흐름도.png / .pdf
import math, os
from PIL import Image, ImageDraw, ImageFont
OUT_DIR = os.path.join(os.path.dirname(__file__), '..', 'docs')
FB = os.path.expanduser('~/.local/share/fonts/malgunbd.ttf')
FR = os.path.expanduser('~/.local/share/fonts/malgun.ttf')
W, H = 2400, 1100
im = Image.new('RGB', (W, H), 'white')
d = ImageDraw.Draw(im)
GRAY, BLUE, GREEN, AMBER = (89, 89, 89), (46, 117, 182), (112, 173, 71), (191, 144, 0)
PURPLE, CAPTION = (124, 58, 237), (64, 64, 64)
def fit(text, path, size, maxw):
"""maxw 안에 들어올 때까지 폰트 크기를 줄여 반환."""
while size > 20:
f = ImageFont.truetype(path, size)
if d.textlength(text, font=f) <= maxw:
return f
size -= 2
return ImageFont.truetype(path, size)
def box(x1, y1, x2, y2, color, main, sub, subcolor):
d.rectangle((x1, y1, x2, y2), fill=color)
cx, cy, maxw = (x1 + x2) // 2, (y1 + y2) // 2, (x2 - x1) - 40
d.text((cx, cy - 24), main, font=fit(main, FB, 40, maxw), fill='white', anchor='mm')
d.text((cx, cy + 32), sub, font=fit(sub, FR, 28, maxw), fill=subcolor, anchor='mm')
def arrow(x1, y1, x2, y2):
d.line((x1, y1, x2, y2), fill=PURPLE, width=7)
ang = math.atan2(y2 - y1, x2 - x1)
L, Wd = 34, 20
d.polygon([(x2, y2),
(x2 - L*math.cos(ang) + Wd*math.sin(ang), y2 - L*math.sin(ang) - Wd*math.cos(ang)),
(x2 - L*math.cos(ang) - Wd*math.sin(ang), y2 - L*math.sin(ang) + Wd*math.cos(ang))],
fill=PURPLE)
cap = ImageFont.truetype(FB, 34)
d.text((310, 100), '입력 — 데이터 폴더 1개', font=cap, fill=CAPTION, anchor='mm')
d.text((880, 100), '① 자동 파싱', font=cap, fill=CAPTION, anchor='mm')
d.text((1440, 100), '② 좌표·측점 계산', font=cap, fill=CAPTION, anchor='mm')
d.text((2080, 100), '③ 화면 출력', font=cap, fill=CAPTION, anchor='mm')
# 입력 그룹 (테두리 + 4종)
d.rectangle((60, 150, 560, 950), fill=(245, 245, 245), outline=(176, 176, 176), width=3)
box(90, 190, 530, 340, GRAY, '영상 (mp4)', '드론 촬영 철도시설물 영상', (232, 232, 232))
box(90, 380, 530, 530, GRAY, '드론 비행로그 (csv)', '프레임별 위치·자세각·초점거리', (232, 232, 232))
box(90, 570, 530, 720, GRAY, '측점 (csv)', '좌표 · 실측 정표고', (232, 232, 232))
box(90, 760, 530, 910, GRAY, 'POI·구조물 (kmz)', '+ 노선 보정 (json·선택)', (232, 232, 232))
# 파싱
box(680, 460, 1080, 640, BLUE, '자동 파싱', '인코딩 자동감지 · KMZ 해제', (219, 233, 247))
# 계산 2종
box(1180, 320, 1700, 480, GREEN, '시간↔측점 대응표 생성', 'GPS를 선로에 투영 → 시간·측점 짝', (230, 242, 220))
box(1180, 580, 1700, 740, GREEN, '좌표 투영 계산', '드론 위치·자세각 → 화면 픽셀', (230, 242, 220))
# 출력 3종
box(1820, 210, 2340, 370, AMBER, '측점 스테이션바', '측점축 탐색 · 측점 검색', (247, 236, 208))
box(1820, 480, 2340, 640, AMBER, '영상 AR 오버레이', '시설물 정보 실시간 정합 표출', (247, 236, 208))
box(1820, 750, 2340, 910, AMBER, '대용량 영상 재생', '2GB+ 스트리밍 (Range/HLS)', (247, 236, 208))
# 화살표
arrow(560, 550, 672, 550) # 입력 → 파싱
arrow(1080, 510, 1172, 420) # 파싱 → 대응표
arrow(1080, 590, 1172, 640) # 파싱 → 투영
arrow(1700, 400, 1812, 305) # 대응표 → 스테이션바
arrow(1700, 660, 1812, 575) # 투영 → AR 오버레이
# 영상 원본 → 재생 (계산 우회, 하단 엘보 경로)
d.line((310, 950, 310, 1030), fill=PURPLE, width=7)
d.line((310, 1030, 2080, 1030), fill=PURPLE, width=7)
arrow(2080, 1030, 2080, 922)
lbl = ImageFont.truetype(FR, 26)
d.text((1195, 998), '영상 원본은 계산 없이 곧바로 스트리밍 재생', font=lbl, fill=(102, 102, 102), anchor='mm')
png = os.path.join(OUT_DIR, '그림_전체흐름도.png')
im.save(png)
print('PNG 저장:', png, im.size)
# PDF (이미지 삽입 + 압축)
import fitz
doc = fitz.open()
rect = fitz.Rect(0, 0, W / 2, H / 2)
page = doc.new_page(width=rect.width, height=rect.height)
page.insert_image(rect, filename=png)
pdf = os.path.join(OUT_DIR, '그림_전체흐름도.pdf')
doc.save(pdf, deflate=True, garbage=4)
print('PDF 저장:', pdf)