스캔된 PDF 클리너
펼친 책을 휴대폰으로 찍으면 제본 부근이 휘어지고, 기울어지며, 회색빛이 돌고, 가장자리에 엄지손가락과 다음 페이지 조각이 보입니다. 이 스킬은 그러한 페이지를 깨끗한 인쇄물처럼 읽을 수 있는 페이지로 바꿉니다.
스크립트는 픽셀 작업을 합니다. 사용자는 판단을 내립니다. 각 페이지의 모서리를 추적하고, 제거된 부분을 확인하며, 텍스트 바깥의 표시 중 인쇄된 것(유지)과 그렇지 않은 것(제거)을 결정합니다. 각 단계는 이미지로 읽을 수 있는 콘택트 시트를 작성하므로, 이를 확인하세요. 단계가 작동했다고 가정하지 마십시오.
설정 (머신당 한 번)
SKILL=<이 스킬이 있는 폴더> # 이 SKILL.md 파일이 들어 있는 폴더
python3 -m venv ~/.cache/scanned-pdf-cleaner-venv
~/.cache/scanned-pdf-cleaner-venv/bin/pip install -q -r "$SKILL/requirements.txt"
PY=~/.cache/scanned-pdf-cleaner-venv/bin/python
아래 모든 명령은 cd "$SKILL/scripts" && $PY <스크립트> ... 로 실행합니다. 문서당 하나의 비어 있는 새 작업 폴더를 사용하고, 사용자 프로젝트 외부(스크래치 또는 임시 폴더)에 만듭니다. 사용자의 파일은 읽기만 합니다.
워크플로우
1. 준비
$PY prepare.py INPUT.pdf WORK # 또는: 이미지 폴더, 또는 이미지 파일 (HEIC는 먼저 변환)
WORK/src/p-NNN.jpg(바로 선 사진), WORK/grid/g-NNN.jpg(각 사진에 100px 간격의 빨간 격자, 네 모서리에 백 단위 레이블), 그리고 WORK/rough.json(사진당 임시 윤곽선 포함)을 작성합니다.
사진이 옆으로 또는 거꾸로 되어 있으면 돌립니다: $PY prepare.py --turn WORK p-003.jpg 90|180|270 (시계 방향).
2. 페이지 모서리 추적 (사용자)
모든 격자 이미지를 읽습니다. 각 사진에서 문서에 속하는 페이지를 찾습니다. 네 모서리를 소스 픽셀 단위로 WORK/rough.json에 기록하며, 순서는 페이지가 읽히는 대로 왼쪽 위, 오른쪽 위, 오른쪽 아래, 왼쪽 아래입니다. 격자 레이블이 가로 7, 세로 12이면 [700, 1200]으로 기록합니다.
{"001": {"src": "p-000.jpg", "quad": [[96,72],[930,92],[945,1468],[70,1480]]}}
- 키는 출력 페이지 순서(
001,002, ...)입니다. 그 순서를 읽는 순서와 일치시키세요. - 페이지의 종이 가장자리를 기준으로 하며, 텍스트가 아닙니다. 제본 부근에서는 페이지가 안쪽으로 휘어지는 선을 기준으로 합니다. 사진 밖으로 나가는 페이지는 모서리를 사진의 가장자리에 둡니다.
- 양면 페이지 사진은 같은
src를 가진 두 항목(페이지당 하나)을 만듭니다. 예:"005"와"006". - 약 30픽셀 이내면 충분합니다. 다음 단계에서 실제 가장자리로 스냅합니다.
3. 종이 가장자리에 스냅
$PY refine.py WORK
WORK/quads.json과 WORK/sheets/quads-NN.jpg를 작성합니다. 주황색 = 사용자 추적, 빨간색 = 스냅됨, 녹색 점 = 왼쪽 위. 시트를 읽습니다. 빨간 윤곽선이 그림자, 테이블 또는 이웃 페이지 위로 점프했다면 해당 추적을 수정하고 단계를 다시 실행합니다.
4. 평평하게 펴기, 색조 보정 및 가장자리 정리
$PY clean.py WORK # 또는: clean.py WORK 004 007 특정 페이지만 다시 수행
각 페이지에 대해 다음을 수행합니다:
- 텍스트 줄과 양쪽 정렬된 컬럼 가장자리를 찾습니다.
- 텍스트 블록을 직사각형으로 만들고 모든 줄에 하나의 부드러운 곡면을 맞춰 휘어진 줄이 곧게 나오도록 합니다.
- 종이는 흰색으로, 잉크는 검은색으로 보정합니다.
- 페이지 가장자리에 닿는 어두운 표시(손가락, 제본 컬, 주름, 다음 페이지 조각)를 제거합니다.
텍스트 줄이 5개 미만인 페이지(예: 제목 페이지, 전체 그림 페이지)는 대신 평범한 네 모서리 워핑을 적용합니다. 출력: WORK/pages/, WORK/blocks.json, WORK/sheets/review-NN.jpg. 여기서 빨간색 = 제거됨, 파란색 = 사용자 결정을 위해 남김, 녹색 = 텍스트 블록.
리뷰 시트를 읽습니다. 확인할 사항:
- 여전히 휘어져 있거나 페이지가 기울어져 있음: 추적이 잘못되었습니다.
rough.json을 수정한 후 해당 페이지에 대해 refine과 clean을 다시 실행하세요. - 녹색 상자 안에 빨간색으로 표시된 텍스트: 사용자에게 알리세요. 가장자리 정리는 텍스트 블록 안에 있는 텍스트를 제거하지 않습니다(페이지 가장자리 띠에 있지 않은 한).
5. 텍스트 외부 표시 목록 작성
$PY flags.py WORK
WORK/flags/flags-N.jpg를 작성합니다. 텍스트 블록 외부에 있는 모든 어두운 표시의 번호가 매겨진 타일입니다.
6. 유지 또는 제거 결정 (사용자)
플래그 시트를 읽고 WORK/decisions.json을 작성합니다:
{"keep": [0, 3, 4, 7], "strokes_only": [23], "erase": [{"page": "014", "box": [1500, 300, 80, 900], "mode": "strokes"}]}
- keep: 인쇄된 모든 것. 페이지 번호, 러닝 헤드, 장 번호, 캡션, 사이드 레이블, 표 규칙, 그림 및 드로잉이 포함됩니다. 인쇄된 글자는 선명하고 규칙적입니다. 책 속의 그림도 인쇄물입니다(아이들이 그린 낙서 같아도).
- remove: 숫자를 목록에서 빼세요. 필기, 펜 및 연필 메모, 얼룩, 점, 지문, 회색 막대, 찢어진 가장자리 그림자가 포함됩니다. 펜 선은 가늘고 고르지 않으며 종종 기울어져 있고 글꼴과 일치하지 않습니다.
- strokes_only: 인쇄된 글자에 펜 선이 지나가거나 옆에 있는 것. 1.5줄보다 긴 선만 제거됩니다.
- erase:
pages/page-KEY.jpg의 페이지 픽셀 단위 상자로, 텍스트 블록 안에 있으면서 제거하라고 요청된 표시를 위한 것입니다."mode": "all"은 상자를 하얗게 만들고,"strokes"는 긴 선만 제거합니다.
사용자가 원할 수 있는 것을 제거하기 전에 물어보세요. 여기에는 텍스트 안의 밑줄이나 줄 사이 메모, 형광펜이 포함됩니다. 기본값: 여백 메모는 제거, 텍스트 안의 밑줄은 유지. 인쇄물과 필기를 구분할 수 없을 때도 물어보세요. 타일을 보여주고 설명하지 마세요.
7. 마무리
$PY finish.py WORK OUT.pdf # --no-frame은 각 페이지의 자체 프레임 유지; --dpi 300이 기본값
수행하는 작업:
- 유지 항목을 제외한 텍스트 블록 외부의 모든 것을 하얗게 만듭니다.
- 블록 옆에 붙어 있는 길고 얇은 펜 브래킷을 제거합니다.
- 모든 페이지를 하나의 페이지 크기에 프레임합니다:
- 텍스트는 하나의 크기로 나옵니다. 가깝거나 멀리서 찍은 사진이 일치합니다. 스케일링은 텍스트 블록의 너비를 사용하거나, 그림이 컬럼을 좁히는 경우 줄 간격을 사용합니다.
- 측면 여백은 동일하므로, 한쪽 가장자리에 붙어 있거나 책 두께로 인해 중앙에서 벗어난 내용이 중앙에 배치됩니다.
- 모든 페이지는 동일한 위쪽 여백에서 시작합니다.
전달하기 전에 WORK/sheets/final-NN.jpg를 읽으세요. 모든 페이지에서 남은 얼룩, 잘린 텍스트 및 실수로 유지한 항목을 확인하세요. 그런 다음 사용자에게 PDF 경로를 알려주세요. 사용자가 달리 말하지 않는 한 입력 파일 옆에 PDF를 저장합니다(예: <name>_clean.pdf).
좋은 결과의 기준
- 텍스트 줄이 가장자리에서 가장자리까지 곧고 수평이며, 제본에 가장 가까운 줄도 포함합니다.
- 종이는 순수한 흰색이고 글자는 진한 검은색이며, 가는 획도 손상되지 않습니다. 큰 어두운 그림은 채우기를 유지합니다.
- 손가락, 그림자, 이웃 페이지 조각, 얼룩이 없습니다. 측면 여백이 동일하고 모든 페이지에서 텍스트 크기가 같습니다.
실제 사용 시 참고 사항
- 보정기는 텍스트를 읽으므로, 양쪽 정렬된 줄이 가득한 페이지에서 최상의 성능을 발휘합니다. 줄 모양만 보기 때문에 오른쪽에서 왼쪽으로 쓰는 언어(히브리어, 아랍어)를 포함한 모든 문자 체계에서 작동합니다.
- 그림 내의 짧은 줄(레이블)은 곡면 맞춤 시 무시되므로, 그림이 페이지를 접지 않습니다.
- 페이지의 많은 부분을 채우는 어두운 그림은 순진한 색조 보정으로 회색으로 바랠 수 있습니다.
tone()은 주변 종이에서 종이 추정치를 낮춰 유지합니다. - 페이지 컬이 제본 부근의 몇 글자를 삼켜버린 경우, 사진에는 복구할 내용이 없습니다. 그렇게 말하고 텍스트를 만들어내지 마세요.
- 두 컬럼 논문: 텍스트 블록은 두 컬럼을 모두 포함합니다. 리뷰 시트에서 제본을 가로질러 맞춰진 줄이 있는지 확인하세요.