# defog **Repository Path**: zjp_giteeHome/defog ## Basic Information - **Project Name**: defog - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-04-24 - **Last Updated**: 2025-07-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # RTMP视频流实时图像识别系统 本系统基于现有的图像识别算法,提供了一个从RTMP视频流中实时识别和处理图像的解决方案,适用于监控、检测和分析场景。 ## 功能特点 - 支持从RTMP流实时获取视频帧并进行处理 - 集成多种识别算法: - 图像去雾增强 - 绝缘子检测 - 绝缘子缺陷检测 - 植被入侵检测 - 异物检测 - 鸟巢检测 - 线夹检测 - 变压器检测 - 线路损坏检测 - 提供Web界面实时查看处理结果 - 支持多流并发处理 - 支持WebSocket实时推送结果 - 可保存检测结果和处理后的图像 ## 系统要求 - Python 3.7+ - OpenCV 4.5+ - Flask 2.0+ - Flask-SocketIO 5.0+ - 其他依赖见 requirements.txt ## 安装方法 1. 克隆仓库 ```bash git clone cd deflog ``` 2. 创建并激活虚拟环境 ```bash # 使用venv python -m venv venv # Windows激活 venv\Scripts\activate # Linux/Mac激活 source venv/bin/activate ``` 3. 安装依赖 ```bash pip install -r requirements.txt ``` 4. 创建必要的目录 ```bash mkdir -p static/original_images static/processed_images rtmp_output ``` ## 使用方法 ### 1. 启动RTMP流处理服务器 ```bash python rtmp_processor.py [--rtmp RTMP_URL] [--model MODEL_TYPE] [--interval INTERVAL] [--host HOST] [--port PORT] ``` 参数说明: - `--rtmp`: RTMP流URL,如果提供则立即开始处理该流 - `--model`: 指定使用的检测模型类型,可选值:defog, insulator, fault_insulator, vegetation, foreign_object, bird_nest, line_clamp, transformer, line_damage, all - `--interval`: 处理帧间隔(秒),默认为1.0 - `--host`: 服务器主机地址,默认为0.0.0.0 - `--port`: 服务器端口,默认为5001 ### 2. 使用Web界面 服务器启动后,在浏览器中访问: ``` http://localhost:5001 ``` 通过Web界面可以: - 添加新的RTMP流进行处理 - 选择要应用的检测模型 - 查看实时处理结果 - 管理活动流 - 调整系统设置 ### 3. 编程接口 (API) 系统提供了RESTful API接口,可以通过HTTP请求进行操作: #### 添加新流 ``` POST /start_stream Content-Type: application/json { "rtmp_url": "rtmp://example.com/live/stream", "detection_models": { "insulator": "powerline-fault-detection-upvfb/1", "defog": "defog/1" }, "frame_interval": 1.0 } ``` #### 停止流处理 ``` POST /stop_stream Content-Type: application/json { "rtmp_url": "rtmp://example.com/live/stream" } ``` #### 获取活动流列表 ``` GET /list_streams ``` #### 获取流的最新处理结果 ``` GET /stream/{rtmp_url}/latest_result ``` ## RTMP流源设置 如果没有现成的RTMP流,可以通过以下方法创建测试流: ### 使用FFmpeg将本地视频转换为RTMP流 ```bash ffmpeg -re -i video.mp4 -c copy -f flv rtmp://localhost/live/stream ``` ### 使用OBS直播软件 1. 下载并安装[OBS Studio](https://obsproject.com/) 2. 设置 -> 流 3. 选择"自定义..."服务 4. 服务器填写"rtmp://localhost/live/stream"或您的RTMP服务器地址 5. 点击"开始直播" ### 使用摄像头作为RTMP源 ```bash ffmpeg -f dshow -i video="Your Camera Name" -c:v libx264 -preset ultrafast -tune zerolatency -f flv rtmp://localhost/live/stream ``` ## RTMP服务器搭建 如果需要在本地搭建RTMP服务器,推荐以下方案: ### 使用Nginx+rtmp模块 1. 安装Nginx和rtmp模块 ```bash # Ubuntu/Debian sudo apt update sudo apt install nginx libnginx-mod-rtmp # CentOS/RHEL sudo yum install nginx nginx-mod-rtmp ``` 2. 配置Nginx 编辑Nginx配置文件(通常在/etc/nginx/nginx.conf),添加以下内容: ```nginx rtmp { server { listen 1935; application live { live on; record off; } } } ``` 3. 重启Nginx ```bash sudo systemctl restart nginx ``` 之后就可以使用`rtmp://localhost/live/stream`作为推流地址了。 ## 常见问题 1. **无法连接到RTMP流** 确认RTMP流URL是否正确,并检查网络连接。可以使用ffplay测试RTMP流是否可访问: ```bash ffplay rtmp://your-rtmp-url ``` 2. **处理速度慢** 调整处理帧间隔可以减轻CPU负担,增大interval参数值: ```bash python rtmp_processor.py --interval 2.0 ``` 3. **没有检测结果** 确保所选的检测模型适合您的视频内容。不同模型针对不同场景优化。 4. **Web界面无法加载** 检查浏览器控制台是否有错误,并确认服务器日志中是否有异常。 ## 高级文件上传与下载功能 系统支持高级文件上传和下载功能,包括批量上传、可恢复上传和分块上传大文件。 详细的API文档请参见 [文件系统API文档](file_system_api.md)。 ## 批量图像识别功能 系统支持批量图像识别功能,可以对指定的一组图片使用选定的模型进行批量识别处理,并将结果保存到相应的目录中。 处理后的图片会包含红色边框标注、中文标签和置信度信息。 详细的API文档请参见 [批量图像识别API文档](model_recognition.md)。 ## 联系与支持 如有问题或建议,请提交Issue或通过以下方式联系: - 邮箱:[example@example.com] - 网站:[http://example.com] ## 许可证 本项目采用 MIT 许可证 ## 图片上传API ### 接口说明 该接口用于上传图片,并按照指定的文件夹结构进行存储。 ### 请求URL ``` POST /upload_image ``` ### 请求参数 | 参数名 | 必选 | 类型 | 说明 | |------------|-------|--------|----------------------------------| | image | 是 | file | 要上传的图片文件 | | line_name | 是 | string | 线路名称 | | tower_name | 是 | string | 杆塔名称 | | date | 否 | string | 日期,格式为YYYY-MM-DD,默认当天 | ### 支持的图片格式 - jpg/JPG - png/PNG - webp/WEBP ### 响应参数 | 参数名 | 类型 | 说明 | |-------------|---------|----------------------| | success | boolean | 请求是否成功 | | message | string | 响应消息 | | image_url | string | 图片URL地址 | | filename | string | 文件名 | | path | string | 文件相对路径 | | line_name | string | 线路名称 | | tower_name | string | 杆塔名称 | | date | string | 日期 | | error | string | 错误信息(失败时返回) | ### 响应示例 成功响应: ```json { "success": true, "message": "图像上传成功", "image_url": "/uploads/线路1/杆塔1/2023-04-09/原图/2023-04-09-001.jpg", "filename": "2023-04-09-001.jpg", "path": "uploads/线路1/杆塔1/2023-04-09/原图/2023-04-09-001.jpg", "line_name": "线路1", "tower_name": "杆塔1", "date": "2023-04-09" } ``` 失败响应: ```json { "success": false, "error": "缺少必要参数: 线路名称" } ``` ### 文件存储结构 上传的图片将按照以下结构进行存储: ``` uploads/ ├── 线路1/ │ ├── 杆塔1/ │ │ ├── 2023-04-09/ │ │ │ ├── 原图/ │ │ │ │ ├── 2023-04-09-001.jpg │ │ │ │ ├── 2023-04-09-002.jpg │ │ │ │ └── ... │ │ │ └── ... │ │ └── ... │ ├── 杆塔2/ │ │ └── ... │ └── ... ├── 线路2/ │ └── ... └── ... ``` 注意:如果提交的线路名和杆塔名不包含"线路"和"杆塔"前缀,系统会自动添加。例如,提交"1"作为线路名将变为"线路1"。 ### 测试示例 使用curl命令测试: ```bash curl -X POST http://localhost:5000/upload_image \ -F "image=@/path/to/image.jpg" \ -F "line_name=1" \ -F "tower_name=11" \ -F "date=2023-04-09" ``` 使用Python请求示例: ```python import requests url = "http://localhost:5000/upload_image" files = {'image': open('image.jpg', 'rb')} data = { 'line_name': '1', # 系统会自动转换为"线路1" 'tower_name': '11', # 系统会自动转换为"杆塔11" 'date': '2023-04-09' # 可选参数 } response = requests.post(url, files=files, data=data) print(response.json()) ``` # File System API Documentation This document describes the available API endpoints for managing the file system in the application. ## Base URL All API endpoints are relative to your server's base URL (e.g., `http://localhost:5001`). ## API Endpoints ### 1. Get File System Tree Retrieves the hierarchical structure of the file system. For image files, the path in the response can be directly used to access the image by appending it to the base URL. ```http GET /tree ``` **Query Parameters:** - `max_level` (optional): Maximum depth of the tree structure (-1 for unlimited) - `path` (optional): Starting path for the tree (defaults to root) **Response:** ```json { "success": true, "tree": { "name": "root", "path": "", "type": "directory", "level": 0, "children": [ { "name": "线路1", "path": "线路1", "type": "directory", "level": 1, "children": [ { "name": "杆塔1", "path": "线路1/杆塔1", "type": "directory", "level": 2, "children": [ { "name": "2024-01-01", "path": "线路1/杆塔1/2024-01-01", "type": "directory", "level": 3, "children": [ { "name": "原图", "path": "线路1/杆塔1/2024-01-01/原图", "type": "directory", "level": 4, "children": [ { "name": "2024-01-01-001.jpg", "path": "线路1/杆塔1/2024-01-01/原图/2024-01-01-001.jpg", "type": "file", "level": 5 } ] } ] } ] } ] } ] } } ``` **Image Access:** For any file node in the tree with `type: "file"`, you can access the image directly using: ``` http://your-server/uploads/{path} ``` For example, if a file node has: ```json { "name": "2024-01-01-001.jpg", "path": "线路1/杆塔1/2024-01-01/原图/2024-01-01-001.jpg", "type": "file" } ``` The image can be accessed at: ``` http://your-server/uploads/线路1/杆塔1/2024-01-01/原图/2024-01-01-001.jpg ``` ### 2. Get Line Towers Retrieves all towers for a specific power line. ```http GET /line/{line_name}/towers ``` **Parameters:** - `line_name`: Name of the power line **Response:** ```json { "success": true, "towers": ["tower1", "tower2", "tower3"] } ``` ### 3. Get Tower Dates Retrieves all available dates for a specific tower. ```http GET /line/{line_name}/tower/{tower_name}/dates ``` **Parameters:** - `line_name`: Name of the power line - `tower_name`: Name of the tower **Response:** ```json { "success": true, "dates": ["2024-01-01", "2024-01-02"] } ``` ### 4. Get Date Images Retrieves all images for a specific date. ```http GET /line/{line_name}/tower/{tower_name}/date/{date}/images ``` **Parameters:** - `line_name`: Name of the power line - `tower_name`: Name of the tower - `date`: Date in YYYY-MM-DD format **Response:** ```json { "success": true, "images": [ { "name": "image1.jpg", "path": "线路1/杆塔1/2024-01-01/原图/image1.jpg", "url": "/uploads/线路1/杆塔1/2024-01-01/原图/image1.jpg" } ] } ``` ### 5. Rename File Renames a file or directory using the complete path. ```http POST /file/rename ``` **Request Body:** ```json { "path": "线路1/杆塔1/2024-01-01/原图/old_image.jpg", "new_name": "new_image.jpg" } ``` **Response:** ```json { "success": true, "message": "重命名成功", "new_path": "线路1/杆塔1/2024-01-01/原图/new_image.jpg" } ``` ### 6. Delete Files Deletes one or more files or directories using the complete path. ```http POST /file/delete ``` **Single File Delete Request Body:** ```json { "path": "线路1/杆塔1/2024-01-01/原图/image.jpg" } ``` **Batch Delete Request Body:** ```json { "paths": [ "线路1/杆塔1/2024-01-01/原图/image1.jpg", "线路1/杆塔1/2024-01-01/原图/image2.jpg", "线路1/杆塔1/2024-01-02" ] } ``` **Single Delete Response:** ```json { "success": true, "message": "删除成功" } ``` **Batch Delete Response:** ```json { "success": true, "message": "成功删除 3 个项目", "deleted": [ "线路1/杆塔1/2024-01-01/原图/image1.jpg", "线路1/杆塔1/2024-01-01/原图/image2.jpg", "线路1/杆塔1/2024-01-02" ], "failed": [] } ``` **Partial Success Response:** ```json { "success": true, "message": "部分删除成功: 2 成功, 1 失败", "deleted": [ "线路1/杆塔1/2024-01-01/原图/image1.jpg", "线路1/杆塔1/2024-01-01/原图/image2.jpg" ], "failed": [ { "path": "线路1/杆塔1/2024-01-02", "error": "权限被拒绝" } ] } ``` ### 7. Get File Info Retrieves information about a file or directory. ```http GET /file/info?path={file_path} ``` **Query Parameters:** - `path`: Path to the file or directory **Response:** ```json { "success": true, "name": "image.jpg", "path": "线路1/杆塔1/2024-01-01/原图/image.jpg", "size": 1024, "created_time": "2024-01-01 12:00:00", "modified_time": "2024-01-01 12:00:00", "type": "file" } ``` ### 8. Download Files Downloads one or more files. If the path points to a folder or multiple files/folders, the content will be compressed into a zip file before downloading. ```http POST /download ``` **Request Body:** ```json { "paths": [ "线路1/杆塔1/2024-01-01/原图/image1.jpg", "线路1/杆塔1/2024-01-01/原图/image2.jpg" ] } ``` Or for a single file/folder: ```json { "paths": "线路1/杆塔1/2024-01-01/原图" } ``` **Response:** - For a single file: Direct file download with appropriate content type - For multiple files or directories: ZIP file download containing all requested items ### 9. Upload Image Uploads an image to a specific location in the file system. ```http POST /upload_image ``` **Form Data:** - `image`: Image file (supported formats: jpg, jpeg, png, webp) - `line_name`: Name of the power line - `tower_name`: Name of the tower - `date` (optional): Date in YYYY-MM-DD format (defaults to current date) **Response:** ```json { "success": true, "message": "图像上传成功", "image_url": "/uploads/线路1/杆塔1/2024-01-01/原图/image.jpg", "filename": "2024-01-01-001.jpg", "path": "线路1/杆塔1/2024-01-01/原图/2024-01-01-001.jpg", "line_name": "线路1", "tower_name": "杆塔1", "date": "2024-01-01" } ``` ## Error Handling All endpoints return appropriate HTTP status codes and error messages in case of failure: ```json { "success": false, "error": "错误描述" } ``` Common status codes: - 200: Success - 400: Bad Request (missing or invalid parameters) - 404: Not Found - 500: Internal Server Error ## File System Structure The file system follows this structure: ``` uploads/ ├── 线路{line_name}/ │ └── 杆塔{tower_name}/ │ └── {date}/ │ └── 原图/ │ └── {date}-{sequence}.jpg ``` ## Usage Examples ### JavaScript Fetch Example ```javascript // Get file system tree async function getFileTree() { const response = await fetch('/tree'); const data = await response.json(); if (data.success) { console.log('File tree:', data.tree); } } // Upload an image async function uploadImage(file, lineName, towerName) { const formData = new FormData(); formData.append('image', file); formData.append('line_name', lineName); formData.append('tower_name', towerName); const response = await fetch('/upload_image', { method: 'POST', body: formData }); const data = await response.json(); if (data.success) { console.log('Upload successful:', data.image_url); } } // Delete a file async function deleteFile(path) { const response = await fetch('/file/delete', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ path }) }); const data = await response.json(); if (data.success) { console.log('File deleted successfully'); } } // Delete multiple files async function deleteFiles(paths) { const response = await fetch('/file/delete', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ paths }) }); const data = await response.json(); if (data.success) { console.log(`Deleted ${data.deleted.length} files`); if (data.failed.length > 0) { console.log(`Failed to delete ${data.failed.length} files`); } } } // Download multiple files async function downloadFiles(paths) { // Create a form to submit (will trigger download) const form = document.createElement('form'); form.method = 'POST'; form.action = '/download'; // Add the paths as hidden input const input = document.createElement('input'); input.type = 'hidden'; input.name = 'paths'; input.value = JSON.stringify(paths); form.appendChild(input); document.body.appendChild(form); form.submit(); document.body.removeChild(form); } ``` ## Notes 1. All paths in requests should be relative to the base upload directory. 2. File operations are validated to ensure they only access files within the allowed directory structure. 3. The API supports CORS for cross-origin requests. 4. All responses include a `success` boolean indicating the operation result. 5. Error messages are provided in Chinese for better integration with the existing system. 6. File paths can use either forward slashes (/) or backslashes (\\) as separators. ## Batch Image Recognition API The system provides a batch image recognition API that allows processing multiple images with multiple detection models simultaneously. This API uses WebSockets to provide real-time progress updates during processing. ### API Endpoint ``` POST /batch_recognize ``` **Request body (JSON):** ```json { "image_paths": [ "line1/tower1/2023-04-09/original/2023-04-09-001.png", "line1/tower1/2023-04-09/original/2023-04-09-002.png" ], "model_names": [ "bird_nest", "vegetation", "foreign_object" ] } ``` **Parameters:** - `image_paths`: Array of image paths to process (relative to uploads directory) - `model_names`: Array of model names to apply to each image **Supported models:** - `vegetation`: Vegetation intrusion detection - `foreign_object`: Foreign object detection - `bird_nest`: Bird nest detection - `line_clamp`: Line clamp detection - `transformer`: Transformer detection - `line_damage`: Line damage detection - `fault_insulator`: Insulator fault detection - `insulator`: Insulator detection **Response:** ```json { "success": true, "task_id": "550e8400-e29b-41d4-a716-446655440000", "message": "Started processing 2 images with 3 models", "total_images": 2, "total_models": 3, "model_names": ["bird_nest", "vegetation", "foreign_object"], "model_configs": { "bird_nest": "Bird Nest Detection", "vegetation": "Vegetation Intrusion Detection", "foreign_object": "Foreign Object Detection" } } ``` ### WebSocket Integration The batch recognition API uses WebSocket to provide real-time progress updates. Connect to the WebSocket server and listen for the following events: 1. Connect to the WebSocket server: ```javascript // Initialize WebSocket connection const socket = io('http://localhost:5000', { transports: ['websocket'] // Force WebSocket transport }); // Connection events socket.on('connect', () => { console.log('Connected to WebSocket server'); }); socket.on('connect_error', (error) => { console.error('WebSocket connection error:', error); }); socket.on('disconnect', (reason) => { console.log('WebSocket disconnected:', reason); }); ``` 2. Listen for progress updates: ```javascript // Listen for progress updates socket.on('batch_recognition_progress', (data) => { if (data.task_id === taskId) { console.log(`Progress: ${data.progress.toFixed(2)}%, Processing: ${data.image_path} with ${data.model_name}`); // Update UI with progress information updateProgressBar(data.progress); // Display detection messages if (data.detection_messages && data.detection_messages.length > 0) { data.detection_messages.forEach(msg => console.log(msg)); } } }); ``` 3. Listen for completion: ```javascript // Listen for task completion socket.on('batch_recognition_complete', (data) => { if (data.task_id === taskId) { console.log(`Batch processing complete. Success: ${data.successful}, Failed: ${data.failed}`); // Display results displayResults(data.results); // Display model statistics displayModelStats(data.model_stats); // Clean up event listeners socket.off('batch_recognition_progress'); socket.off('batch_recognition_complete'); } }); ``` ### Processing Flow 1. Client sends a POST request to the server with image paths and model names 2. Server validates parameters and creates a unique task ID 3. Server returns the task ID and initial information, and starts an asynchronous processing task 4. Server pushes progress updates via WebSocket as each image is processed with each model 5. When all images and models are processed, server pushes the complete results 6. Client updates UI based on the results, displaying processed images and detection information ### Result Handling Processed images are saved following this structure: - Original path: `uploads/line1/tower1/2023-04-09/original/2023-04-09-001.png` - Result path: `uploads/line1/tower1/2023-04-09/bird_nest_detection/2023-04-09-001.png` The processed images include: - Red bounding boxes around detected objects - Chinese object names and confidence percentages above each detection - Detection model and total object count in the top-right corner **Note:** The image path must follow the format: `line/tower/date/original/filename` for the system to determine the output location properly. For detailed documentation, see the [Batch Image Recognition API Documentation](model_recognition.md). ## WebSocket Real-time Communication The system uses WebSockets for real-time communication between the server and clients. There are two main WebSocket features: ### 1. RTMP Stream Results When processing RTMP streams, you can receive real-time processing results via WebSocket: ```javascript // Connect to WebSocket server const socket = io('http://localhost:5000', { transports: ['websocket'] }); // Subscribe to a specific RTMP stream socket.emit('subscribe', { rtmp_url: 'rtmp://example.com/live/stream' }); // Receive real-time processing results socket.on('result_update', (data) => { // data contains: // - rtmp_url: The RTMP URL // - timestamp: UNIX timestamp // - datetime: Formatted datetime string // - image: Base64-encoded processed frame // - detection_results: Object detection results // Example: Display the processed frame document.getElementById('video-frame').src = `data:image/jpeg;base64,${data.image}`; // Example: Display detection results displayDetectionResults(data.detection_results); }); ``` ### 2. Batch Recognition Progress As described in the Batch Recognition API section, WebSockets are also used to receive real-time progress updates during batch image processing: ```javascript // Listen for batch processing progress socket.on('batch_recognition_progress', (data) => { // Process progress updates }); // Listen for batch processing completion socket.on('batch_recognition_complete', (data) => { // Process completion event }); ``` ### WebSocket Events Reference | Event Name | Direction | Description | |------------|-----------|-------------| | `connect` | Client ← Server | Connection established | | `disconnect` | Client ← Server | Connection closed | | `subscribe` | Client → Server | Subscribe to RTMP stream results | | `result_update` | Client ← Server | Real-time RTMP stream processing results | | `batch_recognition_progress` | Client ← Server | Progress update for batch processing | | `batch_recognition_complete` | Client ← Server | Completion event for batch processing | ### Connection Management - WebSocket connection will automatically attempt to reconnect if disconnected - RTMP stream subscriptions need to be re-established after reconnection - WebSocket events for a disconnected client are discarded, not queued