CaptchaConda
머신러닝 없이 고전 이미지 처리만으로 숫자 캡챠를 푸는 솔버. 학습 데이터도, GPU도, 프레임워크도 필요 없다. 매칭 코어는 C++ 백엔드로 이식돼 있고, Python은 얇은 껍데기 (전처리·세그멘테이션·오케스트레이션)로 남는다. 각 환경에 맞는 백엔드는 설치 후 한 번만 빌드한다.
설치
pip install CaptchaConda
python -m CaptchaConda init # 이 환경에 맞게 C++ 백엔드 빌드 (CPU)
# 또는 GPU 환경:
python -m CaptchaConda init --cuda # nvcc 로 CUDA 백엔드 빌드
init은 대화형 마법사로 진행된다(화살표 ↑/↓ 선택, Enter 확정):
- 빌드 방식 선택 — C++ (권장) / Python(빌드 없이 종료)
- 디바이스 선택 — CPU / CUDA
- 현재 라이브러리·컴파일러 검색(스피너)
- 빌드 바이너리 상태 판단 — 없으면 빌드 / 예전 버전이면 업그레이드 확인 / 최신이면 재빌드 확인
- 컴파일러 선택(하나여도 확인) — 없으면 다운로드 여부를 묻고 자동 설치(
build-essential/nvidia-cuda-toolkit등) - 빌드 프로그레스 바
비대화형(파이프/CI) 환경에서는 안전한 기본값(C++/CPU)으로 자동 진행된다. 컴파일러가 전혀 없고 설치도 거부하면 순수 Python 폴백으로 실행할 수 있다(동일 결과, 조금 느림).
사용
from CaptchaConda import CaptchaConda
device = "cuda" # 또는 "cpu"
cc = CaptchaConda(devices=device) # 처음 1회만
cc.init() # 처음 1회만 (백엔드 빌드+로드)
print(cc.solve("captcha.png")) # -> "39825"
print(cc.solve(pil_image, expected_n=5))
CaptchaConda(devices="cpu"|"cuda")— 백엔드 종류 선택init(force=False)— 백엔드 빌드/로드(캐시됨;force=True로 재빌드)solve(image, expected_n=None)— 이미지(경로 또는 PIL) → 숫자 문자열
델타트레이스 (DeltaTrace) — 흐름 기반 분류기
정적 필터 매칭 대신, 형상을 주파수 변환으로 표현해 코사인 유사도로 분류한다. 기본 표현은 글리프의 2D DCT 좌상단 8×8 블록 + 구멍 y위치다. DCT는 형상 에너지를 저차 계수에 모으므로(JPEG 원리) 작은 블록이 곧 압축 특징 — PCA가 필요 없다. 6/9처럼 회전으로 겹치는 숫자는 구멍 y위치로 가르고, 구멍 수로 게이팅한다.
cc.solve(img, expected_n=5, method="deltatrace") # 기본 = 2D DCT (PCA 불필요)
cc.solve(img, expected_n=5, color="green", seg_mode="cluster", method="deltatrace")
d, conf, scores = cc.classify_glyph(glyph, method="deltatrace")
성능(합성): 자리당 easy 100% / medium 99.8% — 필터 백엔드(99.7/97.5)와 다른 표현 모두를 넘어선다. 참고: 분류 시간의 대부분은 변환이 아니라 구멍(위상) 계산이 차지하므로, 순수 속도가 중요하면 C++ 필터 백엔드(자리당 ~34µs)가 여전히 가장 빠르다.
표현 선택 (dt_repr): "dct"(기본, 위) / "fft2d"(2D FFT+PCA, 99.5%·더 느림) /
"fourier"(윤곽 1D 복소 FFT, 99.2/98.8) / "turning"(방향 변화량 1D, ~88%). "turning"은
dt_topo로 위상 게이팅 선택 — 구멍 수(기본)가 분기 수(실험용·불안정 57%)보다 훨씬 낫다.
상호운용 & 신뢰도 (다른 라이브러리와 조합)
통짜 솔버가 아니라 파이프라인 단계를 노출해, 다른 OCR/ML 라이브러리와 섞어 쓸 수 있다.
# 1) 문자별 상세(바운딩박스 + 신뢰도)로 후처리/라우팅
for ch in cc.solve(img, expected_n=5, return_detail=True):
print(ch["digit"], ch["bbox"], ch["confidence"]) # confidence = 1등-2등 마진
# 2) 세그멘테이션만 쓰고 분류는 다른 라이브러리에 맡기기
for bbox, glyph in cc.segment(img, expected_n=5): # glyph: 정규화 (36,28)
digit = my_other_model.predict(glyph) # 외부 분류기
# 3) 외부에서 잘라온 글리프를 CaptchaConda 분류기로
digit, conf, scores = cc.classify_glyph(my_glyph)
confidence(1등-2등 점수 마진)가 낮으면 애매하거나 실패한 인식이다. 이를 임계로 걸어
저신뢰 문자는 다른 라이브러리로 폴백하는 하이브리드 구성이 가능하다.
색 타깃 + 클러스터링 세그멘테이션 (컬러 캡챠용)
실제 캡챠는 숫자와 방해선의 색이 다른 경우가 많다(예: 초록 숫자 + 보라 물결선). 배경 대비 대신 숫자 색만 타깃하면 다른 색 방해선이 통째로 사라진다. 또 숫자가 붙어 있으면 연결 성분이 뭉치므로, 잉크 x좌표를 k=기대 자리수로 클러스터링해 강제 분리한다(1D k-means, 외부 의존성 없음).
cc.solve(img, expected_n=5, color="green") # 초록 숫자만, 다른색 선 제거
cc.solve(img, expected_n=5, color="green", seg_mode="cluster")# 붙은 숫자 강제 5분할
cc.solve(img, expected_n=5, color="auto", seg_mode="cluster")# 숫자 색 자동 추정
cc.solve(img, expected_n=5, color=(40,112,57)) # 정확한 RGB 지정
color:None(기본, 배경 대비) ·"green"/"red"/"blue"·(r,g,b)·"auto"seg_mode:"connected"(기본) ·"cluster"(x좌표 k-means 강제 분할)enhance:True면 노출·대비·채도 강조로 흐린 색 숫자를 또렷하게 전처리color="green"은 틸(teal, 초록≈파랑) 숫자까지 잡되 파란 선(B≫G)은 제외한다deline=True: 색 숫자를 관통하는 다른 색 선을 인페인팅으로 제거(선이 끊은 획을 주변색으로 복원). 겹친 숫자를 완전히 살리진 못한다
한계: 숫자가 매우 흐리거나 얇은 윤곽이라 색으로도 온전히 못 뽑히는 캡챠는 여전히
낮게 나온다(입력 신호 자체의 한계). 이럴 때는 return_detail의 confidence가 낮게
찍히므로, 저신뢰 케이스만 ML 폴백으로 넘기는 하이브리드를 권장한다.
한계 및 대응 (정직하게)
- 얇은 방해선(1~2px): 같은 색이어도 잘 처리된다(자리당 95~98%).
- 두꺼운 방해선(≥3~4px)이 숫자를 관통·융합하는 경우: 성능이 급락한다. 색이 숫자와 같으면 분리 신호가 없고, 선이 여러 숫자를 이어 붙이면 세그멘테이션이 하나로 병합돼 잘못 쪼개진다(예측이 한두 숫자로 퇴화). 이는 학습 없는 고전 이미지 처리의 근본 한계다.
- 대응: 위
confidence로 실패를 감지하고,segment()로 얻은 글리프를 ML OCR 등 다른 라이브러리로 폴백하는 하이브리드를 권장한다. CaptchaConda는 빠른 1차 필터 (대부분의 깨끗/얇은선 캡챠를 CPU로 즉시 처리)로 쓰고, 저신뢰 케이스만 무거운 모델로 넘기면 전체 비용을 크게 아낄 수 있다.
왜 이런 구조인가
- Python은 그대로 배포 → 이식성. 무거운 계산은 C++ 백엔드가 담당.
- 백엔드는 소스로 배포되고
init때 각 환경에 맞게 컴파일 → 배포 바이너리 호환성 문제를 피하고, CUDA가 있으면 GPU 백엔드로 빌드. - 학습이 없으므로 모델 파일·GPU·데이터셋 비용이 0. 필터 데이터(수십 KB)만 동봉.
동작 개요
이미지 → 배경 분리 → 숫자 분리 → (C++) 필터 매칭 + 위상 라우팅 + 이중필터 → 시퀀스. 정확도는 타깃 캡챠 분포에 맞춰 동봉 필터를 튜닝할수록 올라간다.
Metadata
Release files for CaptchaConda 1.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| captchaconda-1.2.0.tar.gz | 426.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| captchaconda-1.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 854.8 kB
Release files / captchaconda-1.2.0.tar.gz
| Download URL | captchaconda-1.2.0.tar.gz |
|---|---|
| Size | 426.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3fdac8bf978224f6d7c32ac3bd924a0983b95dac438543b6ee0f0a75a5272969
|
|
BLAKE2b-256 checksum How to use checksums |
780dbe7b24151eeae087cde7c9e896454361dc5cf7927d18873b10adfe5fd6dd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.6
|
Release files / captchaconda-1.2.0-py3-none-any.whl
| Download URL | captchaconda-1.2.0-py3-none-any.whl |
|---|---|
| Size | 428.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
811972a05c2d57f09080b023755d4f6560b9783665fe1291a3c78134e9505e96
|
|
BLAKE2b-256 checksum How to use checksums |
44fce99e076e08d9293f8871667f198086f6570cd8571fc4881ae32d95aae104
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.6
|