AnwarDebes/drone-id

GitHub: AnwarDebes/drone-id

一个带来源标注的无人机型号目录与识别 API,支持通过自由文本语义搜索和结构化特征匹配来判定无人机型号。

Stars: 0 | Forks: 0

Drone-ID: a source-cited drone model catalog and identification API # 无人机识别系统 [![Release](https://img.shields.io/github/v/release/AnwarDebes/drone-id?color=0ea5e9)](https://github.com/AnwarDebes/drone-id/releases) [![Python](https://img.shields.io/badge/python-3.11%2B-3776AB?logo=python&logoColor=white)](pyproject.toml) [![License: MIT](https://img.shields.io/badge/license-MIT-22c55e.svg)](LICENSE) ![Tests](https://img.shields.io/badge/tests-46%20passing-2dd4bf.svg) ![Catalog](https://img.shields.io/badge/catalog-56%20cited%20models-fbbf24.svg)
一个经过精选且标明来源的无人机**型号**参考目录,外加一个 API,它可以通过自由文本描述或结构化的特征集,将观察结果与已知型号进行匹配。 ## 首先阅读:这是什么,以及它不是什么 该系统回答了一个问题:**“这是哪种型号的无人机?”** 它的设计确保了两个概念无法被忽视,且永远不会被混淆。 ### 1. 是型号识别,而非操作者归属 该目录告诉你无人机*是什么*:它的型号、制造商,以及**生产**它的公司所在国家(`manufacturer_country`)。它绝不会告诉你无人机是*谁的*。 `manufacturer_country` 是型号的一个属性。它**不是**驾驶特定机架的人的国籍,并且在 schema 或 API 中刻意没有保留任何操作者、所有者或国籍字段。中国制造的 DJI、土耳其制造的 TB2 和美国制造的 MQ-9,都由许多不同国家的众多操作者驾驶。试图从型号推断操作者,正是这种设计拒绝犯下的错误。**操作者和归属国籍判定不在范围内**(请参阅下文的“不在范围内”)。 所以:这不是一个能证明是谁的无人机越过了边境的系统。它可以说“那看起来像一架 DJI Matrice 350 RTK”。它无法说出是谁在拿着遥控器。 ### 2. 是一个目录,而不是传感器 这是一个数据库和匹配 API。它不是传感系统。它存储了某个型号*是否*支持 Remote ID,以及该型号的 RF、声音和视觉特征*是什么*样子的,以便单独的传感层可以根据它匹配观察结果。它不接收 Remote ID 广播、捕获 RF、运行雷达或对相机图像进行分类。这些需要硬件和带有标签的数据集,属于第二阶段的工作。 检测输入(Remote ID 负载字段、RF 频段列表、图像属性)旨在与目录条目进行匹配,但该项目从不模拟或伪造传感能力。特征匹配 endpoint 仅对**其他系统已经提取出的结构化特征**进行评分,而不是对原始信号。 ## 包含的内容 - 带有 Alembic 迁移的 PostgreSQL 目录(`drone_models`)。 - FastAPI 应用:CRUD、丰富的过滤、语义搜索和结构化特征匹配。 - 基于模型描述和规格文本的 ChromaDB 语义搜索,默认使用多语言 embedding 模型。 - 包含三个路径的导入 pipeline(单一来源导入器、手动 YAML 整理,以及拒绝没有引用的条目的验证步骤)。 - 56 个完全注明来源的条目,涵盖九个制造商国家和从消费级到军用的范围,首先覆盖了 DJI 系列(占主导地位的市场):Mini、Air、Mavic、FPV 和企业级 Matrice / Agras 家族,以及 Autel、Skydio、Parrot、Yuneec、固定翼测绘平台(senseFly、WingtraOne、Quantum Systems),以及著名的 ISR / 打击平台(TB2、MQ-9、Global Hawk、ScanEagle、Heron、Wing Loong II 等)。运行 `python -m ingestion.audit` 查看实时细分。 - `SOURCES.md` 记录了每个数据源及其可靠性。 ## 快速开始(无需 Docker) 该应用默认使用 SQLite 和离线 embedding 后端,因此无需任何外部服务即可运行。生产环境使用 PostgreSQL 和多语言模型(见下文)。 ``` python -m venv .venv && source .venv/bin/activate pip install -r requirements.txt # core + dev # 可选,用于真正的 semantic search: # pip install -r requirements-semantic.txt cp .env.example .env # 首次运行的离线友好设置: export EMBEDDING_BACKEND=hash CHROMA_MODE=persistent CHROMA_PATH=./chroma_data alembic upgrade head # build the schema python -m ingestion.seed --reset # validate + load the cited catalog + index uvicorn app.main:app --reload # serve at http://127.0.0.1:8000 ``` 然后打开 http://127.0.0.1:8000/docs 访问交互式 API,或者: ``` curl localhost:8000/health curl "localhost:8000/drones?manufacturer_country=CN" curl -X POST localhost:8000/search/describe \ -H 'content-type: application/json' \ -d '{"text":"small white foldable camera quadcopter ~250g on 2.4GHz","limit":3}' ``` ## 基于 PostgreSQL + ChromaDB 运行(生产形态) ``` docker compose up -d # starts postgres + chroma cp .env.example .env # then set the two URLs below ``` 在 `.env` 中: ``` DATABASE_URL=postgresql+asyncpg://drone:drone@localhost:5432/drone_id CHROMA_MODE=http CHROMA_HOST=localhost CHROMA_PORT=8000 EMBEDDING_BACKEND=sentence_transformers EMBEDDING_MODEL=paraphrase-multilingual-MiniLM-L12-v2 ``` ``` alembic upgrade head python -m ingestion.seed --reset uvicorn app.main:app --host 0.0.0.0 --port 8080 ``` embedding 模型特意选用了多语言模型,因此其他语言的描述和查询也能被合理地嵌入。如果未安装语义技术栈或无法访问 Chroma,API 的其余部分将继续工作,而 `/search/describe` 会返回 503 并给出明确原因(请检查 `/health`)。 ## API | 方法 | 路径 | 认证 | 目的 | |---|---|---|---| | GET | `/` | - | 服务标语和范围声明 | | GET | `/health` | - | 数据库 + 语义搜索状态 | | GET | `/drones` | - | 列表 / 过滤目录 | | GET | `/drones/{id_or_slug}` | - | 单个型号 | | POST | `/drones` | admin | 创建一个型号 | | PUT | `/drones/{id_or_slug}` | admin | 更新一个型号 | | DELETE | `/drones/{id_or_slug}` | admin | 删除一个型号 | | POST | `/search/describe` | - | 基于自由文本的语义搜索 | | POST | `/match/signature` | - | 结构化特征匹配 | `GET /drones` 上的过滤器:`manufacturer`、`manufacturer_country`、`category`、`airframe`、`freq_band`、`remote_id_supported`、`weight_min/max`、`mtow_min/max`、`q`(名称 + 别名),以及 `limit` / `offset`。 写入 endpoint 受 `X-Admin-Key` 请求头(`ADMIN_API_KEY`)中的共享密钥控制。这只是一个简单的门控,而不是完整的认证系统;在任何部署之前,请放置一个真正的身份认证层。 ### `POST /match/signature` 接受结构化观察结果,并返回带有透明按组件细分的候选型号排名: ``` { "freq_bands": ["2.4GHz", "5.8GHz"], "remote_id_fields": {"present": true, "standard": "ASTM F3411"}, "visual_attributes": ["foldable", "quadcopter"], "weight_estimate": {"value": 245, "tolerance": 60}, "size_estimate": {"value": 150, "tolerance": 80} } ``` 评分仅基于您实际提供的组件的加权平均值(freq 0.30,weight 0.20,size 0.20,remote_id 0.15,visual 0.15),因此稀疏的观察结果不会因为它无法测量的数据而受到惩罚。请参阅“不在范围内”中的重要限制:这仅匹配结构化特征,而非原始信号。 每个候选对象都带有型号的 `data_confidence`,因此您可以看到其规格有多可信,并且当前两个候选对象过于接近而无法自信地分开时,响应会将 `ambiguous` 设置为 `true`。这对于关键的系统非常重要:API 会展现不确定性,而不是断言一个单一的答案。 ## 数据模型 只有一个表,`drone_models`。亮点: - 身份:`model_name`、`aliases`、`manufacturer`、`manufacturer_country`(ISO 3166-1 alpha-2)、`category`、`airframe`、`slug`。 - 物理:`length_mm`、`width_mm`、`height_mm`、`diagonal_mm`、`weight_g`、`mtow_g`。 - 性能:`max_speed_kmh`、`range_km`、`endurance_min`、`max_altitude_m`、`max_payload_g`。 - 通讯:`control_freq_bands`、`video_freq_bands`、`control_protocol`、`gnss_support`。 - 检测特征:`remote_id_supported`、`remote_id_standard`、`radar_cross_section_class`、`acoustic_notes`、`visual_identifiers`。 - 来源:`sources`(`{field, url_or_citation, retrieved_at}` 的 JSON 数组)和 `data_confidence`(`verified` / `partial` / `unverified`)。 每个填充的规格字段都带有引用。未知字段留空(null),而不是进行估算。该目录是为 PostgreSQL(原生数组和 JSONB)设计并迁移的;相同的模型和迁移也可以在 SQLite 上运行,用于本地开发和测试。 ## 导入 三个路径,全部汇聚于同一个经过验证的 `DroneCreate` 形态: 1. **单一来源导入器**(`ingestion/sources/`):制造商页面、FAA UAS、EASA。制造商/FAA/EASA 导入器目前是记录在案的脚手架(它们会抛出带有实现计划的 `NotImplementedError`,而不是返回虚构数据);手动 YAML 导入器已完全正常工作。 2. **手动整理**(`data/catalog/**.yaml`,每个型号一个文件):目前的主要路径。请参阅 `data/SCHEMA.md`。 3. **验证**(`app/validation.py`):拒绝任何在没有涵盖来源引用的情况下填充规格字段的条目。 ``` python -m ingestion.seed --validate-only # parse + validate, touch nothing python -m ingestion.seed --reset # rebuild catalog + index python -m ingestion.seed --no-embed # DB only, skip ChromaDB python -m ingestion.audit # coverage / confidence / citation snapshot ``` 目录的大部分内容是通过对经过验证的网络研究构建的,这些研究以带引用的 JSON 格式记录在 `ingestion/research/` 中(作为审计跟踪保留),然后通过 `python -m ingestion.convert_research` 转换为经过验证的 YAML。该转换器是一个门控:它会剥离任何无法与引用相关联的字段,而不是猜测,因此只有带引用的数据才会被保留。选择以这种方式扩展目录,而不是通过爬虫,是刻意为之的:对于关键系统来说,经过验证和引用的数据胜过快速但脆弱的数据。 ## 数据覆盖范围 来自 `python -m ingestion.audit` 的快照(56 个条目): - 按类别:商用 16 个,消费级 15 个,军用打击 12 个,军用 ISR 7 个,VTOL 3 个,竞速 2 个,固定翼 1 个。 - 按制造商国家(生产国,绝非操作者):CN 30 个,US 13 个,TR 3 个,FR 2 个,CH 2 个,IL 2 个,RU 2 个,DE 1 个,IR 1 个。 - 置信度:89% 已验证(50/56),11% 部分(6/56)。在对主要来源进行第二轮重新验证后,仅存的“部分”条目是没有制造商或政府规格表的那些:CH-4、Wing Loong II、Lancet-3、Orlan-10、Shahed-136(开源情报估算)以及 Freefly Alta X(未发布官方高度/范围)。这些都是如实标记的,从不夸大。对于一个可能用于国防用途的系统来说,承认不确定性比虚假的自信更安全。 - 引用健康状况:每个填充的规格字段都有引用(种子程序强制执行此操作)。 国家的分布正是关键所在:它表明制造商国家只是型号的一个属性,仅此而已。同一机架由许多国家操作,这正是为什么操作者归属不在范围内的原因。 ## 不在范围内(第二阶段:需要硬件和/或单独的机器学习工作) 这些是刻意不在这里构建的,设计上也不假装它们存在: - **实时 RF、雷达和声音传感。** 需要硬件。目录存储用于匹配的特征描述符;它不捕获信号。 - **相机 + ML 检测/分类。** 一个单独的机器学习项目,需要带有标签的无人机图像数据集。目录仅存储 `visual_identifiers` 文本。 - **Remote ID 广播接收器/解码器。** 需要硬件和 RF。目录存储某个型号*是否*支持 Remote ID;实时解码是独立的工作。 - **针对真实捕获信号的 RF / 声音特征匹配。** `/match/signature` endpoint 仅基于结构化特征进行匹配。匹配真实捕获的信号需要带标签的信号数据集(RF 指纹、声音轮廓),而该项目中不存在这些数据集。 - **对检测到的无人机进行操作者/归属国籍判定。** 因“首先阅读”中所述的原因,在设计上不在范围内。 ## 测试 ``` pytest -q ``` 所有 46 个测试均可离线通过(SQLite 加上哈希 embedder,无需任何服务)。该测试套件涵盖了评分逻辑、引用验证、schema 规则,以及针对种子目录对 API 的全面端到端通过(过滤器、语义搜索、特征匹配、管理员门控以及创建/更新/删除)。 ## 项目布局 ``` app/ FastAPI app: models, schemas, crud, scoring, search, routers ingestion/ loader, seed CLI, validation use, per-source importers data/catalog/ curated YAML, one file per model (the seed data) migrations/ Alembic tests/ unit + end-to-end SOURCES.md data sources and reliability data/SCHEMA.md YAML entry format ```
标签:Python, 型号识别, 数据目录, 无人机, 无后门, 测试用例, 请求拦截, 逆向工具