사진을 PDF로
목표는 올바른 순서의 개별 페이지, 빡빡한 테두리, 가장자리의 필획 보존입니다. 사진과 함께 로컬에서 작업합니다. 이 과정에 특별한 플러그인이나 MCP는 필요하지 않습니다.
검증된 방법
- 소스 검토. EXIF를 고려하세요. 이름/시간과 내용 기준으로 순서를 확인하세요. 촬영 시간 자체만으로는 순서를 증명하지 않습니다. 표지, 펼침면, 재촬영된 중복, 빈 장을 찾으세요. 밝기만으로는 옅은 그림과 빈 페이지를 안정적으로 구분할 수 없습니다. 종이가 밝은 배경(흰 책상, 종이, 근처 화면) 위에 있고 윤곽이 감지되지 않으면 어둡고 무광인 표면에서 다시 촬영해 달라고 요청하세요.
- 페이지 레이블 지정. 낱장(문서, A4, 가로 포함)의 경우
prepare --layout pages를 실행하세요.auto는 접힌 흔적(등때기 그림자나 접힌 선)이 있을 때만 넓은 윤곽을 나누지만, 특이한 용지에서는 오류가 발생할 수 있습니다.scan.py prepare는 초안 manifest와 윤곽이 포함된 연락처 시트를 만듭니다. 감지기는 종이를 밝고 채도가 낮은 영역으로 찾아 가장자리를 '종이 → 어두운 배경'의 급격한 전환 지점으로 당기고, 펼침면의 경우 접힌 부분을 찾습니다. 접힌 부분은 줄이 꺾이는 지점입니다. 등때기 그림자는 한 페이지에만 있으므로, 깊은 그림자의 경우 접힌 부분은 밝기 차이의 어두운 쪽 기준선에 설정됩니다. 기준 노트북에서 접힌 부분의 중앙 오차는 2~3px입니다. 여전히 가정일 뿐입니다.flags(gutter-*,partner-mismatch,touches-frame,aspect-outlier,one-side-unruled,margin-ink,contour,full-frame-fallback,duplicate)가 비어 있지 않은 페이지는 우선 수동으로 레이블을 지정하세요. 나머지는 사진으로 확인하세요. 감지기가 모니터, 영수증 또는 펼침면의 절반을 잘못 잡을 수 있습니다.scan.py inspect는 각 모서리의 큰 확대 이미지를 프레임 분할로 제공합니다. 이를 통해 manifest에서 모서리를 수정하세요. 각 페이지는 EXIF 회전 후 좌표에서 TL, TR, BR, BL의 네 모서리를 갖습니다. - 원근 보정. 기본값은 페이지당 하나의 투영 행렬입니다. 자동으로 찾은 가장자리를 따라 개별 행/열을 이동하지 마세요. 그리드, 텍스트, 손가락, 그림자가 가장자리로 잘못 인식되어 전체 페이지에 물결 현상을 일으킬 수 있습니다. 명시적으로 요청된 구부러진 책 페이지의 완전한 교정에는 별도의 검증된 알고리즘과 추가적인 기하학 검증이 필요합니다.
- 테두리 조정. 모든 곳에 동일한 큰 여백보다는 빡빡한 자르기가 선호됩니다.
bleed_px의 기본값은 0입니다. 모서리 사이의 직선 바깥에 실제로 기록이나 구부러진 가장자리 정보가 남아 있는 경우에만 개별적으로 약간의 여백을 추가하세요. 글자 꼭대기, 점(ё, й 위), 왼쪽 날짜, 접힌 부분의 텍스트, 도면의 아래쪽 선을 확인하세요. 아래쪽 줄은 종종 가장자리까지 닿습니다. 이 경우 경계는 가장자리의 중앙값을 따르며 빡빡하지 않습니다. 빡빡한 가장자리와 종이 끝 사이에 펜 필획이 있으면prepare가 자동으로 가장자리를 그쪽으로 이동시킵니다(margin_ink필드, 너비의 4% 이하). 연필은 이렇게 보호되지 않으므로, 가장자리 근처의 연필 날짜와 서명은 눈으로 확인하세요. 구부러진 가장자리는 직선으로 근사되므로, 휘어진 페이지의 모서리가 약간 경계 밖에 남을 수 있습니다. PDF의 추가 자르기는crop명령으로 수행하며, 다시 늘리거나 JPEG 재압축하지 마세요. - 옅은 필획 보존. 부드러운 조명 보정은 허용되지만, 강한 이진화는 연필을 지울 수 있습니다. 표지, 사진 및 중요한 색상에 대해서는
enhance를 비활성화하세요. 생성 모델로 글자, 도표 또는 누락된 프레임 부분을 다시 그리지 마세요. OCR은 필요하거나 요청된 경우에만 추가하세요. - 최종 PDF 확인. 사용 가능한 PDF 스킬을 사용하여 생성/확인하고, 해당 스킬에서 제공하는 작업 마커를 포함하세요.
review는 모든 페이지를 렌더링하고, 연락처 시트를 만들며, 배경이나 가장자리 필기가 있는 페이지를 나열합니다(edges.json).compare는 각 페이지를 4% 여백과 빨간색 자르기 프레임과 함께 보여줍니다. 외부에 무엇이 남았는지 확인할 수 있습니다. 첫 페이지만 보지 말고 전체 문서를 검토하세요. 대량 작업을 위한 경제적인 방식: 모든 페이지에 대해compare를 실행하고, 16페이지 이하의 묶음으로 나누어 이미지 지원 가격이 저렴한 모델(Claude Code의 Sonnet, Codex의gpt-5.6-luna)을 사용하는 병렬 에이전트에게 references/screening.md의 작업을 변경 없이 전달합니다. 검토자가defect을 보고한 페이지와prepare플래그가 있는 페이지만 직접 열고, 확인된 것만 수정하세요. 8개의 알려진 3% 이상 모서리 오류가 있는 32페이지 초안에서 이 방식은 (Sonnet 7개, 플래그 1개로) 8개 모두 찾았고, 4개의 거짓 경보가 있었습니다. Haiku는 4개를 찾았고 거짓 경보만 추가했으므로 Haiku만으로는 충분하지 않습니다. 두 번째 노트북(32페이지, 작업 맞춤 없음)에서 Sonnet과gpt-5.6-luna는 눈에 띄는 배경 줄무늬를 발견했지만 거짓 경보는 없었고, 1.5~2% 모서리 오류가 있는 페이지는 놓쳤습니다.gpt-6.1-terra는 거의 모든 것을 표시했으며 (19개 중 12개 깨끗한 페이지 포함), 이를 사용한 경제적 이점은 없습니다. 이 방식은 하나의 노트북에서 테스트되었고 작업도 같은 페이지로 구성되었습니다. 중요한 문서나 의심스러운 경우 모든 페이지를 직접 보세요. 검토자 응답의 페이지 번호는 순서도 함께 확인합니다. 자르기 후에는 영향을 받은 페이지를 재확인하고, 기하 알고리즘 변경 후에는 전체 문서를 재확인하세요. 페이지 수와 올바른 config는 직접 보는 것을 대체할 수 없습니다.
이러한 디지털화에서 사용자는 확인된 빈 페이지를 삭제하는 것을 선호합니다. 명시적으로 보존 요청이 있으면 그게 우선입니다. 중복은 시각적 확인 후에 제거하며, 그리드/필체 유사성으로 판단하지 마세요. 다른 지시가 없으면 표지는 보존하세요. 펼침면은 원본이 그렇게 구성된 경우 왼쪽에서 오른쪽으로 읽으세요.
명령어
스크립트 경로는 이 스킬을 기준으로 결정하세요. 스키마와 매개변수: references/commands.md. 이전 노트북의 모서리, 경로, 페이지 번호, 비율을 가져와 사용하지 마세요.
python3 <skill>/scripts/scan.py prepare <photos> --work <work> --layout auto
python3 <skill>/scripts/scan.py inspect <work>/manifest.json --work <work>/inspect --ids 0006-L,0006-R
python3 <skill>/scripts/scan.py build <work>/manifest.json --output <work>/draft.pdf
python3 <skill>/scripts/scan.py measure <work>/draft-pages --work <work>/measure
python3 <skill>/scripts/scan.py review <work>/draft.pdf --work <work>/review
python3 <skill>/scripts/scan.py compare <work>/draft.scan.json --work <work>/compare
의존성: Pillow, NumPy, OpenCV, ReportLab (사진용); pypdfium2 (crop용); Poppler pdftoppm (review 및 measure용). 임포트는 명령어별로 분리되어 있습니다. 사용 가능한 인터프리터/준비된 환경을 확인하세요. 필요한 경우 전역 Python을 변경하지 않고 별도의 venv를 사용하세요. OpenCV/NumPy가 시스템 패키지로 설치된 경우 동일한 인터프리터로 --system-site-packages를 사용하여 venv를 생성하세요 (python3 -m venv; uv venv는 기본적으로 자체 Python을 사용하여 시스템 cv2를 인식하지 못함). 네트워크는 필수가 아닙니다. 특정 머신의 캐시 경로를 스킬에 포함시키지 마세요.
비율과 용지 크기. aspect: null은 윤곽 측면에서 평가되며 각도에 따라 1~2% 정도 차이가 날 수 있습니다. 모눈종이의 경우 초안을 만들고 measure를 실행하세요. 이는 모눈 간격을 찾고 페이지의 물리적 크기를 계산하여 노트북 전체에 대한 하나의 aspect와 --width-mm을 제안합니다. 값은 이전 노트북이 아닌 출력에서 가져오세요. 동일한 --width-mm을 사용하면 모든 PDF 페이지가 동일한 물리적 크기를 갖습니다. 그렇지 않으면 크기는 픽셀과 --dpi에서 계산되어 촬영 거리에 따라 변동합니다.
build는 포함된 페이지에 대해 reviewed: true를 요구합니다. 이는 에이전트가 레이아웃을 확인했음을 나타내는 표시이며, 사용자와의 추가적인 확인이 아닙니다. 이미 전달된 사진의 일상적인 처리에 대한 허가를 묻지 마세요.
감지기 회귀. 검증된 노트북 manifest는 기준입니다. scan.py를 변경한 후에는 동일한 사진에 대해 prepare를 실행하고 eval <새 manifest> --reference <기준>을 실행하세요. 이 명령은 페이지 너비 대비 모서리 오류 비율, 표시된 페이지의 비율, '조용한' 오류(오류가 --tolerance(기본값 3%)를 초과하지만 표시되지 않은 페이지)를 보여줍니다. 조용한 오류가 --max-silent보다 많으면 종료 코드는 1입니다. 개인 사진이 포함된 기준은 스킬 저장소에 넣지 마세요.
완료
- 원본 사진을 변경하지 마세요. 기존 PDF는 새 버전을 확인한 후에 교체하세요. 부분 수정을 위해 레이아웃과 매개변수를 보관하세요.
- 재수정 시 먼저 파일의 최신성을 확인하세요. JPEG 재압축이 누적되지 않도록 하세요.
- 결과, 페이지 수 및 원본의 주요 제약 사항을 알리세요. 기록의 일부가 이미 프레임 밖이라면, 복원했다고 말하지 말고 그 사실을 알리세요.
- 이 스킬은 준비 과정과 반복적인 코드 작성을 절약해 주지만, 완전 자동 경계 인식이나 시각적 확인 생략을 보장하지는 않습니다.