@servantcdh/ez-planet-labeling 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -0
- package/dist/index-DDn_Fjhx.js +788 -0
- package/dist/index.d.ts +836 -0
- package/dist/index.js +2436 -0
- package/dist/style.css +1 -0
- package/package.json +52 -0
package/README.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# @servantcdh/ez-planet-labeling
|
|
2
|
+
|
|
3
|
+
Fabric.js v6 기반의 이미지 라벨링 워크스페이스 라이브러리.
|
|
4
|
+
|
|
5
|
+
3-Level API로 유연한 통합을 지원합니다.
|
|
6
|
+
|
|
7
|
+
[](https://stackblitz.com/github/servantcdh/ez-planet/tree/master/examples/labeling-demo?file=src/App.tsx)
|
|
8
|
+
|
|
9
|
+
## 설치
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @servantcdh/ez-planet-labeling
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Dependencies
|
|
16
|
+
|
|
17
|
+
### Peer Dependencies (호스트 앱에서 설치)
|
|
18
|
+
|
|
19
|
+
| Package | Version | 용도 |
|
|
20
|
+
|---------|---------|------|
|
|
21
|
+
| `react` | `^18.0.0` | UI 런타임 |
|
|
22
|
+
| `react-dom` | `^18.0.0` | DOM 렌더링 |
|
|
23
|
+
| `fabric` | `^6.0.0` | 캔버스 엔진 |
|
|
24
|
+
|
|
25
|
+
### Bundled Dependencies (라이브러리에 포함)
|
|
26
|
+
|
|
27
|
+
| Package | 용도 |
|
|
28
|
+
|---------|------|
|
|
29
|
+
| `zustand` | 내부 상태 관리 (호스트 앱 store와 격리) |
|
|
30
|
+
| `zundo` | Temporal history (Undo/Redo) |
|
|
31
|
+
| `@erase2d/fabric` | Fabric v6 EraserBrush 대체 |
|
|
32
|
+
|
|
33
|
+
## 3-Level API
|
|
34
|
+
|
|
35
|
+
### Level 1 — All-in-one
|
|
36
|
+
|
|
37
|
+
단일 컴포넌트로 완성된 라벨링 워크스페이스를 렌더링합니다.
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import { LabelingWorkspace } from '@servantcdh/ez-planet-labeling'
|
|
41
|
+
import '@servantcdh/ez-planet-labeling/dist/style.css'
|
|
42
|
+
|
|
43
|
+
<LabelingWorkspace
|
|
44
|
+
image={{ url: '/sample.png', width: 1920, height: 1080 }}
|
|
45
|
+
annotations={annotations}
|
|
46
|
+
onChange={(e) => setAnnotations(e.annotations)}
|
|
47
|
+
records={records}
|
|
48
|
+
activeRecordId={currentId}
|
|
49
|
+
onRecordSelect={handleSelect}
|
|
50
|
+
classes={classes}
|
|
51
|
+
onSave={handleSave}
|
|
52
|
+
tools={['selection', 'blankRect', 'polygon', 'brush', 'eraser']}
|
|
53
|
+
mode="labeling"
|
|
54
|
+
/>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Level 2 — Composable
|
|
58
|
+
|
|
59
|
+
Provider와 개별 컴포넌트를 조합하여 커스텀 레이아웃을 구성합니다.
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import {
|
|
63
|
+
LabelingProvider,
|
|
64
|
+
LabelingCanvas,
|
|
65
|
+
LabelingToolbar,
|
|
66
|
+
LabelingNavigation,
|
|
67
|
+
LabelingInfoPanel,
|
|
68
|
+
} from '@servantcdh/ez-planet-labeling'
|
|
69
|
+
import '@servantcdh/ez-planet-labeling/dist/style.css'
|
|
70
|
+
|
|
71
|
+
<LabelingProvider image={image} annotations={annotations} onChange={onChange} ...>
|
|
72
|
+
<LabelingNavigation records={records} activeRecordId={id} onRecordSelect={onSelect} />
|
|
73
|
+
<LabelingCanvas image={image} annotations={annotations} onChange={onChange} />
|
|
74
|
+
<LabelingToolbar tools={['selection', 'brush', 'eraser']} />
|
|
75
|
+
<LabelingInfoPanel classes={classes} annotations={annotations} />
|
|
76
|
+
</LabelingProvider>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Level 3 — Headless Hooks
|
|
80
|
+
|
|
81
|
+
UI 없이 캔버스 로직만 사용합니다.
|
|
82
|
+
|
|
83
|
+
```tsx
|
|
84
|
+
import {
|
|
85
|
+
useLabelingTools,
|
|
86
|
+
useLabelingCanvas,
|
|
87
|
+
useLabelingHistory,
|
|
88
|
+
} from '@servantcdh/ez-planet-labeling'
|
|
89
|
+
|
|
90
|
+
const { activeToolId, setTool, colorCode, setColorCode } = useLabelingTools()
|
|
91
|
+
const { addAnnotation, removeAnnotation, exportState } = useLabelingCanvas()
|
|
92
|
+
const { canUndo, canRedo, undo, redo } = useLabelingHistory()
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Props Reference
|
|
96
|
+
|
|
97
|
+
### LabelingWorkspaceProps
|
|
98
|
+
|
|
99
|
+
| Prop | Type | Required | Description |
|
|
100
|
+
|------|------|----------|-------------|
|
|
101
|
+
| `image` | `string \| { url, width, height }` | Yes | 라벨링 대상 이미지 |
|
|
102
|
+
| `annotations` | `Annotation[]` | Yes | 현재 어노테이션 목록 |
|
|
103
|
+
| `onChange` | `(event: CanvasChangeEvent) => void` | Yes | 어노테이션 변경 콜백 |
|
|
104
|
+
| `records` | `WorkspaceRecord[]` | Yes | 레코드 목록 (Navigation) |
|
|
105
|
+
| `activeRecordId` | `string` | Yes | 현재 활성 레코드 ID |
|
|
106
|
+
| `onRecordSelect` | `(record: WorkspaceRecord) => void` | Yes | 레코드 선택 콜백 |
|
|
107
|
+
| `classes` | `LabelingClass[]` | Yes | 라벨 클래스 목록 |
|
|
108
|
+
| `onSave` | `(state: CanvasState) => void` | Yes | 저장 콜백 |
|
|
109
|
+
| `tools` | `ToolType[]` | No | 사용할 도구 목록 |
|
|
110
|
+
| `mode` | `'labeling' \| 'validation' \| 'readonly'` | No | 워크스페이스 모드 |
|
|
111
|
+
| `theme` | `Partial<LabelingTheme>` | No | 테마 커스터마이징 |
|
|
112
|
+
| `layout` | `WorkspaceLayout` | No | 레이아웃 설정 |
|
|
113
|
+
| `extensions` | `LabelingExtension[]` | No | 확장 기능 |
|
|
114
|
+
| `validationResults` | `ValidationResult[]` | No | 검증 결과 (validation 모드) |
|
|
115
|
+
| `indicator` | `WorkspaceIndicator` | No | 진행 표시기 |
|
|
116
|
+
|
|
117
|
+
### Annotation
|
|
118
|
+
|
|
119
|
+
```ts
|
|
120
|
+
interface Annotation {
|
|
121
|
+
id: string // 호스트 앱에서 자유롭게 할당 (DB PK, UUID 등)
|
|
122
|
+
type: AnnotationType // 'box' | 'segmentation' | 'polygon' | 'brush' | ...
|
|
123
|
+
label: { name: string; index: number }
|
|
124
|
+
style: { color: string; opacity: number; lineColor?: string; lineWidth?: number }
|
|
125
|
+
geometry: AnnotationGeometry | null // BoxGeometry | PolygonGeometry | ...
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## 주요 기능
|
|
130
|
+
|
|
131
|
+
- **도구**: Selection, Bounding Box, Polygon, Brush, Eraser, Magic Brush, Superpixel
|
|
132
|
+
- **Extension System**: `ToolExtension`으로 커스텀 도구 등록 (SAM, AutoLabeling 등)
|
|
133
|
+
- **Validation Mode**: `mode="validation"`으로 검증 워크플로우 지원
|
|
134
|
+
- **SSR Safe**: `loadFabric()` 비동기 동적 import로 Next.js 호환
|
|
135
|
+
- **CSS Modules**: `lc-` prefix 스코핑, CSS 변수 기반 theming
|
|
136
|
+
- **Undo/Redo**: zundo 기반 temporal history
|
|
137
|
+
|
|
138
|
+
## Extension System
|
|
139
|
+
|
|
140
|
+
```tsx
|
|
141
|
+
import type { ToolExtension } from '@servantcdh/ez-planet-labeling'
|
|
142
|
+
|
|
143
|
+
const samExtension: ToolExtension = {
|
|
144
|
+
id: 'sam-tool',
|
|
145
|
+
slot: 'tool',
|
|
146
|
+
icon: <SAMIcon />,
|
|
147
|
+
label: 'SAM',
|
|
148
|
+
shortcut: 'S',
|
|
149
|
+
canvasHandlers: {
|
|
150
|
+
onMouseDown: (e) => { /* SAM point prompt */ },
|
|
151
|
+
onMouseUp: (e) => { /* Generate mask */ },
|
|
152
|
+
},
|
|
153
|
+
render: (ctx) => <SAMPanel context={ctx} />,
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
<LabelingWorkspace extensions={[samExtension]} ... />
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
## Theming
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
<LabelingWorkspace
|
|
163
|
+
theme={{
|
|
164
|
+
primary: '#3b82f6',
|
|
165
|
+
background: '#1a1a2e',
|
|
166
|
+
surface: '#16213e',
|
|
167
|
+
border: '#334155',
|
|
168
|
+
text: '#f1f5f9',
|
|
169
|
+
textSecondary: '#94a3b8',
|
|
170
|
+
fontFamily: 'Pretendard, sans-serif',
|
|
171
|
+
radius: 8,
|
|
172
|
+
}}
|
|
173
|
+
...
|
|
174
|
+
/>
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT
|