日本語 · English · 简体中文 · 繁體中文 · 한국어 · Deutsch
Fullseye는 범위가 넓어서, 맨 처음 “무엇을 먼저 열어볼지”를 정하지 못하면 멈춰버립니다. 여기 나열한 것은 새로 작성한 데모가 아니라 게이트(gate)가 매번 실행하고 있는 예제입니다(실패하면 CI가 빨간색이 됩니다).
| 진입점 | 대상 | 5분: 우선 실행 | 30분: 내부까지 추적 | 반나절: 내 데이터로 |
|---|---|---|---|---|
| 설명 가능한 외관 검사 | 검사·품질 보증 | py -3.11 examples/poc_solder_fillet_aoi.py 납땜 필렛(fillet) AOI |
py -3.11 examples/poc_fabric_defect.py 미검출과 오검출을 나누어 집계 |
CAPABILITIES.md의 “찾기” → Studio에서 내 이미지로 |
| 로봇을 위한 3-D | 로봇·3-D 계측 | py -3.11 examples/perception_pipeline.py 스테레오→깊이→포인트 클라우드→주행 가능성 |
py -3.11 examples/grasp_pose.py 포인트 클라우드를 모델에 정합해 6-DoF 자세와 파지 방향 산출 |
EXAMPLES_3D.md → 내 포인트 클라우드·메시 입력 |
| 물리 기반 비파괴 검사 | X선·광학·계측 | py -3.11 examples/ct_reconstruction.py 투영→재구성→치수(mm)와 결함 수 |
py -3.11 examples/poc_ct_void_morphology.py 합격/불합격이라는 숫자 하나가 형상에 왜 무지한가 |
CAPABILITIES.md의 “형상화” → 내 볼륨 데이터로 |
어느 예제든 참값(ground truth)을 갖고 있습니다(폐형해 또는 합성 데이터). 항상 제로 포인트(아무것도 하지 않았을 때)의 결과를 함께 제시하므로, “효과가 있었다”고 말할 수 있는지 스스로 확인할 수 있습니다. 어디까지 검증되어 있는지의 장부는 MATURITY.md에 있습니다 —— 손으로 작성한 것이 아니라, 실제로 돌아가는 게이트와 실데이터 유무로부터 집계해 낸 것입니다.
이 문서는 Fullseye(작업명 imgevolve)를 최단 경로로 실행하기 위한 가이드입니다. 설치 → 첫 파이프라인 만들기 → 실행 → 결과 확인의 순서로, 막히지 않는 동선을 따라 진행합니다. 더 상세한 환경 구축은 INSTALL.md, Studio의 전체 기능은 STUDIO_GUIDE.md, 코드에서의 실행은 ENGINE.md를 참조하세요.
Fullseye는 numpy 배열을 입력·출력으로 하는 이미지 처리 연산자 라이브러리이며, 그 위에 HDevelop풍의 시각적 파이프라인 설계 환경(Fullseye Studio)과 실행 런타임(FullseyeEngine)이 얹혀 있습니다. HALCON/HDevelop 식으로 말하면 “HDevelop에서 절차를 조립하고, HDevEngine에서 자신의 애플리케이션에서 호출한다”는 2단 구조를, 그대로 Python + numpy로 재현한 것입니다.
전제 조건: Python 3.11(Windows는 py -3.11, Linux는 python3.11).
cd <path-to-fullseye>
py -3.11 -m pip install -e . # numpy + scipy 코어만(약 885개 연산자)
코어는 numpy와 scipy만으로 동작합니다. OpenCV / scikit-image / Pillow 등 추가 백엔드는 선택 사항이며, 설치되어 있지 않아도 해당 백엔드 고유의 연산자만 비활성화될 뿐입니다(우아한 저하, graceful degradation). 실무에서는 최소한 이미지 파일 읽기/쓰기에 OpenCV나 Pillow가 필요하므로, 다음 중 하나를 추가로 설치해 두면 편리합니다.
py -3.11 -m pip install -e ".[opencv]" # 이미지 I/O + OpenCV 유래 연산자
py -3.11 -m pip install -e ".[all]" # 전체 백엔드(opencv, skimage, pil, wavelets, gpu, extra)
py -3.11 -m pip install -e ".[gui]" # Fullseye Studio(PySide6)를 사용한다면
extras 목록과 의미는 INSTALL.md에 정리되어 있습니다. GUI를 사용하려면 [gui](또는 [all] + [gui])가
필요합니다.
설치하지 않고 시험해 볼 수도 있습니다. 저장소 최상위 디렉터리(
<path-to-fullseye>)를 작업 디렉터리로 하고, 환경 변수PYTHONPATH에 그 경로를 등록하면import fullseye는 동작합니다. 다만fullseye/fullseye-studio라는 명령(콘솔 스크립트)은pip install -e .를 실행해야 비로소 사용할 수 있습니다.
import fullseye, numpy as np
frame = np.clip(np.random.default_rng(0).random((64, 64)), 0, 1) # gray H×W in [0,1]
edges = fullseye.apply(frame, "sobel_amp") # image → image(그래디언트 강도)
seg = fullseye.apply(frame, "otsu") # image → region(0/1 이진)
n = fullseye.apply(seg, "count_obj") # region → feature(객체 수 = Python float)
print(n) # 예: 316.0
인자 순서는
apply(image, name, a, b)— 첫 번째 인자가 배열, 두 번째 인자가 연산자 이름입니다. 반대로 넘기면 0.1.9부터는TypeError: ... arguments look swapped로 멈춥니다(0.1.8까지는 numpy의 “truth value of an array is ambiguous”라는 관계없는 오류가 발생했습니다).a/b는 0..1 사이의 유한값이어야 합니다. 문자열·None·NaN은 즉시TypeError/ValueError가 되고, 범위를 벗어난 값은 잘려서 장부에 기록됩니다.
apply(image, name, a=0.5, b=0.5)는 연산자 1개를 적용합니다. name은 연산자 이름(예: gaussian)이어도
HALCON 별칭(예: gauss_filter)이어도 모두 해석됩니다.a, b는 각 연산자가 가진 2개의 다이얼(0.0~1.0)입니다. 의미는 연산자마다 다릅니다(반경·임계값·σ 등).image(그레이스케일) / region(이진) / feature(스칼라 float) /
color(RGB) / contour(XLD) / volume(3D).on_error="fallback"에서는, 연산자가 내부에서 실패해도 타입에
맞는 무해한 값(이미지라면 입력의 복사본 등)이 반환되고, 같은 연산자에 대해 1회만 FullseyeFallbackWarning이
발생합니다. 무엇이 몇 번 폴백했는지는 fullseye.fallbacks() / fullseye.fallback_counts()로 확인할 수 있습니다.
on_error="raise"를 넘기면(또는 환경 변수 FULLSEYE_ON_ERROR=raise) fail-closed가 되어, 연산자의 진짜
예외·dtype 계약 위반(정수/bool 이미지)·GPU 커널 실패가 그대로 발생합니다. sort 불일치는 부분적으로만 검사됩니다
(예: RGB (H,W,3)을 2-D 연산자에 넘기면 볼륨으로 처리되어, raise에서도 예외가 되지 않습니다 —
docs/KNOWN_ISSUES.md #32-4). CI나 검증에서는 raise를 권장합니다.add_image / union2 등, list_ops()에서 tier == "nary")는 입력을 리스트로 전달합니다:
fullseye.apply([img1, img2], "add_image").ncc_locate / shape_locate)은 template=으로 찾을 이미지를 전달합니다:
corr, row, col = fullseye.apply(img, "ncc_locate", template=patch)(반환되는 row/col은 일치 위치의 중심입니다).
템플릿이 없으면 no-match인 [0, 0, 0]이 반환됩니다.어떤 연산자가 있는지는 다음으로 찾을 수 있습니다.
fullseye.op_names() # 전체 레지스트리 연산자 이름(860개, 2026-09-03 기준)
fullseye.list_ops(search="edge") # 이름 / HALCON 이름 / 카테고리로 부분 일치 검색
fullseye.list_ops(sort="region") # 입력 sort로 필터링
fullseye.categories() # 47개 카테고리
여러 연산자를 순서대로 통과시키는 것이 “파이프라인”입니다. 배열을 각 단계로 전달해 최종 결과를 반환합니다.
# 모든 단계에서 같은 a, b를 사용(CLI와 같은 형태)
out = fullseye.run_pipeline(frame, ["gaussian", "sobel_amp", "otsu"])
# 단계마다 다른 다이얼을 쓰고 싶을 때((name, a, b) 튜플로 지정)
out = fullseye.run_pipeline(frame, [("gaussian", 0.3, 0.5), ("otsu", 0.4, 0.5)])
이것은 “smooth(평활화) → 에지 강도 → Otsu 이진화”로, 이미지에서 이진 에지 맵을 만드는 전형적인 예입니다. 바로 쓸 수 있는 조합(레시피)이 20개 동봉되어 있습니다.
import recipes
recipes.names() # 레시피 이름 목록
stages = recipes.stages("Edge — Sobel + Otsu") # [(op, a, b), ...]
out = fullseye.run_pipeline(frame, stages)
코드를 작성하지 않고, 연산자를 검색해 배치하고, 다이얼을 슬라이더로 돌리고, 한 단계씩 실행하며 중간 결과를 눈으로
보면서 조립할 수 있습니다. GUI extras(pip install -e ".[gui]" = PySide6)가 필요합니다.
py -3.11 studio.py # 또는 설치되어 있다면: fullseye-studio
3개의 패널로 구성됩니다.
op (a, b) 한 줄을 씁니다(값은
repr의 전체 정밀도. Program에 아직 적용되지 않은 수동 편집이 있으면 그 줄만 삽입되고, Apply로 반영됩니다).param_specs.py)이 있는 경우 실제 단위로 조작할
수 있습니다 — gaussian이라면 σ를 px로(슬라이더 + 단위가 붙은 스핀), median이라면 커널 크기를 3/5/7/9의
콤보로, reg_erode라면 반복 횟수를 정수 스핀으로, aug_barrel의 b는 “pincushion” 체크박스로. 오른쪽 끝의 0..1
스핀은 항상 원시 값입니다(정확한 입력용). 사양은 ops.py의 변환식(예: 0.3 + 2.7·a)으로부터 수기로 작성했고,
테스트로 구현과 대조하고 있습니다(tests/test_studio_params.py). 사양이 없는 연산자는 기존과 같이 0..1 슬라이더
2개입니다. 단계 목록도 표시 단위로 기록됩니다(gaussian (blur σ=1.08 px, b=–)). Reset(Home) → Step(Ctrl+→) →
Run all(Ctrl+Enter)로 한 단계씩, 또는 한 번에 실행할 수 있습니다.조립한 파이프라인은 Export(Ctrl+E)로 --ops 문자열이나 Python 코드로 내보낼 수 있고, Save pipeline
(Ctrl+Shift+S)로 JSON으로 저장할 수 있습니다. 전체 기능과 단축키는 STUDIO_GUIDE.md를, 앱
내에서는 F1로 목록이 나옵니다.
Studio에서 Save pipeline한 JSON(또는 --ops 문자열)을, 그대로 파일에 대해 실행할 수 있습니다. 이것이
HDevEngine에 해당하는 “설계한 것을 다시 작성하지 않고 실행한다”는 경로입니다.
# 저장한 JSON의 I/O와 각 단계를 확인(이미지 없이 구조만 점검)
py -3.11 imgevolve.py run edge.json --describe
# 이미지에 적용해 결과를 저장
py -3.11 imgevolve.py run edge.json in.png --out result.png
# 한 단계씩 결과를 저장(result_00.png, result_01.png, ...)
py -3.11 imgevolve.py run edge.json in.png --stepwise --out step.png
# 파이프라인을 단독 Python 함수로 내보내기
py -3.11 imgevolve.py run "gaussian,sobel_amp,otsu" --to-python
코드에서 실행할 때는 FullseyeEngine을 사용합니다(자세한 내용은 ENGINE.md).
import fullseye
eng = fullseye.FullseyeEngine.load("edge.json") # or .from_ops("gaussian,sobel_amp,otsu")
print(eng.input_sort(), "->", eng.output_sort()) # image -> region
out = eng.run(frame) # numpy in, numpy out
steps = eng.run_stepwise(frame) # 각 단계의 중간 결과(리스트)
이미지 파일을 직접 처리하고 싶을 때는 CLI가 간편합니다(이미지 I/O에 OpenCV나 Pillow가 필요합니다).
py -3.11 imgevolve.py ops --search edge # 연산자 검색
py -3.11 imgevolve.py has gauss_filter # 해당 HALCON 이름이 구현되어 있는지 + 호출 방법
py -3.11 imgevolve.py apply gauss_filter in.png out.png --a 0.6
py -3.11 imgevolve.py pipeline in.png out.png --ops "gaussian,sobel_amp,otsu"
apply / pipeline은 각 단계에서 공통의 --a / --b를 사용합니다. 단계마다 다른 다이얼을 쓰고 싶다면,
위의 run_pipeline(Python)이나 Studio를 사용하세요.
| 증상 | 대처 |
|---|---|
ModuleNotFoundError: No module named 'fullseye' |
pip install -e .를 실행하거나, 저장소 최상위 디렉터리를 PYTHONPATH에 등록 |
fullseye / fullseye-studio 명령이 없음 |
콘솔 스크립트는 pip install -e .로 등록됩니다. 설치하지 않았다면 py -3.11 imgevolve.py ... / py -3.11 studio.py를 사용 |
| Studio가 실행되지 않음 | GUI extras 미설치. pip install -e ".[gui]"(PySide6) |
apply / pipeline에서 cannot read ... |
이미지 I/O용으로 OpenCV([opencv])나 Pillow([pil])를 설치 |
| 추가 백엔드의 연산자가 “unknown”으로 표시됨 | 해당 백엔드가 미설치. .[skimage] .[wavelets] .[extra] 등을 추가 |
더 상세한 문제 해결은 INSTALL.md를 참조하세요.