anycv-sdk 0.1.0__tar.gz

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.
Files changed (34) hide show
  1. anycv_sdk-0.1.0/PKG-INFO +394 -0
  2. anycv_sdk-0.1.0/README.md +369 -0
  3. anycv_sdk-0.1.0/pyproject.toml +45 -0
  4. anycv_sdk-0.1.0/setup.cfg +4 -0
  5. anycv_sdk-0.1.0/src/anycv_sdk/__init__.py +35 -0
  6. anycv_sdk-0.1.0/src/anycv_sdk/algorithms/__init__.py +38 -0
  7. anycv_sdk-0.1.0/src/anycv_sdk/algorithms/base_yolo.py +95 -0
  8. anycv_sdk-0.1.0/src/anycv_sdk/algorithms/crowd.py +66 -0
  9. anycv_sdk-0.1.0/src/anycv_sdk/algorithms/external_http.py +101 -0
  10. anycv_sdk-0.1.0/src/anycv_sdk/algorithms/floating_plastic.py +47 -0
  11. anycv_sdk-0.1.0/src/anycv_sdk/algorithms/illegal_parking_obb.py +53 -0
  12. anycv_sdk-0.1.0/src/anycv_sdk/algorithms/python.py +324 -0
  13. anycv_sdk-0.1.0/src/anycv_sdk/algorithms/yolo_results.py +81 -0
  14. anycv_sdk-0.1.0/src/anycv_sdk/cli.py +42 -0
  15. anycv_sdk-0.1.0/src/anycv_sdk/core/__init__.py +5 -0
  16. anycv_sdk-0.1.0/src/anycv_sdk/core/adapter.py +170 -0
  17. anycv_sdk-0.1.0/src/anycv_sdk/core/config.py +181 -0
  18. anycv_sdk-0.1.0/src/anycv_sdk/core/engine.py +162 -0
  19. anycv_sdk-0.1.0/src/anycv_sdk/core/errors.py +23 -0
  20. anycv_sdk-0.1.0/src/anycv_sdk/core/images.py +39 -0
  21. anycv_sdk-0.1.0/src/anycv_sdk/core/models.py +121 -0
  22. anycv_sdk-0.1.0/src/anycv_sdk/core/params.py +57 -0
  23. anycv_sdk-0.1.0/src/anycv_sdk/core/streams.py +161 -0
  24. anycv_sdk-0.1.0/src/anycv_sdk/service.py +406 -0
  25. anycv_sdk-0.1.0/src/anycv_sdk/standalone.py +347 -0
  26. anycv_sdk-0.1.0/src/anycv_sdk.egg-info/PKG-INFO +394 -0
  27. anycv_sdk-0.1.0/src/anycv_sdk.egg-info/SOURCES.txt +32 -0
  28. anycv_sdk-0.1.0/src/anycv_sdk.egg-info/dependency_links.txt +1 -0
  29. anycv_sdk-0.1.0/src/anycv_sdk.egg-info/entry_points.txt +2 -0
  30. anycv_sdk-0.1.0/src/anycv_sdk.egg-info/requires.txt +15 -0
  31. anycv_sdk-0.1.0/src/anycv_sdk.egg-info/top_level.txt +1 -0
  32. anycv_sdk-0.1.0/tests/test_core.py +237 -0
  33. anycv_sdk-0.1.0/tests/test_service.py +142 -0
  34. anycv_sdk-0.1.0/tests/test_standalone.py +155 -0
@@ -0,0 +1,394 @@
1
+ Metadata-Version: 2.4
2
+ Name: anycv-sdk
3
+ Version: 0.1.0
4
+ Summary: 适用于AnyCV视觉识别算法的统一SDK和FastAPI服务
5
+ Keywords: computer-vision,fastapi,algorithm-sdk,inference
6
+ Classifier: Programming Language :: Python :: 3
7
+ Classifier: Programming Language :: Python :: 3.12
8
+ Classifier: Framework :: FastAPI
9
+ Classifier: Topic :: Scientific/Engineering :: Image Recognition
10
+ Requires-Python: <3.13,>=3.12
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: fastapi>=0.110.0
13
+ Requires-Dist: pydantic>=2.0.0
14
+ Requires-Dist: python-multipart>=0.0.9
15
+ Requires-Dist: PyYAML>=6.0.0
16
+ Requires-Dist: requests>=2.31.0
17
+ Requires-Dist: uvicorn[standard]>=0.29.0
18
+ Provides-Extra: algorithms
19
+ Requires-Dist: numpy>=1.26.0; extra == "algorithms"
20
+ Requires-Dist: opencv-python>=4.9.0; extra == "algorithms"
21
+ Requires-Dist: ultralytics>=8.2.0; extra == "algorithms"
22
+ Provides-Extra: dev
23
+ Requires-Dist: httpx>=0.27.0; extra == "dev"
24
+ Requires-Dist: pytest>=8.0.0; extra == "dev"
25
+
26
+ # AnyCV SDK
27
+
28
+ > 新增配置优先接入方式:算法项目可以只提供 `algorithm.py` 和 `anycv.yaml`,通过 `adapter: python` + `entrypoint` 自动生成标准 FastAPI 接口。详见 [配置优先的 SDK 接入方式](docs/config-first-sdk.md)。
29
+
30
+ AnyCV SDK 是一个面向视觉算法项目的统一接入层。它把不同算法的模型加载、单帧推理、RTMP 流式任务、健康检查、Swagger 文档和参数解析收敛到同一套 Python SDK 与 FastAPI 服务里。
31
+
32
+ 当前项目只保留两条主线:
33
+
34
+ - **anycv 主环境**:本仓库作为统一算法运行环境,通过 `configs/algorithms.yaml` 管理多个算法,启动一个 FastAPI 服务统一暴露算法接口。
35
+ - **SDK 分发包**:把 `anycv_sdk` 打成 SDK 包给算法同事使用。算法同事只需要实现算法类并引入 SDK,即可自动暴露健康检查、单帧推理、OPTIONS 探测和可选流式接口。
36
+
37
+ ## 项目结构
38
+
39
+ ```text
40
+ anycv/
41
+ ├─ pyproject.toml # Python 包元信息、依赖、命令行入口
42
+ ├─ configs/
43
+ │ └─ algorithms.yaml # 统一多算法服务配置
44
+ ├─ src/
45
+ │ └─ anycv_sdk/
46
+ │ ├─ __init__.py # SDK 对外导出入口
47
+ │ ├─ cli.py # anycv-service 命令行入口
48
+ │ ├─ service.py # 统一多算法 FastAPI 服务
49
+ │ ├─ standalone.py # 单算法模板 FastAPI 服务
50
+ │ ├─ core/
51
+ │ │ ├─ adapter.py # 多算法适配器基类
52
+ │ │ ├─ config.py # YAML 配置加载和路径解析
53
+ │ │ ├─ engine.py # 多算法运行引擎
54
+ │ │ ├─ images.py # 图片解码、base64 编码
55
+ │ │ ├─ models.py # 配置、结果、流任务数据模型
56
+ │ │ ├─ params.py # HTTP 表单参数解析与合并
57
+ │ │ └─ streams.py # 本地推流子进程管理
58
+ │ └─ algorithms/
59
+ │ ├─ __init__.py # adapter 名称到具体类的注册入口
60
+ │ ├─ base_yolo.py # YOLO 算法通用加载逻辑
61
+ │ ├─ crowd.py # 人群检测/人数统计适配器
62
+ │ ├─ floating_plastic.py # 漂浮塑料垃圾检测适配器
63
+ │ ├─ illegal_parking_obb.py # 车辆违停 OBB 检测适配器
64
+ │ └─ yolo_results.py # YOLO 结果转换工具
65
+ ├─ algorithms/ # 原始算法脚本和算法侧配置
66
+ ├─ templates/
67
+ │ └─ algorithm_project/ # 单算法项目模板
68
+ └─ tests/ # SDK 单元测试和接口契约测试
69
+ ```
70
+
71
+ `src/anycv_sdk` 会被打进 SDK 包;根目录下的 `algorithms/` 主要保存原始算法脚本、示例配置和本项目运行所需资源。模型权重建议放在 `weights/` 或服务器统一模型目录中,不建议提交到 Git,也不会自动打进 SDK 包。
72
+
73
+ ## 当前算法
74
+
75
+ | 算法 ID | 路由 | 类型 | 流式任务 |
76
+ | --- | --- | --- | --- |
77
+ | `crowd-person-track-001` | `/detect/crowd` | 人群检测/跟踪统计 | 支持 |
78
+ | `floating-plastic-detect-001` | `/detect/floating-plastic` | 水面漂浮塑料垃圾检测 | 支持 |
79
+ | `illegal-parking-obb-001` | `/detect/illegal-parking-obb` | 车辆 OBB 检测 | 支持 |
80
+
81
+ 算法清单以 `configs/algorithms.yaml` 为准。服务启动时只注册 `status: 1` 的算法。
82
+
83
+ ## 快速运行
84
+
85
+ Windows PowerShell:
86
+
87
+ ```powershell
88
+ uv python install 3.12
89
+ uv sync --extra algorithms --extra dev
90
+ uv run anycv-service --config configs\algorithms.yaml --host 0.0.0.0 --port 8000
91
+ ```
92
+
93
+ Ubuntu / Linux:
94
+
95
+ ```bash
96
+ uv python install 3.12
97
+ uv sync --extra algorithms --extra dev
98
+ uv run anycv-service --config configs/algorithms.yaml --host 0.0.0.0 --port 8000
99
+ ```
100
+
101
+ 启动后访问:
102
+
103
+ - `GET http://127.0.0.1:8000/`
104
+ - `GET http://127.0.0.1:8000/api/alg/v1/health`
105
+ - `GET http://127.0.0.1:8000/docs`
106
+
107
+ 如果使用 GPU,建议按服务器 CUDA 版本单独安装对应 PyTorch,例如:
108
+
109
+ ```bash
110
+ uv pip install --force-reinstall torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu128
111
+ ```
112
+
113
+ 模型权重需要按 `configs/algorithms.yaml` 中的 `modelPath` 放到对应目录,或把 `modelPath` 改成服务器上的绝对路径。
114
+
115
+ ## HTTP 接口约定
116
+
117
+ ### 健康检查
118
+
119
+ ```http
120
+ GET /api/alg/v1/health
121
+ ```
122
+
123
+ 返回服务状态、已注册算法、模型路径、加载状态和当前活跃推流任务。
124
+
125
+ ### 单帧推理
126
+
127
+ ```http
128
+ POST /detect/{algorithm-route}
129
+ Content-Type: multipart/form-data
130
+ ```
131
+
132
+ 必须包含:
133
+
134
+ - `file`:图片文件字段。
135
+
136
+ 可选字段:
137
+
138
+ - `conf`:置信度阈值。
139
+ - `iou`:NMS IoU 阈值。
140
+ - `imgsz`:推理输入尺寸。
141
+ - `device`:推理设备,例如 `0`、`cuda:0`、`cpu`、`auto`。
142
+ - `classes`:类别过滤,例如 `9,10` 或列表参数。
143
+
144
+ 响应必须包含:
145
+
146
+ - `result_image`:JPEG base64 字符串,不包含 `data:image/...` 前缀。
147
+ - `detections`:结构化检测结果列表,具体字段由算法决定。
148
+ - `cost_ms`:推理耗时,单位毫秒。
149
+
150
+ ### 启动流式任务
151
+
152
+ ```http
153
+ POST /detect/{algorithm-route}/stream
154
+ Content-Type: application/json
155
+ ```
156
+
157
+ 请求体:
158
+
159
+ ```json
160
+ {
161
+ "input_url": "rtmp://source/live/a",
162
+ "output_server": "rtmp://target/live/result",
163
+ "stream_key": "stream-a",
164
+ "width": 1920,
165
+ "height": 1080,
166
+ "bitrate": 2500
167
+ }
168
+ ```
169
+
170
+ `width`、`height`、`bitrate` 传 `0` 时使用算法默认配置。
171
+
172
+ ### 停止流式任务
173
+
174
+ ```http
175
+ DELETE /detect/{algorithm-route}/stream/{stream_key}
176
+ ```
177
+
178
+ SDK 会按 `algorithm_id + stream_key` 找到本地子进程并终止。
179
+
180
+ ## 新增算法编写流程规范
181
+
182
+ ### 1. 选择接入方式
183
+
184
+ 当前项目只维护两种新增算法路径:
185
+
186
+ 1. **接入 anycv 主环境**:算法需要纳入本仓库统一服务时,在 `src/anycv_sdk/algorithms/` 编写适配器,并在 `configs/algorithms.yaml` 注册算法。
187
+ 2. **使用 SDK 独立暴露接口**:算法同事独立维护算法项目时,安装 `anycv-sdk`,继承 `AlgorithmTemplate`,调用 `create_algorithm_app()` 自动生成标准接口。
188
+
189
+ 如果算法需要视频流能力,仍然通过 `stream.command` 托管本地算法脚本。
190
+
191
+ ### 2. 编写适配器
192
+
193
+ 在 `src/anycv_sdk/algorithms/` 下新增文件,例如 `my_algorithm.py`:
194
+
195
+ ```python
196
+ from __future__ import annotations
197
+
198
+ from typing import Any
199
+
200
+ from anycv_sdk.algorithms.base_yolo import YoloAdapter, resolve_device
201
+ from anycv_sdk.core.images import encode_jpeg_base64
202
+ from anycv_sdk.core.models import AlgorithmResult
203
+
204
+
205
+ class MyAlgorithmAdapter(YoloAdapter):
206
+ def infer(self, image: Any, params: dict[str, Any] | None = None) -> AlgorithmResult:
207
+ model = self.ensure_loaded()
208
+ merged = self.merge_params(params)
209
+ result = model.predict(
210
+ source=image,
211
+ conf=float(merged.get("conf", 0.25)),
212
+ imgsz=int(merged.get("imgsz", 1280)),
213
+ device=resolve_device(merged.get("device", "auto")),
214
+ verbose=False,
215
+ )[0]
216
+ return AlgorithmResult(
217
+ {
218
+ "detections": [],
219
+ "result_image": encode_jpeg_base64(result.plot()),
220
+ "algorithmId": self.config.algorithm_id,
221
+ "algorithmName": self.config.algorithm_name,
222
+ }
223
+ )
224
+ ```
225
+
226
+ 适配器要求:
227
+
228
+ - `load()` 必须幂等,重复调用不能重复占用显存;继承 `YoloAdapter` 时已内置该逻辑。
229
+ - `infer()` 接收 SDK 解码后的 OpenCV BGR 图片。
230
+ - 所有请求参数必须通过 `self.merge_params(params)` 与配置默认值合并。
231
+ - 返回结果必须包含 `result_image`。
232
+ - `detections` 建议始终返回列表,没有目标时返回 `[]`,不要返回 `None`。
233
+ - 算法异常应抛出 `AlgorithmError` 或普通异常,由服务层统一转换为 HTTP 错误。
234
+
235
+ ### 3. 注册 adapter
236
+
237
+ 在 `src/anycv_sdk/algorithms/__init__.py` 的 `create_adapter()` 中增加分支:
238
+
239
+ ```python
240
+ if config.adapter == "my_algorithm":
241
+ from anycv_sdk.algorithms.my_algorithm import MyAlgorithmAdapter
242
+
243
+ return MyAlgorithmAdapter(config)
244
+ ```
245
+
246
+ `config.adapter` 的值必须与 YAML 配置中的 `adapter` 字段一致。
247
+
248
+ ### 4. 增加配置
249
+
250
+ 在 `configs/algorithms.yaml` 的 `algorithms` 下追加:
251
+
252
+ ```yaml
253
+ - adapter: my_algorithm
254
+ algorithmId: my-algorithm-001
255
+ algorithmName: 示例算法
256
+ category: detection
257
+ route: /detect/my-algorithm
258
+ supportStream: 1
259
+ timeoutMs: 30000
260
+ status: 1
261
+ modelPath: /data/models/anycv/my_algorithm/model.pt
262
+ runtime:
263
+ mode: main
264
+ defaults:
265
+ conf: 0.25
266
+ imgsz: 1280
267
+ device: auto
268
+ stream:
269
+ cwd: ../algorithms/my_algorithm
270
+ script: detect_rtmp_push.py
271
+ log_file: logs/{stream_key}.log
272
+ command:
273
+ - "{python}"
274
+ - "-u"
275
+ - "{script}"
276
+ - "--url"
277
+ - "{input_url}"
278
+ - "--push_url"
279
+ - "{output_server}"
280
+ - "--model"
281
+ - "{model_path}"
282
+ - "--conf"
283
+ - "{conf}"
284
+ - "--imgsz"
285
+ - "{imgsz}"
286
+ - "--device"
287
+ - "{device}"
288
+ ```
289
+
290
+ 配置规范:
291
+
292
+ - `algorithmId` 一旦给平台使用,不要随意修改。
293
+ - `route` 必须唯一,并以 `/` 开头。
294
+ - `modelPath` 生产环境建议使用绝对路径。
295
+ - `status: 0` 表示保留配置但不注册接口。
296
+ - `defaults` 只放允许请求覆盖的安全参数。
297
+ - `stream.command` 每个元素是一个命令行参数,不要写成一整条 shell 字符串。
298
+ - `stream.command` 支持 `{input_url}`、`{output_server}`、`{stream_key}`、`{model_path}`、`{python}`、`{script}` 和 `defaults` 中的字段。
299
+
300
+ ### 5. 增加测试
301
+
302
+ 至少覆盖:
303
+
304
+ - 配置能正常加载,路由出现在 `load_app_config()` 结果中。
305
+ - 单帧推理返回包含 `result_image` 的结构。
306
+ - 流式算法能正确渲染 `stream.command`。
307
+ - 如果新增了结果转换逻辑,需要用假对象测试字段结构,避免强依赖真实模型。
308
+
309
+ 运行:
310
+
311
+ ```bash
312
+ uv run pytest
313
+ ```
314
+
315
+ ### 6. 更新文档和版本
316
+
317
+ 新增算法进入主服务后,应同步更新:
318
+
319
+ - `configs/algorithms.yaml` 中的注释。
320
+ - 本 README 的当前算法表格。
321
+ - 部署手册中的模型文件放置说明。
322
+ - `pyproject.toml` 的 `version`,如果需要对外重新发 SDK 包。
323
+
324
+ ## SDK 打包和分发
325
+
326
+ 当前项目使用 `pyproject.toml` 管理依赖、使用 uv 管理 `.venv` 环境,同时保留 `setuptools` 和 `src` 布局用于打包。包名为 `anycv-sdk`,命令行入口为 `anycv-service`。
327
+
328
+ 打包前建议先跑测试:
329
+
330
+ ```bash
331
+ uv sync --extra algorithms --extra dev
332
+ uv run pytest
333
+ ```
334
+
335
+ 构建 wheel 和源码包:
336
+
337
+ ```bash
338
+ uv pip install build
339
+ uv run python -m build
340
+ ```
341
+
342
+ 构建完成后会生成:
343
+
344
+ ```text
345
+ dist/
346
+ ├─ anycv_sdk-0.1.0-py3-none-any.whl
347
+ └─ anycv_sdk-0.1.0.tar.gz
348
+ ```
349
+
350
+ 算法同事的单算法项目安装本地 wheel:
351
+
352
+ ```bash
353
+ uv pip install "dist/anycv_sdk-0.1.0-py3-none-any.whl"
354
+ ```
355
+
356
+ 如果算法项目需要运行 YOLO/OpenCV,还需要安装算法扩展依赖:
357
+
358
+ ```bash
359
+ uv pip install numpy opencv-python ultralytics
360
+ ```
361
+
362
+ 注意:
363
+
364
+ - wheel 默认只包含 `src/anycv_sdk` 包代码。
365
+ - 模型权重不会被打包,需要由部署流程单独下发。
366
+ - 根目录 `algorithms/` 下的原始脚本不会自动进入 SDK 包;算法同事应在自己的算法项目中维护算法脚本和模型权重。
367
+ - 对算法同事分发 SDK 时,应固定版本号,并在算法项目中锁定依赖版本。
368
+
369
+ ## 常用命令
370
+
371
+ ```bash
372
+ # 本地开发安装
373
+ uv sync --extra algorithms --extra dev
374
+
375
+ # 启动统一多算法服务
376
+ uv run anycv-service --config configs/algorithms.yaml --host 0.0.0.0 --port 8000
377
+
378
+ # 强制启动时加载全部启用模型
379
+ uv run anycv-service --config configs/algorithms.yaml --load-on-startup
380
+
381
+ # 禁止启动时预加载模型,改为首次请求懒加载
382
+ uv run anycv-service --config configs/algorithms.yaml --no-load-on-startup
383
+
384
+ # 运行测试
385
+ uv run pytest
386
+
387
+ # 构建 SDK 包
388
+ uv run python -m build
389
+ ```
390
+
391
+ ## 相关文档
392
+
393
+ - [部署手册](docs/部署手册.md)
394
+ - [SDK 使用手册](docs/sdk使用手册.md)